PICマイコンと TM1637 で7セグLEDを光らす。

概要

TM1637 とPICを使って簡単に7セグLEDを光らすことができればいいなということで、この記事を作成しました。

結果的に光らせることができました。プログラムは記事の一番下に書いてます。

使用機器

  • PICマイコン PIC16F1827 (190円)
  • 7セグLEDドライバ TM1637 (830円 3個入り)

配線図(Fritzing)

汚いですけど、一応配線図です。

TM1637 ブレッドボードでの配線

TM1637 動作結果

※昔に作ったやつなので、記事に乗せている配線図や、プログラムとは使用しているピンの位置が違います。。。

プログラム( TM1637 制御)

今回は、クロック出力(CLK)にRA1ピン データ出力(DIO)にRA2ピンを使用。

ソースコードは、Githubにも公開しています。

レジスタの設定方法については、この記事で解説。

tm1637.h ヘッダー

#include <xc.h>
#include <stdint.h>

void start_segment();
void stop_segment();
void set_brigthness(uint8_t brightness, uint8_t on);
uint8_t write_byte(uint8_t b);
void set_segments(const uint8_t segments[], uint8_t length, uint8_t pos);
void clear_segment();
uint8_t encode_digit(uint8_t digit);

tm1637.c

マクロのDIO_PINの値とCLK_PINの値を変えると使用するピンを変更可能


#include "tm1637.h"
#include <xc.h>

#define COMM1 0x40 
#define COMM2 0xC0
#define COMM3 0x80

/** DATA PIN NUMBER */
#define DIO_PIN 0x04 //RA2
/** CLOCK PIN NUNBER */
#define CLK_PIN 0x02 //RA1

uint8_t m_brightness;

uint8_t segdata[] = { 
   0x3F, // 0
   0x06, // 1
   0x5B, // 2
   0x4F, // 3
   0x66, // 4
   0x6D, // 5
   0x7D, // 6
   0x07, // 7
   0x7F, // 8
   0x6F  // 9 
};

/** CLK_PIN set output mode*/
void CLK_SET_OUTPUT(){ TRISA &= ~CLK_PIN; }

/** CLK_PIN set high */
void CLK_SET_HIGH(){ LATA |= CLK_PIN; }
/** CLK_PIN set low */
void CLK_SET_LOW() { LATA &= ~CLK_PIN; }

/** DIO_PIN set output mode */
void DIO_SET_OUTPUT(){ TRISA &= ~DIO_PIN; }
/** DIO_PIN set input mode */
void DIO_SET_INPUT(){ TRISA |= DIO_PIN; }
/** DIO_PIN set high */
void DIO_SET_HIGH(){ LATA |= DIO_PIN; }
/** DIO_PIN set low*/
void DIO_SET_LOW(){ LATA &= ~DIO_PIN; }

void start_segment(void){    
    //DIO_PIN, CLK_PIN set output
    DIO_SET_OUTPUT();
    CLK_SET_OUTPUT();
    
    //DIO_PIN, CLK_PIN set high
    DIO_SET_HIGH();
    CLK_SET_HIGH();
    
    //DIO_PIN, CLK_PIN set low
    DIO_SET_LOW();
    CLK_SET_LOW();
}

void stop_segment(void){
    //DIO_PIN, CLK_PIN set output
    DIO_SET_OUTPUT();
    CLK_SET_OUTPUT();
    
    //DIO_PIN, CLK_PIN set low
    CLK_SET_LOW();
    DIO_SET_LOW();
    
    //DIO_PIN, CLK_PIN set high
    CLK_SET_HIGH();
    DIO_SET_HIGH();
}

