概要
TM1637 とPICを使って簡単に7セグLEDを光らすことができればいいなということで、この記事を作成しました。
結果的に光らせることができました。プログラムは記事の一番下に書いてます。
使用機器
- PICマイコン PIC16F1827 (190円)
- 7セグLEDドライバ TM1637 (830円 3個入り)
配線図(Fritzing)
汚いですけど、一応配線図です。
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++;
}
}