目的:
通过数码管案例,熟悉TM1650芯片的使用方法,加深树莓派的IIC接口使用方法。
目录
1、基础知识
1.1、LED数码管基础知识
LED数码管(LED Segment Displays)由多个发光二极管封装在一起组成“8”字型的器件,引线已在内部连接完成,只需引出它们的各个笔划,公共电极。数码管实际上是由七个发光管组成8字形构成的,加上小数点就是8个。这些段分别由字母a,b,c,d,e,f,g,dp来表示。
LED数码管根据LED的接法不同分为共阴和共阳两类,比如我们使用的共阴数码管原理图如下:
图1-1 共阴极数码管原理图
另外的一种共阳极数码管原理图如图1-2 所示。
图1-2 共阳极数码管原理图
无论是共阴极还是共阳极数码管,都拥有段引脚和位引脚,其中段引脚用于设定数码管要显示的内容,位引脚用于选择需要显示哪一位数字。如果要在不同的位显示不同的数字,则每次只能有一个位被选中,并在段引脚中送入相应的数据。那我们现在看到的数码管是如何做到在同一时间不同位显示不同的数字的呢?
这就用到了数码管动态扫描显示的技术,该技术利用了人类视觉系统的暂留性,实际程序显示的时候,是先显示其中一位,然后关闭这位的显示,但由于刷新的频率太高,即使某位的显示关闭了,显示的图像还会在视觉系统中短暂停留,所以,如果数码管轮流以超过50Hz的刷新率显示,人眼是分辨不出来某一位数码管关闭了,这样看起来就像所有的数码管都在显示不同的内容。
1.2、TM1650芯片介绍
TM1650 是一种带键盘扫描接口的 LED(发光二极管显示器)驱动控制专用电路。内部集成有 MCU,输入输出控制数字接口、数据锁存器、LED 驱动、键盘扫描、辉度调节等电路。
本次案例使用的是TM1650的数码管驱动功能,原理图如下:
图1-3 TM1650典型电路
TM1650可以使用I2C的方式通信,本次案例的控制命令一共用到两条,一是进入模式设置,二是通过下表设定TM1650的模式,并注意要打开显示。
a、数据命令设置
B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 | 说明 |
---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 模式命令 |
0 | 1 | 0 | 0 | 1 | x | x | 1 | 读按键数据命令 |
b、显示命令设置
MSB | LSB | ||||||||
---|---|---|---|---|---|---|---|---|---|
B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 | 功能 | 说明 |
无 关 项 , 填 0 | 0 | 0 | 0 | 无关项, 填0 | 辉度设置 | 8级亮度 | |||
0 | 0 | 1 | 1级亮度 | ||||||
0 | 1 | 0 | 2级亮度 | ||||||
0 | 1 | 1 | 3级亮度 | ||||||
1 | 0 | 0 | 4级亮度 | ||||||
1 | 0 | 1 | 5级亮度 | ||||||
1 | 1 | 0 | 6级亮度 | ||||||
1 | 1 | 1 | 7级亮度 | ||||||
0 | 7/8段显示控制位 | 8段显示方式 | |||||||
1 | 7段显示方式 | ||||||||
0 | 开启/关闭显示位 | 关显示 | |||||||
1 | 开显示 |
c、显存地址
在显示的时候,往相应的显存地址写入数据,数据格式参考上表,若要数码管的其中一段亮,就给这段置1.
1.3、树莓派上IIC的接口使用方法
参考官方的链接:I2C Library | Wiring Pi
1.3.1、头文件
使用IIC接口的之前需要添加头文件
#include <wiringPiI2C.h>
1.3.2、初始化设备ID的函数
int wiringPiI2CSetup (int devId) ;
返回设备节点
1.3.3、读取设备节点值的函数
int wiringPiI2CRead (int fd) ;
1.3.4、给设备节点写值的函数
int wiringPiI2CWrite (int fd, int data) ;
1.3.5、给设备节点的某一个寄存器写值
写1个字节
int wiringPiI2CWriteReg8 (int fd, int reg, int data) ;
写2个字节
int wiringPiI2CWriteReg16 (int fd, int reg, int data) ;
1.3.6、读取设备节点某一个寄存器的值
读取一个字节数据
int wiringPiI2CReadReg8 (int fd, int reg) ;
读取两个字节数据
int wiringPiI2CReadReg16 (int fd, int reg) ;
2、功能实现
通过树莓派实现数码管上的数字跳动。
2.1、原理图
图2-1 数码管原理图
通过接线 数码管接在了树莓派的I2C-1端口上。
2.2、代码实现
通过IIC工具的到TM1650的设备地址为0x24;0x34,0x35,0x36,0x37分别对应第1到4位数码管显示寄存器的地址。因此,编写代码的时候,首先往设备地址0x24中写入相应命令,然后往数码管显示寄存器写入要显示的内容即可。
i2cdetect -y 1
图2-2 TM1650IIC地址
2.2.1、头文件实现
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <wiringPiI2C.h>
2.2.2、宏定义
#define u8 unsigned char
#define uint16_t unsigned short
#define u32 unsigned int
//# TM1650 分开的地址,分别对应一个指令地址和4个4位数字的显示地址
#define COMMAND_I2C_ADDRESS 0x24
#define DISPLAY_I2C_ADDRESS_1 0x34
#define DISPLAY_I2C_ADDRESS_2 0x35
#define DISPLAY_I2C_ADDRESS_3 0x36
#define DISPLAY_I2C_ADDRESS_4 0x37
#define TIM_COMMAND 0x24 //数据命令
#define TIM_START 0x01 //默认开启显示位
#define data_dp 0x80 //小数点的段码
#define data_null 0x00 //不显示
#define data_neg 0x40 //负号的段码
2.2.3、TM1650初始化
int tm1650init(void)
{
wiringPiSetup();
fd = wiringPiI2CSetup (COMMAND_I2C_ADDRESS);
if(fd < 0)
{
printf("COMMAND_I2C_ADDRESS IIC初始化失败\r\n");
return fd;
}
fd1 = wiringPiI2CSetup (DISPLAY_I2C_ADDRESS_1);
if(fd1 < 0)
{
printf("DISPLAY_I2C_ADDRESS_1 IIC初始化失败\r\n");
return fd1;
}
fd2 = wiringPiI2CSetup (DISPLAY_I2C_ADDRESS_2);
if(fd2 < 0)
{
printf("DISPLAY_I2C_ADDRESS_2 IIC初始化失败\r\n");
return fd2;
}
fd3 = wiringPiI2CSetup (DISPLAY_I2C_ADDRESS_3);
if(fd3 < 0)
{
printf("DISPLAY_I2C_ADDRESS_3 IIC初始化失败\r\n");
return fd3;
}
fd4 = wiringPiI2CSetup (DISPLAY_I2C_ADDRESS_4);
if(fd4 < 0)
{
printf("DISPLAY_I2C_ADDRESS_4 IIC初始化失败\r\n");
return fd4;
}
wiringPiI2CWrite (fd,display_brightness[6]);
wiringPiI2CWrite (fd1,data_null);
wiringPiI2CWrite (fd2,data_null);
wiringPiI2CWrite (fd3,data_null);
wiringPiI2CWrite (fd4,data_null);
return 0;
}
2.2.4、数码管显示函数
int showDigit(u8 d1, u8 d2,u8 d3, u8 d4)
{
wiringPiI2CWrite (fd1,digitCode[d1]);
wiringPiI2CWrite (fd2,digitCode[d2]);
wiringPiI2CWrite (fd3,digitCode[d3]);
wiringPiI2CWrite (fd4,digitCode[d4]);
return 0;
}
2.2.5、主函数
int main(void)
{
u8 d1,d2,d3,d4;
u8 ret;
u32 i=0;
ret = tm1650init();
if(ret != 0)
{
printf("tm1650init init error \r\n");
return -1;
}
for(;;)
{
d4 = i % 10;
d3 = (i/10) % 10;
d2 = (i/100) % 10;
d1 = (i/1000) % 10;
showDigit(d1, d2, d3, d4);
delay(1000);
i += 1;
}
return 0;
}
2.3、生成执行程序
编译的时候需要添加wiringPi库,编译步骤如下所示:
gcc -Wall -o tm1650 tm1650.c -lwiringPi
图2-3 编译过程
2.4、功能实现
执行程序
./tm1650
实现数码管的数字跳变。
图2-4-1 数码管数字变化