uint8_t get_DIO_PIN_value(){
    if(DIO_PIN == 0x01){ return PORTAbits.RA0; }
    if(DIO_PIN == 0x02){ return PORTAbits.RA1; }
    if(DIO_PIN == 0x04){ return PORTAbits.RA2; }
    if(DIO_PIN == 0x08){ return PORTAbits.RA3; }
    if(DIO_PIN == 0x10){ return PORTAbits.RA4; }
    if(DIO_PIN == 0x20){ return PORTAbits.RA5; }
    if(DIO_PIN == 0x40){ return PORTAbits.RA6; }
    if(DIO_PIN == 0x80){ return PORTAbits.RA7; }
}

uint8_t write_byte(uint8_t b){
    uint8_t data = b;
    
    //CLK_PIN set output
    CLK_SET_OUTPUT();
    for(uint8_t i = 0; i < 8; i++){      
        //CLK_PIN set low
        CLK_SET_LOW();        
        
        if(data & 0x01){
            //DIO_PIN set high
            DIO_SET_HIGH();
        }else{
            //DIO_PIN set low     
            DIO_SET_LOW();
        }
        
        //CLK_PIN set high
        CLK_SET_HIGH();
        
        data = data >> 1;
    }
    
    //wait ACK
    //CLK_PIN set low
    //DIO_PIN set high
    CLK_SET_LOW();
    DIO_SET_HIGH();
    
    //CLK_PIN set high     
    CLK_SET_HIGH();
    
    //DIO_PIN set input
    DIO_SET_INPUT();
    
    uint8_t ack = get_DIO_PIN_value();
    if(ack == 0){
        //DIO_PIN set output
        DIO_SET_OUTPUT();
        
        //DIO_PIN set low
        DIO_SET_LOW();
    }
    
    //DIO_PIN set output
    DIO_SET_OUTPUT();
    
    return ack;
}

/**
 * 
 * @param brightness
 * @param on 0:light off, 1:light on
 */
void set_brigthness(uint8_t brightness, uint8_t on){
    if(on == 1){
        m_brightness = (brightness & 0x7 | 0x08);
    }else{
        m_brightness = (brightness & 0x7 | 0x00);
    }
}

/**
 * set number to TM1637
 * @param segments
 * @param length segments array length
 * @param pos 
 */
void set_segments(const uint8_t segments[], uint8_t length, uint8_t pos){
    //write COMM1
    start_segment();
    write_byte(COMM1);
    stop_segment();
    
    //write COMM2 + first digit address
    start_segment();
    write_byte(COMM2 + (pos & 0x03));
    
    //write the data bytes
    for(uint8_t k = 0; k < length; k++){
        write_byte(segments[k]);        
    }
    
    stop_segment();
    
    //write COMM3 + brigthness
    start_segment();
    write_byte(COMM3 + (m_brightness & 0x0f));    
    stop_segment();
}

/**
 * TM1637 segment set to 00:00
 */
void clear_segment(){
    uint8_t data[] = { 0, 0, 0, 0 };
	set_segments(data, 4, 0);
}

/**
 * digit to TM1637 number
 * @param digit
 * @return 
 */
uint8_t encode_digit(uint8_t digit){
    return segdata[digit & 0x0f];
}

プログラム(メイン)

main.c

#include "tm1637.h"
#include "mcc_generated_files/mcc.h"


void main(void)
{
    
    SYSTEM_Initialize();
    
    ANSELA = 0x00;
    TRISA = 0x00;
    LATA = 0x00;
    
    uint8_t data[] = {0xff, 0xff, 0xff, 0xff};
    
    clear_segment();
    
    data[0] = encode_digit(1);
    data[1] = encode_digit(9);
    data[2] = encode_digit(8);
    data[3] = encode_digit(4);
    
    
    set_brigthness(0x0f, 1);
    set_segments(data, 4, 0);
    
    uint8_t k = 0;
    
    
    while (1)
    {               
        for(uint8_t i = 0; i < 4; i++){
            data[i] = encode_digit(i + k);
        }
        
        set_segments(data, 4, 0);
        __delay_ms(1000);
        k++;
    }
}

コメントする