STM32通過I2C驅動TM1637顯示四位數碼管


  目前市面上有一些數碼管顯示芯片,其中TM1637是比較經典,也是我個人比較喜歡的一款芯片。TM1637是天微電子的一款帶按鍵掃描的8段*6位數碼管驅動芯片,本次使用STM32F103C8T6驅動四位數碼管。(下圖:TM1637功能及管腳,來源TM1637開發手冊)

I2C驅動:

  TM1637采用的通信方式是I2C通信,所以我們首先來簡單介紹下I2C的通信方式:

  I2C通信是一種經典的通信協議,在物理層上,它使用SDA(串行數據線),SCL(串行時鍾線)兩條線控制一個或多個設備。既然通過一條數據線控制多個設備,那么設備就必定有一個獨屬於自己的地址(類似於ID),以便於主機可以和不同的設備通信。

  在協議層上,I2C通信時會首先發送一個Start信號,這時,在數據線上的設備都會聽到這個信號,並等待着下一個信號:地址信號的到來。主機在開始信號后會發送地址信號,如果這個地址不是從機設備的地址,那么這個從機會忽略后面的消息,因為主機的通信對象不是它,它不需要繼續聽下去(這也不太禮貌)。但如果這個地址是從機的地址,那么從機會發送一個應答信號,表示”我聽到了“。

  由於本次是我們是單方面向TM1637寫數據,所以I2C中主機由從機中讀數據不再贅述。接下來主機會發送多個字節的數據,主機每發送一個字節的數據,從機就會應答一次,當主機想要停止發送,就會發送一個停止數據,整個通信流程就完成了。(圖源網絡,地址位也可能是10位)

 

 

TM1637驅動代碼:

  知道了通信方式,我們就可以比較輕松的編寫出TM1637的驅動代碼,先看看官方給出的程序流程:

  

  這里我們舍去按鍵掃描的程序,直接使用I2C驅動,並使用圖中的地址自加模式

  我們先進行頭文件中宏的定義:

#ifndef   __TM1637_H
#define   __TM1637_H

#include "stm32f10x.h"
#include "sys.h"

//與庫函數操作取一個
#define    SDA_IN()  {GPIOA->CRL&=0X0FFFFFFF;GPIOA->CRL|=(u32)8<<28;}      //通過寄存器更改為輸入
#define    SDA_OUT() {GPIOA->CRL&=0X0FFFFFFF;GPIOA->CRL|=(u32)3<<28;}      //通過寄存器更改為輸出

#define    TM_SCL_PORT        GPIOA
#define    TM_SCL_CLK         RCC_APB2Periph_GPIOA
#define    TM_SCL_PIN         GPIO_Pin_5

#define    TM_DIO_PORT        GPIOA
#define    TM_DIO_CLK         RCC_APB2Periph_GPIOA
#define    TM_DIO_PIN         GPIO_Pin_7

 #define TM_SCL PAout(5)
 #define TM_SDA PAout(7)

  #define READ_SDA PAin(7)

 

/*函數聲明,這里省略,使用時請自加*/

#endif

 

  在驅動文件TM1637.c中首先是I2C初始化,這里使用了軟件I2C

#include "TM1637.h"
#include "delay.h"



void TM_Init(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    
    RCC_APB2PeriphClockCmd(TM_DIO_CLK|TM_SCL_CLK,ENABLE);    
    
    GPIO_InitStructure.GPIO_Pin = TM_DIO_PIN | TM_SCL_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;    
    GPIO_Init(TM_DIO_PORT,&GPIO_InitStructure);
    
//    TM_SCL=1;
//    TM_SDA=1;
}

  

  然后是開始,停止,等待應答,寫一個8位數據的函數

void TM_Start(void)
{
    TM_SDA=1;
    delay_us(2);
    TM_SCL=1;
    delay_us(2);
    TM_SDA=0;
    delay_us(2);
    TM_SCL=0;
    delay_us(2);
}

void TM_Stop(void)
{
    TM_SCL=0;
    delay_us(2);
    TM_SDA=0;
    delay_us(2);
    TM_SCL=1;
    delay_us(2);
    TM_SDA=1;
    delay_us(2);
}

void TM_Wait_Ask(void)
{
    SDA_IN();
    unsigned char i;
    TM_SCL=0;
    delay_us(5);
    while(READ_SDA==1&&(i<250))i++;
    TM_SCL=1;
    delay_us(2);
    TM_SCL=0;
    SDA_OUT();
}

void TM_WriteByte(uint8_t txd)
{
    uint8_t i;
    for(i=0;i<8;i++)
  {
        TM_SCL=0;
        delay_us(2);
        if(txd & 0x01){
            TM_SDA=1;
        }
        else {
            TM_SDA=0;
        }
        delay_us(3);
        txd>>=1;
        TM_SCL=1;
        delay_us(3);
  }
    //TM_Wait_Ask();
}

  

  最后是main中使用的Display函數,這里的函數適用於4位數碼管:

void TM_Display(uint8_t *discode)
{
    uint8_t i;
    
    TM_Start();
    TM_WriteByte(0x40);    //40 地址自加模式     44 固定地址模式
    TM_Wait_Ask();
    TM_Stop();
    
    TM_Start();
    TM_WriteByte(0xc0);   //首地址
    TM_Wait_Ask();
    
    for(i=0;i<4;i++)
    {
        TM_WriteByte(*(discode+i));  //依次發送數組數據
        TM_Wait_Ask();
    }
    TM_Stop();
    
    TM_Start();
    TM_WriteByte(0x89);   //亮度
    TM_Wait_Ask();
    TM_Stop();
}

   在主函數中,我們需要定義一個字符數組,以顯示正確的字符,同時需要定義一個uint8_t長度的四位數組,即可進行顯示。

  

unsigned char  Data[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//不帶點

unsigned char  DataD[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef};
//帶點

uint8_t time[4]={0x3f,0x3f,0x3f,0x3f};   //一個四位數組,這里代表0000

TM_Display(time);  //進行顯示!

 

  以上就是STM32通過I2C驅動TM1637的相關內容。

  代碼有幾處借鑒了網上或者TM官方的思路,文章純手打,如果轉載使用望注明一下博客地址。 |・ω・)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM