5、数码管驱动使用

tech2023-02-17  92

一、判断现在手里头买的是共阴还是共阳数码管

我们可使用万用表进行最简单判断,将万用表调到二极管档,

(1)万用表笔随便一脚,假设红笔, 搭在数码管上任一脚 。黑笔在其它脚上扫过,如果不亮,有可能此管为共阴,可用2法再试。如有一段点亮。黑笔不动, 移动红笔,在其它脚测。如果其它脚 分别都 能点亮,则可以说明黑笔接的是公共脚 ,此管共阳。(指针 表的黑表笔是正电源)

(2)表笔更换一下,黑笔先搭一脚,扫红笔。如有一段点亮,红笔不动,扫黑笔。如各段分别点亮,则红笔所接为公共 ,此管共阴

二、段选与位选

多位一体数码管,内部的公告端是独立的,我们把公共端叫做位选线

负责显示什么数字的线全部都是连接在一起,我们把这个叫做段选线

三、现在使用大部分都直接使用驱动芯片了,所以我们重点来讲驱动芯片的使用

网上搜一搜 ,比如tm1650就是一个8*4驱动,可以驱动4位数码管,采用的IIC通讯

当时开发用的中微的芯片,所以在此我就拿中微的CMS1650来写,其实他跟TM1650都是一样的,数码管驱动芯片大同小异,掌握一款其他就都会了。

三、CMS1650

1、概述

方便使用,电路设计便捷,工作电压又低,堪称完美

2、管脚

管脚分布图DIG就是位选,其他就是段选

3、通讯协议

通讯协议采用的是IIC通讯协议。我们可以看看规格书,规格书我上传了。

(1)先来看看规格书写的协议的开始的信号与停止信号

启始信号,在SCL为高电平期间,SDA出现下降沿现象;

考虑代码整洁性,我们可以先进行宏定义

#define CLS_CMS_SCL   P0_4 = 0   //时钟拉低 #define SET_CMS_SCL   P0_4 = 1   //时钟拉高  #define SET_CMS_SDA   P0_5 = 1   //数据拉低 #define CLS_CMS_SDA   P0_5 = 0   //数据拉高

#define CLK           P0_4   #define SDA           P0_5  

#define SDA_OUT()     {P0TRIS |= 0x20;P0 |= 0x20; }  #define SDA_INT()     {P0TRIS &= 0xDF;P0UP |=0x20;}

void LED_Init(void) {   P0TRIS |= 0x10; //设置P04输出 SCL     P0 |= 0x10;     //输出高           P0TRIS |= 0x20; //设置P05输出 SDA     P0 |= 0x20;     //输出高 }

void CMS1650_Start(void) //SCL 为“1”,SDA 从“1”跳“0”,认为是开始信号 {      SDA_OUT();//设置/SCL、SDA 为输出脚     SET_CMS_SCL;     SET_CMS_SDA;     delay_us(5);     CLS_CMS_SDA;     delay_us(5);     CLS_CMS_SCL;//钳住I2C总线,准备发送或接收数据,(IIC规定只有在SCL为低电平期间,数据线上才允许高低变化,所以开始信号启动后,拉低SCL) }

void CMS1650_Stop(void) // SCL 为“1”电平,SDA 从“0”跳“1”,认为是结束信号 {      SDA_OUT();     SET_CMS_SCL;     CLS_CMS_SDA;     delay_us(5);     SET_CMS_SDA;     delay_us(5);//停止信号,就不用把SCL拉低 }

(2)应答信号

应答信号由接收设备产生,在SCL为高电平期间,接收设备将SDA拉低说明数据传输正确,产生应答。

所以我们代码应该这样写,传输完数据后,得先释放数据线;再将SCL拉高,判断低电平是否到来。

//等待从机应答信号到来 //返回值:1,接收应答失败 //              0,接收应答成功 u8 CMS1650_Wait_Ack(void) {     u16 time = 0;      SDA_INT();//将SDA设置为上拉输入 ,主机释放数据总线(总线在空闲状态为高电平)等待从机产生应答信号            SET_CMS_SCL;delay_us(1);  //   SCL拉高     while(SDA == 1)//在while循环延时这段时间内,看丛机是否有产生应答信号,有的话SDA就=0,跳出循环     {         time++;         if(time>255)//从机没应答,传输失败         {             CMS1650_Stop();             return 1; //有必要的话显示或者产生个中断说明传输失败,跳出循环。注:return可以可以跳出while循环

                                                                      continue:不跳出当前循环,结束本次循环(结束当前循环),执行下一轮循环                                                                       break:跳出当前循环,结束该循环执行         }     }     CLS_CMS_SCL;     return 0;   }

