本期将引见一款TM1637驱动的四位数码管,经过软件模仿时序的措施中止I2C通讯完成数码管的显现功用。 一、IIC通讯 I2C(IIC,Inter-Integrated Circuit),两线式串行总线,由PHILIPS公司开发用于衔接微控制器及其外围设备。它是由数据线SDA和时钟SCL构成的串行总线,可发送和接纳数据。在CPU与被控IC之间、IC与IC之间中止双向传送,高速IIC总线普通可达400kbps以上。IIC是半双工通讯方式。 I2C通讯 I2C总线的通讯过程主要包含三个主要阶段:起始阶段、数据传输阶段和终止阶段。 1.起始阶段: 闲暇状态:I2C总线总线的SDA和SCL两条信号线同时处于高电平常,规则为总线的闲暇状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。 开端信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。 2.数据传输阶段 数据传输:在I2C总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在SCL串行时钟的配合下,在SDA上逐位地串行传送每一位数据。数据位的传输是边沿触发。I2C总线中止数据传送时,时钟信号为高电平期间,数据线上的数据必须坚持稳定,只需在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变更。 应对信号ACK:发送器每发送一个字节,就在时钟脉冲9期间释放数据线,由接纳器反响一个应对信号。应对信号为低电平常,规则为有效应对位(ACK简称应对位),表示接纳器曾经胜利地接纳了该字节;应对信号为高电平常,规则为非应对位(NACK),普通表示接纳器接纳该字节没有胜利。 3.终止阶段 中止信号:当SCL为高期间,SDA由低到高的跳变;中止信号也是一种电平跳变时序信号,而不是一个电平信号。 二、TM1637驱动电路引见 TM1637采用功率CMOS工艺,显现方式(8段×6位),支持共阳数码管输出,键扫描(8×2bit),增强型抗干扰按键辨认电路,辉度调理电路(占空比8级可调),两线串行接口(CLK,DIO),振荡方式:内置RC振荡(450Khz+-5%),内置上电复位电路,内置自动消隐电路。 显现寄存器地址和显现方式 该寄存器存储经过串行接口从外部器件传送到TM1637 的数据,地址00H-05H共6个字节单元,分别与芯片SGE和GRID管脚所接的LED灯对应,分配如下图:写LED显现数据的时分,依照从显现地址从低位到高位,从数据字节的低位到高位操作。 接口阐明 微处置器的数据经过两线总线接口和 TM1637 通讯,在输入数据时当 CLK 是高电平常,DIO 上的信号必须坚持不变;只需 CLK 上的时钟信号为低电平常,DIO 上的信号才干改动。数据输入的开端条件是 CLK为高电平常,DIO 由高变低;终了条件是 CLK 为高时,DIO 由低电平变为高电平。 TM1637 的数据传输带有应对信号 ACK,当传输数据正确时,会在第八个时钟的降落沿,芯片内部会产生一个应对信号 ACK 将 DIO 管脚拉低,在第九个时钟终了之后释放 DIO 口线。 1.指令数据传输过程如下图(读按键数据时序) Command:读按键指令;S0、S1、S2、K1、K2 组成按键信息编码,S0、S1、S2 为 SGn 的编码,K1、K2 为 K1 和 K2 键的编码,读按键时,时钟频率应小于 250K,先读低位,后读高位。在数码管显现这里未用到读数据功用,这里暂时不作细致引见。 2.写SRAM 数据地址自动加1 方式 Command1:设置数据 Command2:设置地址 Data1~N:传输显现数据 Command3:控制显现 3.写 SRAM 数据固定地址方式 Command1:设置数据 Command2:设置地址 Data1~N:传输显现数据 Command3:控制显现 数据指令 指令用来设置显现方式和LED 驱动器的状态。 在CLK降落沿后由DIO输入的第一个字节作为一条指令。经过译码,取最高B7、B6两位比特位以区别不同的指令。 B7 B6 指令 0 1 数据命令设置 1 0 显现控制命令设置 1 1 地址命令设置 1)数据命令设置 该指令用来设置数据写和读,B1和B0位不允许设置01或11。 2)地址命令设设置 该指令用来设置显现寄存器的地址;假如地址设为0C6H 或更高,数据被疏忽,直到有效地址被设定;上电时,地址默许设为00H。 3)显现控制 将数据写0x8f,翻开显现开关,数码管显现数据 三、数码管模块原理图 数码管按段数可分为七段数码管和八段数码管,八段数码管比七段数码管多一个发光二极管单元(多一个小数点显现);按能显现多少个“8”可分为1位、2位、3位、4位、5位、6位、7位等数码管; 按发光二极管单元衔接方式可分为共阳极数码管和共阴极数码管。共阳数码管是指将一切发光二极管的阳极接到一同构成公共阳极(COM)的数码管,共阳数码管在应用时应将公共极COM接到+5V,当某一字段发光二极管的阴极为低电平常,相应字段就点亮,当某一字段的阴极为高电平常,相应字段就不亮。共阴数码管是指将一切发光二极管的阴极接到一同构成公共阴极(COM)的数码管,共阴数码管在应用时应将公共极COM接到地线GND上,当某一字段发光二极管的阳极为高电平常,相应字段就点亮,当某一字段的阳极为低电平常,相应字段就不亮。 四、程序设计一 依据TM1637通讯时序图能够看出要完成数码管显现能够分红4部分,分别为数据命令设置、地址命令设置、数据显现、显现控制。每个命令的设置都有起始、数据传输和终止三个过程。 1.数据命令设置 //开端信号 TM1637_Start(); //数据传输 TM1637_WriteByte(0x44);//0x44固定方式有利于控制显现位,,0x40则采用显现地址自加方式 TM1637_Ack(); //中止信号 TM1637_Stop(); 2.地址命令设置及数据显现 //开端信号 TM1637_Start(); //数据传输 TM1637_WriteByte(0xC0+p);//0X00地址开端显现 TM1637_Ack(); TM1637_WriteByte(NumDis[ch]);//显现数据 TM1637_Ack(); //中止信号 TM1637_Stop(); 3.显现控制 //开端信号 TM1637_Start(); //数据传输 TM1637_WriteByte(0x8f);//显现开启 TM1637_Ack(); //中止信号 TM1637_Stop(); 细致代码: 在"driver_delay.h"文件中定义了 #define TM1637_CLK_Low GPIO_ResetBits(GPIOB,GPIO_Pin_10) #define TM1637_CLK_High GPIO_SetBits(GPIOB,GPIO_Pin_10) #define TM1637_DIO_Low GPIO_ResetBits(GPIOB,GPIO_Pin_11) #define TM1637_DIO_High GPIO_SetBits(GPIOB,GPIO_Pin_11) #define TM1637_DIO_IN GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11) //单个数码管数组显现0123456789 unsigned charNumDis[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0X6F};//0123456789 //开端信号;数据输入的开端条件是CLK为高电平常,DIO 由高变低 void TM1637_Start(void) { TM1637_CLK_High; TM1637_DIO_High; delay_us(2); TM1637_DIO_Low; } //应对信号;当传输数据正确时,会在第八个时钟的降落沿,芯片内部会产生一个应对信号ACK 将DIO 管脚拉低,在第九个时钟终了之后释放DIO 口线 void TM1637_Ack(void) { TM1637_CLK_Low; delay_us(5); while(TM1637_DIO_IN);//读取DIO口的状态,0为有应对信号 TM1637_CLK_High; delay_us(2); TM1637_CLK_Low; } //中止信号;终了条件是CLK 为高时,DIO 由低电平变为高电平 void TM1637_Stop(void) { TM1637_CLK_Low; delay_us(2); TM1637_DIO_Low; delay_us(2); TM1637_CLK_High; delay_us(2); TM1637_DIO_High; } //写数据 void TM1637_WriteByte(unsigned charoneByte) { unsigned int i; //发送8位的数据 for(i=0;i<8;i++) { TM1637_CLK_Low; //从最低位开端发送 if(oneByte&0x01) { TM1637_DIO_High; } else { TM1637_DIO_Low; } delay_us(3); oneByte=oneByte>>1;//右移一位 TM1637_CLK_High; delay_us(3); } } //初始值显现0000 void TM1637_Display(void) { //数据命令设置 TM1637_Start(); TM1637_WriteByte(0x40);//0x40则采用显现地址自加1方式 TM1637_Ack(); TM1637_Stop(); //地址设置 TM1637_Start(); TM1637_WriteByte(0xC0);//0X00地址开端显现 TM1637_Ack(); //数据显现 TM1637_WriteByte(0x3f);//显现0 TM1637_Ack(); TM1637_WriteByte(0x3f);//显现0 TM1637_Ack(); TM1637_WriteByte(0x3f);//显现0 TM1637_Ack(); TM1637_WriteByte(0x3f);//显现0 TM1637_Ack(); TM1637_Stop(); //显现控制 TM1637_Start(); TM1637_WriteByte(0x8f);//开启显现 TM1637_Ack(); TM1637_Stop(); } //显现变量值 void TM1637_DisplayChar(unsigned intch,unsigned int p) { if(ch>10)ch=0;//避免数组越界 //数据命令设置 TM1637_Start(); TM1637_WriteByte(0x44);//0x44固定方式有利于控制显现位,0x40则采用显现地址自加方式这里不运用 TM1637_Ack(); TM1637_Stop(); //地址设置 TM1637_Start(); TM1637_WriteByte(0xC0+p);//0X00地址开端显现 TM1637_Ack(); //数据显现 TM1637_WriteByte(NumDis[ch]);//显现 TM1637_Ack(); TM1637_Stop(); //显现控制 TM1637_Start(); TM1637_WriteByte(0x8f); TM1637_Ack(); TM1637_Stop(); } //GPIO初始化 void TM1637_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10|GPIO_Pin_11; GPIO_InitStructure.GPIO_Mode =GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); } 主函数代码 int main(void) { inti,j; TM1637_Init(); TM1637_Display();//显现初始值0000 delay_ms(5000);//延时5s while(1) { //每个数码管依次循环加到9 for(i=3;i>=0;i--) { for(j=0;j<10;j++) { delay_ms(300); TM1637_DisplayChar(j,i); } if(i==0)i=4; } } } 效果显现:初始值显现0000,持续5S后,从右到左,每个数码管依次循环加到9 五、程序设计二 Mixly依据这个流程,也能够很方便的写出对数码管模块的显现控制 子函数模块 转译的代码: //开端信号 void start() { pinMode(2, OUTPUT); digitalWrite(3,HIGH); digitalWrite(2,HIGH); delayMicroseconds(2); digitalWrite(2,LOW); } //应对信号 void ack() { digitalWrite(3,LOW); delayMicroseconds(5); if(digitalRead(2) == 1) { }else { digitalWrite(3,HIGH); delayMicroseconds(2); digitalWrite(3,LOW); } } //中止信号 void stop() { pinMode(2, OUTPUT); digitalWrite(3,LOW); delayMicroseconds(2); digitalWrite(2,LOW); delayMicroseconds(2); digitalWrite(3,HIGH); delayMicroseconds(2); digitalWrite(2,HIGH); } //写数据 void write(byte x) { digitalWrite(2,HIGH); for(int i = 1; i <= 8; i = i + (1)) { digitalWrite(3,LOW); if ((x&0x01)) { digitalWrite(2,HIGH); }else { digitalWrite(2,LOW); } delayMicroseconds(3); x= (x>>1); digitalWrite(3,HIGH); delayMicroseconds(3); } } //显现0000 void display_starter() { //数据命令设置 start(); write(0x40); ack(); stop(); //地址设置 start(); write(0xC0); ack(); //数据显现 write(0x3F); ack(); write(0x3F); ack(); write(0x3F); ack(); write(0x3F); ack(); stop(); //显现控制 start(); write(0x8F); ack(); stop(); } int NUM[]={0X06, 0X5B, 0X4F, 0X66, 0X6D,0X7D, 0X07, 0X7F, 0X6F, 0X3F}; //显现变量 void display_char(int ch, int p) { if(ch > 10) { ch = 0; } p =p - 1; start(); write(0X44); ack(); stop(); start(); write(0xC0 + p); ack(); write(NUM[(int)(ch - 1)]); ack(); stop(); start(); write(0x8F); ack(); stop(); } 主函数模块 转译的代码 void setup(){ pinMode(3, OUTPUT); pinMode(2, OUTPUT); display_starter();//设置初始值0000 delay(5000);//延时5S } void loop(){ display_char(1, 4);//第四个数码管显现1 delay(1000); } 效果显现:初始值显现0000,持续5S后第四个数码管显现1 作者:冯美文 点击原文链接,能够下载代码。 假如你觉得有用,欢送点击 赞扬 |