基于STM32的四位数码管显示编程

1、四位数码管的简单介绍

因为在学校做项目的时候使用到了数码管显示,所以就编写了一个基于SMT32的数码管显示程序。通过看手册知道这个四位数码管采用TM1637 驱动电路。内部有集成MCU数字电路接口,数据锁存器,LED高压驱动。引出两根数据线与单片机连接通讯的数据线,接线就接着两根数据线,当然,还有电源线:

1.1:接线方法

基于STM32的四位数码管显示编程_第1张图片

1.2:通讯方式

想要使用并且熟悉一个模块,通过查看官方手册是最好的一个方法。通过查看手册,你可以得到这个模块的驱动方法和基本电路连接。
以下就是这个四位数码管的驱动方式说明:
基于STM32的四位数码管显示编程_第2张图片

可以看出这是一个使用IIC通讯的方式,因为两根数据线,一根传输数据的线,一根时钟线,熟悉单片机外设功能的话就可以看出这是一个IIC通讯了。而且还有起始信号,结束信号,应答信号。
所以我们只要根据IIC的时序图写好IIC通讯程序就行了。
这里说一个题外话,在一般使用到IIC通讯的时候,大都是使用模拟IIC通讯,因为IIC通讯的最大速度也就是3M左右,现在单片机IO口速度已经达到了50M了,配置过IO口就知道了,IO口速度配置的时候有个高速配置,速度就是50M的。
而且用模拟IIC比硬件IIC更方便,简单。所以大都是使用模拟IIC。

2、程序的编写

在知道怎么接线和怎么驱动之后这个就好办了,接下来就是愉快的编程了。下面就是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:四位数码管的显示程序

在编写前,查看一下手册的命令。
基于STM32的四位数码管显示编程_第3张图片
还有从数码管第几个开始显示的命令:
基于STM32的四位数码管显示编程_第4张图片

可以看出默认的时候显示的地址为00H,也就是从第一个位显示,这个数码管是四位的。
下面是程序和注释:

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 && num < 1000)
 {
  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));     //显示完之后清除数组中的内容
}

我使用到数码管是因为要显示超声波测得到的距离,下面这个就是测试得到的结果:
基于STM32的四位数码管显示编程_第5张图片

头文件

#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

你可能感兴趣的:(嵌入式之STM32)