我们先来看下数码管的实物图
数码管由四个引脚:CLK,DIO,VCC,GND
VCC接5V GND接GND CLK和DIO接GPIO。
实现原理: https://blog.csdn.net/q1241580040/article/details/45815245
数码管显示原理:https://www.cnblogs.com/yuwl26/p/3307337.html
数码管相对于之前的LED,按钮之类要复杂,想要了解详情的可以看以上两个链接。
我就简单的介绍下数码管原理:通过CLK DIO 两个引脚的高低电平变化来写入数据。
数码管接收到开始信号后 可以写入数据 接收到停止信号后结束写入。
数码管分两种:共阴极 和 共阳极
数码管上的每个数字都由七条短杠 和 一个小数点组成,共阴极的数码管 当短杠接收到高电平时会通电发光,供阳极则为低电平通电发光。
这样说不是很好理解 我就举个例子,比方说我们想让共阴极的数码管显示数字 5,那就要让afgcd 这五个短杠 为高电平1,那个abcdefgD(D表示小数点)为 10110110,这里的数据写入格式为 Dgfedcba ,即01101101,转换为十六进制为 0x6d
unsigned char code table[]={//共阴极0~f数码管编码
0x3f,0x06,0x5b,0x4f, //0~3
0x66,0x6d,0x7d,0x07, //4~7
0x7f,0x6f,0x77,0x7c, //8~b
0x39,0x5e,0x79,0x71 //c~f
};
除了显示数字字母 数码管还有一些固定的命令
0xc0~0xc3 表示数码管上四个数字的地址
代码
#include
#include
#include
#include
#include
#include
#include
#define CLK 27
#define DIO 22
//共阴极0~f数码管编码
char segdata[]={
0x3f,0x06,0x5b,0x4f, //0~3
0x66,0x6d,0x7d,0x07, //4~7
0x7f,0x6f,0x77,0x7c, //8~b
0x39,0x5e,0x79,0x71, //c~f
0x00 //不显示
};
//共阴极0~9带小数点的数码管编码
char segdatadp[]={
0xbf,0x86,0xdb,
0xcf,0xe6,0xed,
0xfd,0x87,0xff,0xef
};
//初始化wiringPi 使用BCM编码
void tm1637_init()
{
if(-1==wiringPiSetupGpio())
{
exit(-1);
}
pinMode(CLK,OUTPUT);
pinMode(DIO,OUTPUT);
}
//当CLK高电平时,DIO由高变低则代表开始信号
void tm1637_start()
{
digitalWrite(CLK,1);
usleep(140);
digitalWrite(DIO,1);
usleep(140);
digitalWrite(DIO,0);
usleep(140);
digitalWrite(CLK,0);
usleep(140);
}
//当CLK高电平时,DIO由低变高则代表停止信号
void tm1637_stop()
{
digitalWrite(CLK,0);
usleep(140);
digitalWrite(DIO,0);
usleep(140);
digitalWrite(CLK,1);
usleep(140);
digitalWrite(DIO,1);
usleep(140);
}
void write_bit(char bit)
{
digitalWrite(CLK,0);
usleep(140);
if(bit){
digitalWrite(DIO,1);
}else{
digitalWrite(DIO,0);
}
usleep(140);
digitalWrite(CLK,1);
usleep(140);
}
void write_byte(char data)
{
char i = 0;
for(i=0;i<8;i++)
{
write_bit((data>>i)&0x01);
}
digitalWrite(CLK,0);
usleep(140);
digitalWrite(DIO,1);
usleep(140);
digitalWrite(CLK,1);
usleep(140);
pinMode(DIO,INPUT);
while(digitalRead(DIO));
pinMode(DIO,OUTPUT);
}
void write_command(char cmd)
{
tm1637_start();
write_byte(cmd);
tm1637_stop();
}
void write_data(char addr,char data)
{
tm1637_start();
write_byte(addr);
write_byte(data);
tm1637_stop();
}
void number_display(int h_shi,int h_ge,int m_shi,int m_ge)
{
write_command(0x40);//写数据
write_command(0x44);//固定地址
write_data(0xc0,segdata[h_shi]);//写入第一个数码管
write_data(0xc1,segdata[h_ge]);
write_data(0xc2,segdata[m_shi]);
write_data(0xc3,segdata[m_ge]);
write_command(0x88);//显示开
}
void time_display(int h_shi,int h_ge,int m_shi,int m_ge,int f_dp)
{
write_command(0x40);//写数据
write_command(0x44);//固定地址
write_data(0xc0,segdata[h_shi]);//写入第一个数码管
if(f_dp)
{
write_data(0xc1,segdata[h_ge]);
}else{
write_data(0xc1,segdatadp[h_ge]);
}
write_data(0xc2,segdata[m_shi]);
write_data(0xc3,segdata[m_ge]);
write_command(0x88);//显示开
}
//sigint信号处理函数 退出并关闭数码管
void handler(int signo)
{
number_display(16,16,16,16);
exit(-1);
}
int main()
{
char FLAGDP = 1;
signal(SIGINT,handler);
tm1637_init();
char i = 0;
#if 0
while(1)
{
for(i=0;i<10;i++)
{
number_display(i,i,i,i);
sleep(1);
}
}
#endif
while(1)
{
FLAGDP^=1;
time_t t = time(NULL);
struct tm* _mt = gmtime(&t);
int h_s=0,h_g=0,m_s=0,m_g=0;
h_s = (_mt->tm_hour+8)/10;//时区+8
h_g = (_mt->tm_hour+8)%10;
m_s = _mt->tm_min/10;
m_g = _mt->tm_min%10;
time_display(h_s,h_g,m_s,m_g,FLAGDP);
sleep(1);
}
return 0;
}