(3)写入数据

void CMS1650_SendByte(u8 txd) {   u8 t = 0;    //   SDA_OUT(); //  CLS_CMS_SCL;//拉低时钟开始数据传输    ,开始信号已经拉低SCL了,这里可以不用写了    for(t=0;t<8;t++)    {                if((txd&0x80)>>7)                 SET_CMS_SDA;             else                 CLS_CMS_SDA;             txd<<=1;              delay_us(5);              SET_CMS_SCL;//数据发送完,拉高时钟             delay_us(5);              CLS_CMS_SCL;//拉低时钟开始数据传输                 delay_us(5);      } }

对于数据的写入为啥要SCL 从“0”跳到“1”,再从“1”跳到“0”这么写,我们来看看接收方是怎么接收就一目了然了;

从设备收数据:主设备发送了开始位后,把clk拉低,只有clk拉低,sda才可以做高低变化; 当clk被拉高时,(0->1)从设备就会去读取sda的高低电平值;clk再次被拉低时,(1->0)从设备认为此位已读取完毕,认为是有效位,等待clk再次拉高,读取下一位。

(4)一个完整的写显示时序

首先得先写入数据命令,然后开显示确定显示的亮度

8段显示的话就是小数点也显示出来

再来确定显存地址(确定位选地址)

最后

 

void main() {

  u8 t = 0;

    LED_Init(); //SCL SDA 设置为输出

   delay_ms(300);    //延时一段时间,否则开显示无响应

   CMS1650_SendByte(0x48);

   CMS1650_Wait_Ack();//等待应答

 //这里应答处理,看大家要做什么处理,这里应答处理我就先不作处理

   CMS1650_SendByte(0x30);//开显示:3级亮度

    CMS1650_Wait_Ack();//等待应答         CMS1650_Stop();

    CMS1650_WriteByte(0x6E,0x7f);     CMS1650_WriteByte(0x6C,0x7f);     CMS1650_WriteByte(0x6A,0x7f);     CMS1650_WriteByte(0x68,0x7f);//开机8888

 //单片机上电数码管显示8.8.8.8.

}

全部代码

void LED_Init(void) {   P0TRIS |= 0x10; //设置P04输出 SCL     P0 |= 0x10;     //输出高           P0TRIS |= 0x20; //设置P05输出 SDA     P0 |= 0x20;     //输出高 } void CMS1650_Start(void) //SCL 为“1”,SDA 从“1”跳“0”,认为是开始信号 {      SDA_OUT();     SET_CMS_SCL;     SET_CMS_SDA;     delay_us(5);     CLS_CMS_SDA;     delay_us(5);     CLS_CMS_SCL;//钳住I2C总线,准备发送或接收数据 } void CMS1650_Stop(void) // SCL 为“1”电平,SDA 从“0”跳“1”,认为是结束信号 {      SDA_OUT();     SET_CMS_SCL;     CLS_CMS_SDA;     delay_us(5);     SET_CMS_SDA;     delay_us(5); }

//等待从机应答信号到来 //返回值:1,接收应答失败 //        0,接收应答成功 u8 CMS1650_Wait_Ack(void) {     u16 time = 0;     SDA_OUT();     SET_CMS_SDA;delay_us(1);//主机释放数据总线,(总线在空闲状态为高电平)等待从机产生应答信号            SET_CMS_SCL;delay_us(1);          SDA_INT();//将SDA设置为上拉输入     while(SDA == 1)//在while循环延时这段时间内,看丛机是否有产生应答信号,有的话SDA就=0,跳出循环     {         time++;         if(time>255)//从机没应答,传输失败         {             CMS1650_Stop();             return 1; //有必要的话显示或者产生个中断说明传输失败         }     }     CLS_CMS_SCL;     return 0;   }

void CMS1650_SendByte(u8 txd) {   u8 t = 0;    //    SDA_OUT(); //  CLS_CMS_SCL;//拉低时钟开始数据传输    ,开始信号已经拉低SCL了,这里可以不用写了    for(t=0;t<8;t++)    {                if((txd&0x80)>>7)                 SET_CMS_SDA;             else                 CLS_CMS_SDA;             txd<<=1;              delay_us(5);              SET_CMS_SCL;//数据发送完,拉高时钟             delay_us(5);             CLS_CMS_SCL;//拉低时钟开始数据传输                 delay_us(5);      } }

void CMS1650_WriteByte(u8 Addr,u8 Data) {     CMS1650_Start();     CMS1650_SendByte(Addr);     CMS1650_Wait_Ack();//等待应答     CMS1650_SendByte(Data);     CMS1650_Wait_Ack();//等待应答         CMS1650_Stop(); }

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

最新回复(0)