一、四位数码管的简单介绍
由于在学校作项目的时候使用到了数码管显示,因此就编写了一个基于SMT32的数码管显示程序。经过看手册知道这个四位数码管采用TM1637 驱动电路。内部有集成MCU数字电路接口,数据锁存器,LED高压驱动。引出两根数据线与单片机链接通信的数据线,接线就接着两根数据线,固然,还有电源线:javascript
1.1:接线方法
1.2:通信方式
想要使用而且熟悉一个模块,经过查看官方手册是最好的一个方法。经过查看手册,你能够获得这个模块的驱动方法和基本电路链接。
如下就是这个四位数码管的驱动方式说明:
java
能够看出这是一个使用IIC通信的方式,由于两根数据线,一根传输数据的线,一根时钟线,熟悉单片机外设功能的话就能够看出这是一个IIC通信了。并且还有起始信号,结束信号,应答信号。
因此咱们只要根据IIC的时序图写好IIC通信程序就好了。
这里说一个题外话,在通常使用到IIC通信的时候,大都是使用模拟IIC通信,由于IIC通信的最大速度也就是3M左右,如今单片机IO口速度已经达到了50M了,配置过IO口就知道了,IO口速度配置的时候有个高速配置,速冻就是50M的。
并且用模拟IIC比硬件IIC更方便,简单。因此大都是使用模拟IIC。
编程
二、程序的编写
在知道怎么接线和怎么驱动以后这个就好办了,接下来就是愉快的编程了。下面就是IIC的程序编写。数组
2.1:IIC的初始化
这里知道使用模拟IIC以后就开始简单的初始化,初始化就是初始化IO,配置IO口结构体的属性。函数
void Iic_Init(void) { GPIO_InitTypeDef GPIO_InitStatus; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitStatus.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;//定义引脚为PB6,PB7. GPIO_InitStatus.GPIO_Mode=GPIO_Mode_Out_PP; //配置引脚模式为输出模式 GPIO_InitStatus.GPIO_Speed=GPIO_Speed_50MHz; //配置引脚的速度为高速:50M GPIO_Init(GPIOB,&GPIO_InitStatus); //初始化GPIO IIC_CLK(1); //一开始拉高时钟线,这算是个宏定义。 IIC_DATA_OUT(1); //数据线输出高电平 }
2.2:IIC的起始信号
void Iic_Start(void) { Iic_Data_Out(); //把DIO数据线配置成输出模式, IIC_CLK(1); //CLK时钟线输出高电平 IIC_DATA_OUT(1);//DIO数据线输出高电平 delay_us(2); //延时2us IIC_DATA_OUT(0);//DIO数据线输出低电平 }
2.3:IIC的中止信号
void Iic_Stop(void) { Iic_Data_Out(); //把DIO数据线配置成输出模式, IIC_CLK(0); //CLK时钟线输出低电平 delay_us(2); //延时2us IIC_DATA_OUT(0);//DIO数据线输出低电平 delay_us(2); //延时2us IIC_CLK(1); //CLK时钟线输出高电平 delay_us(2); //延时2us IIC_DATA_OUT(1);//DIO数据线输出高电平 }
2.4:IIC的应答信号
void Iic_Ack(void) { Iic_Data_Input(); //把DIO数据线配置成输入模式,用来读取数据 IIC_CLK(0); //CLK时钟线输出低电平 delay_us(5); //延时5us while(IIC_DATA_INT);//等待DIO数据线被拉低,若是没有拉低会卡在这里等待应答 IIC_CLK(1); //CLK时钟线输出高电平 delay_us(2); //延时2us IIC_CLK(0); //CLK时钟线输出低电平 }
2.5:IIC的写程序
void Iic_Write_Byte(u8 byte) //参数:须要写进数码管的数据 { u8 Num; //定义一个用来循环8次接受数据的变量用来计数循环 Iic_Data_Out(); //把DIO数据线 for(Num=0;Num<8;Num++) //循环8次 { IIC_CLK(0); //每次写的时候CLK输出低电平 if(byte&0x01) //低位在前 判断数据的当前位为1仍是0 { IIC_DATA_OUT(1); //DIO数据线输出高电平 当前数据位为1 } else { IIC_DATA_OUT(0); //DIO数据线输出低电平 当前数据位为0 } delay_us(3); //延时3us byte=byte>>1; //每次发送完一次位数后,数据都左移一位 IIC_CLK(1); //每次写完时候CLK输出高电平 delay_us(3); //延时3us } }
2.6:IIC的读程序
由于这个数码管不须要到读,因此就没有写了,这个只要写程序,把数据写进数码管去。测试
2.7:四位数码管的显示程序
在编写前,查看一下手册的命令。
还有从数码管第几个开始显示的命令:
spa
能够看出默认的时候显示的地址为00H,也就是从第一个位显示,这个数码管是四位的。
下面是程序和注释:
code
void Display_Num(u16 num) { u16 number[4] = {0}; if(num < 10) //判断参数是几位数据,而后根据位数分解数字 { number[0] = num; } else if(num >=10 && num <100) { number[0] = num%10; number[1] = num/10; } else if(num >=100) { number[0] = num%10; number[1] = (num/10)%10; number[2] = num/100; } else if(num >= 1000) //1234 { number[0] = num%10; //1234 % 10 = 4 number[1] = (num/10)%10; //(1234 / 10) = 123 ; 123 % 10 = 3 number[2] = (num/100)%10; //(1234 / 100) = 12 ; 12 % 10 = 2 number[3] = num/1000; //(1234 / 1000) = 1 } Iic_Start(); Iic_Write_Byte(0x40); //启动该写数据模式。 0x40; Iic_Ack(); Iic_Stop(); Iic_Start(); Iic_Write_Byte(0xc0); //从第一位数码管显示,发送0xc0; Iic_Ack(); Iic_Write_Byte(Num_Dis[number[3]]); //第四位数码管显示的数据 Iic_Ack(); Iic_Write_Byte(Num_Dis[number[2]]); //第三位数码管显示的数据 Iic_Ack(); Iic_Write_Byte(Num_Dis[number[1]]); //第二位数码管显示的数据 Iic_Ack(); Iic_Write_Byte(Num_Dis[number[0]]); //第一位数码管显示的数据 Iic_Ack(); Iic_Stop(); Iic_Start(); Iic_Write_Byte(0x8f); //开始显示 Iic_Ack(); Iic_Stop(); memset(number,0,sizeof(number)); //显示完以后清除数组中的内容 }
我使用到数码管是由于要显示超声波测获得的距离,下面这个就是测试获得的结果:
blog
头文件
#ifndef IIC_H #define IIC_H #include "stm32f10x.h" #define IIC_CLK(x) (x?GPIO_WriteBit(GPIOB,GPIO_Pin_7,Bit_SET):GPIO_WriteBit(GPIOB,GPIO_Pin_7,Bit_RESET)) #define IIC_DATA_OUT(x) (x?GPIO_WriteBit(GPIOB,GPIO_Pin_6,Bit_SET):GPIO_WriteBit(GPIOB,GPIO_Pin_6,Bit_RESET)) #define IIC_DATA_INT ((GPIOB->IDR & (1<<6))) void Iic_Init(void); //初始化 void Iic_Data_Out(void); //把DIO配置成输出模式 void Iic_Data_Input(void); //把DIO配置成输入模式 void Iic_Start(void); //起始信号 void Iic_Stop(void); //结束信号 void Iic_Ack(void); //应答信号 void Iic_Write_Byte(u8 byte); //写数据 void Display_Num(u16 num); //显示函数,调用这个函数就好了,前提是在main中调用了初始化函数 #endif