PIC18F46K22でSPIで7セグLEDを4桁ドライブする(C言語)(timer0使用)

icon 項目のみ表示/展開表示の切り替え

概要

PIC18F46K22 のSPIに74HC595経由で7セグメントLED4桁をドライブする。
回路はSPIで7セグLEDを4桁ドライブする回路のとおりである。
本プログラムはダイナミック点灯のタイミングはtimer0を使用する。
1ms置きに割り込みを掛け桁を切り替えて表示する。

プログラムの説明

disp_7seg関数はunsigned int型の整数を4桁LEDに10進数として表示データを作成する。
割り込み発生時にこのデータを順次出力してLEDに表示する。

ソースファイル

以下のファイルで構成されている
7seg4c3.c ・・・ メインプログラムとLED制御プログラム

ソースファイルのダウンロード 7seg4c3.zip


/*
 * 7SEG LED4桁 ハードウェアSPIダイナミックスキャンサンプル(timer0使用) Version 1.00
 * File:        7seg4c3c.c
 * Target:      PIC18F46K22 64MHz
 * コンパイラ:   Microchip MPLAB XC8 C Compiler V1.20
 * 書き込み:     PICKit 3
 * リリース:     2014/02/07 19:20
 * MSPP2モジュールでSPIのデータを作成 74HC595に接続されたLEDに0000から9999まで1ずつカウントしながら表示する。表示タイミングはtimer0による割り込みを使用
 * 接続
 *   SCK2(RD0),SDO2(RD4),SS2(RD3)
 * LEDのデータフォーマット
 *   MSB xxxxdddd LSB
 *   xxxxは各ビットが桁位置に対応(Lで点灯)
 *   ddddは桁データ
*/

#include <p18f46k22.h>
#include <plib\delays.h>
#include <plib\spi.h>

#pragma config  FOSC = HSHP,PRICLKEN=ON,PLLCFG=ON,WDTEN=OFF,LVP=OFF

#define SCK PORTDbits.RD0
#define SS  PORTDbits.RD3
#define SDO PORTDbits.RD4

char SPI2rw(char w);            //  SPI2入出力
void interrupt isr(void);       //  1ms置きの割り込み処理ルーチン
void disp_7seg(unsigned w);    //  引数Wを10進数とみなして7SEG表示データを設定
void disp_7seg_hex(unsigned w);//  引数Wを16進数とみなして7SEG表示データを設定

unsigned char disp7seg_data[4];  // 表示データ4桁分
unsigned char disp7seg_count=0;  // 表示桁位置

void main(void){
    ANSELDbits.ANSD0=0; //  SCK2
    ANSELDbits.ANSD3=0; //  SS2
    ANSELDbits.ANSD4=0; //  SDO2
    SS=0;
    SCK=0;
    SDO=0;
    TRISDbits.RD3=0;
    TRISDbits.RD0=0;
    TRISDbits.RD4=0;

    OpenSPI2(SPI_FOSC_16,MODE_11,SMPMID);
    SPI2rw(0xff);   // LED消灯
//  1ms周期に設定
    OpenTimer0(TIMER_INT_ON & T0_8BIT & T0_SOURCE_INT & T0_PS_1_128);
    WriteTimer0(131);

    INTCONbits.TMR0IE=1;
    INTCONbits.GIE=1;

    for(;;)
       for(unsigned n=0;n<10000;n++){
            disp_7seg(n);
            Delay10KTCYx( 250); // 64MHz/4*0.16秒/10000
        }
}

//  1ms置きの割り込み処理ルーチン

void interrupt isr(void){
    INTCONbits.TMR0IF=0;

    if(disp7seg_count>3)
        disp7seg_count=0;

    SPI2rw(disp7seg_data[disp7seg_count]);
    ++disp7seg_count;
    WriteTimer0(131);
}

//  SPI2入出力

char SPI2rw(char w){
    SS=0;
    SSP2BUF=w;
    while(!SSP2STATbits.BF);
    char r=SSP2BUF;
    SS=1;
    return r;
}

//  引数Wを10進数とみなして7SEG表示データを設定

void disp_7seg(unsigned w){
    unsigned d;
    d=w % 10;
    disp7seg_data[3]=0xe0+d;   //  1桁目

    d=(w/10) % 10;
    disp7seg_data[2]=0xd0+d;   //  2桁目

    d=(w/100) % 10;
    disp7seg_data[1]=0xb0+d;   //  3桁目

    d=(w/1000) % 10;
    disp7seg_data[0]=0x70+d;   //  4桁目
}

//  引数Wを16進数とみなして7SEG表示データを設定

void disp_7_hex(unsigned w){
    unsigned d;
    d=w & 0x0f;
    disp7seg_data[3]=0xe0+d;   //  1桁目

    d=(w>>4) & 0xf;
    disp7seg_data[2]=0xd0+d;   //  2桁目

    d=(w>>8) & 0xf;
    disp7seg_data[1]=0xb0+d;   //  3桁目

    d=(w>>12) & 0xf;
    disp7seg_data[0]=0x70+d;   //  4桁目
}