基於STM32的四位數碼管顯示編程

一、四位數碼管的簡單介紹

由於在學校作項目的時候使用到了數碼管顯示,因此就編寫了一個基於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
相關文章
相關標籤/搜索