|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
相信大家刚学习单片机的时候都用过数码管,那时候的数码管都是用单片机的IO口直接驱动的,用软件进行动态刷新,但是这样控制数码管是很占用单片机外部资源的,单片机的外部资源也是有限的,不能全部IO口来进行数码管的驱动吧!!那有没有专门的驱动芯片驱动呢?答案是有的,他就是LED驱动芯片,这里就以天微电子TM1650来做讲解吧!
9 k" w/ [+ G3 ]4 F; _9 [/ ^( J6 B7 w0 K, W
首先TM1650是IIC通讯协议的,没错他只要两个单片机IO口就能控制4位数码管的显示,分别是SCL(时钟线)和SDA(数据线)进行数据的传输
( ]' H, n7 [/ s: \1 A+ B$ y![]()
& f/ Q1 o; Q7 g- Q# W* a; k
0 f0 q8 v& \8 D$ `7 V# P9 DIIC串口协议
* \0 i/ u0 s1 o2 r5 m# X开始信号:保持 SCL 为“1”电平,SDA 从“1”跳“0” ,认为是开始信号
& Y- B1 C3 O2 \" n9 X# z) V结束信号:保持 SCL 为“1”电平,SDA 从“0”跳“1” ,认为是结束信号
8 D7 X. }: @* P: `/ S应答:如果本次通讯正常,芯片在串行通讯的第 8 个时钟下降沿后,TM1650 主动把 SDA 拉低。直到检0 a- \& d: t+ W+ w0 K: E0 ]
测到 SCL 来了上升沿,SDA 释放为输入状态
4 q8 D. r; C; V6 v" y: W- k* v( ~7 C5 Y; o/ E/ a! b
& |! q. u3 ?- [# y9 e! Q( b% V* A
我这里用的是单片机硬件IIC时序,你也可以用软件来进行模拟时序2 m' G/ {( F& b) f! p* M& y. X4 ?; S: ^
以下是驱动程序:- #include "main.h"
- uint8_t code Num_Buff[16]={ //数码管共阴真值表0-F
- 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71
- };
- extern void Dis_IIC_Init(void);
- extern void Dis_Write_NumData(uint16_t NumDat);
- extern void DisPlay_ON(void);
- extern void DisPlay_OFF(void);
- extern void Dis_Write(uint8_t ADD,uint8_t Dat);
- extern void Dis_Write_ERRData(uint8_t ERR_Num);
- DisPlay_t DisPlay =
- {
- 0,
- 0,
- Dis_IIC_Init,
- Dis_Write_NumData,
- DisPlay_ON,
- DisPlay_OFF,
- Dis_Write,
- Dis_Write_ERRData
- };
- //硬件IIC初始化
- static void Dis_IIC_Init()
- {
- P_SW2 = 0xB0; //IIC引脚切换至P32,P33引脚及使能特殊功能寄存器(XFR)
- IP2 = 0x40; //设置优先级为较低级优先级,定时器0为最低级优先级,IIC优先级高于定时器0优先级
- IP2H = 0x00; //设置优先级为较低级优先级,定时器0为最低级优先级,IIC优先级高于定时器0优先级
- I2CCFG &= 0x00; //清零
- I2CCFG |= 0xC2; //使能IIC功能,主机模式,8分频,总线速度=FOSC/2/(分频系数*2+4)
- I2CMSCR &= 0x00; //清零
- I2CMSCR |= 0x80; //使能IIC主机模式中断
- }
- //起始信号
- static void IIC_Start()
- {
- DisPlay.IIC_Send_Time = TRUE;
- I2CMSCR |= 0x81;
- while(DisPlay.IIC_Send_Time);
- }
- //发送停止
- static void IIC_Stop()
- {
- DisPlay.IIC_Send_Time = TRUE;
- I2CMSCR |= 0x86;
- while(DisPlay.IIC_Send_Time);
- }
- //发送应答
- static void IIC_ACk()
- {
- DisPlay.IIC_Send_Time = TRUE;
- I2CMSCR |= 0x83;
- while(DisPlay.IIC_Send_Time);
- }
- //发送一个字节
- static void IIC_Write_Byt(uint8_t d)
- {
- I2CTXD = d;
- DisPlay.IIC_Send_Time = TRUE;
- I2CMSCR |= 0x82;
- while(DisPlay.IIC_Send_Time);
- }
- //发送数据操作
- static void Dis_Write(uint8_t ADD,uint8_t Dat)
- {
- IIC_Start();
- IIC_Write_Byt(ADD);
- IIC_ACk();
- IIC_Write_Byt(Dat);
- IIC_ACk();
- IIC_Stop();
- }
- static void DisPlay_ON()
- {
- Dis_Write(0x48,0x41); //0x41为四级亮度,8段码显示方式,开显示
- }
- static void DisPlay_OFF()
- {
- Dis_Write(0x48,0x40); //关显示
- }
- //数据显示处理函数
- static void Dis_Write_NumData(uint16_t NumDat)
- {
- // Dis_Write(0x48,0x41); //0x41为四级亮度,8段码显示方式,开显示
- Dis_Write(0x68,Num_Buff[NumDat/100%10]); //取出显示百位
- if(DisPlay.Therm_Fa == 0)
- {
- Dis_Write(0x6A,Num_Buff[NumDat/10%10]+0x80); //取出显示十位
- Dis_Write(0x6C,Num_Buff[NumDat%10]&0x7F); //取出显示个位
- }
- else
- {
- Dis_Write(0x6A,Num_Buff[NumDat/10%10]&0x7F); //取出显示十位
- Dis_Write(0x6C,Num_Buff[NumDat%10]+0x80); //取出显示个位
- }
- }
- static void Dis_Write_ERRData(uint8_t ERR_Num)
- {
- Dis_Write(0x68,Num_Buff[14]);
- Dis_Write(0x6A,Num_Buff[ERR_Num]&0x7F);
- Dis_Write(0x6C,0x00);
- }
- //I2C中断服务函数
- void IIC_interrupt() interrupt 24
- {
- if(I2CMSST & 0x40)
- {
- I2CMSST &= 0xBF; //清除中断标志位
- DisPlay.IIC_Send_Time = FALSE;
- I2CMSCR &= 0x80; //除了最高不变,其他位清零,为下次发送做准备
- }
- }- g' t; M/ @9 ~9 N! X+ R$ q6 v5 V! T
' L; g6 s: |8 u, ?: Z* w9 R+ O
' {& L6 N. {/ r3 a9 v |
|