STM32+TM1620B实现按键识别和数码管驱动

        各位好,小弟在学习了B站江科大的STM32的教程后,自己搞了个板子,实现TM1620B的按键识别和数码管驱动,现跟大家分享下原理和代码。

1、原理

        单片机用的是STM32F103C8T6,3个2位7段共阴极数码管,6个按键,1个TM1620B。

        其中6位数码管的公共端分别接到TM1620B的GR1~6上,因此TM1620B需要是6位7段的模式,每个数码管的a~g接到TM1620B的SEG1~6以及SEG12上。

        按键的公共端接到TM1620的K2上,按键的另一端分别接到SEG1~6上。

2、程序实现

(1)TM1620B的初始化

#define     TM1620B_PORT     GPIOB
#define     TM1620B_STB      GPIO_Pin_3
                                        //在上升或下降沿初始化串行接口,随后等待接收指令。
                                        //STB 为低后的第一个字节作为指令,当处理指令时,当前其它处理被终止。
                                        //当STB 为高时,CLK 被忽略 
#define     TM1620B_CLK      GPIO_Pin_4
                                        //在上升沿输入/输出串行数据
#define     TM1620B_DIO      GPIO_Pin_5
                                        //在时钟上升沿输入/输出串行数据,从低位开始

        STM32的PB2~5接TM1620B的STB、CLK、DIO。

/*!
 * @brief 初始化TM1620B的管脚
 * @param  
 */
void TM1620B_Init(void)
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);                        //关闭JTAG功能(PB3/4),只使用SWD(PA13/14)调试

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB , ENABLE );                        
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode  =  GPIO_Mode_Out_OD;     //开漏输出                   
    GPIO_InitStruct.GPIO_Pin   =  TM1620B_STB | TM1620B_CLK | TM1620B_DIO ;
    GPIO_InitStruct.GPIO_Speed =  GPIO_Speed_10MHz ;
    GPIO_Init( TM1620B_PORT , &GPIO_InitStruct );         

    TM1620B_W_DIO(1);
    TM1620B_W_CLK(1);
    TM1620B_W_STB(1);       //常态都拉高
}

        ①PB3和4默认不是GPIO的功能,需要改一下。STM32F103系列PB3 PB4重映射成正常io口_stm32f103 pb3-CSDN博客

        ②IIC开漏输出。

        ③开始3个管脚都拉高。

(2)发送一个字节

①读写3个管脚

/*********************************读写TM1620B管脚********************************************/
void TM1620B_W_STB( uint8_t BitValue )
{
    GPIO_WriteBit(TM1620B_PORT , TM1620B_STB , (BitAction)BitValue );
}
void TM1620B_W_CLK( uint8_t BitValue )
{
    GPIO_WriteBit(TM1620B_PORT , TM1620B_CLK , (BitAction)BitValue );
}
void TM1620B_W_DIO( uint8_t BitValue )
{
    GPIO_WriteBit(TM1620B_PORT , TM1620B_DIO , (BitAction)BitValue );
}
uint8_t TM1620B_R_DIO(void)
{
    return GPIO_ReadInputDataBit(TM1620B_PORT , TM1620B_DIO  );
}
/*****************************END:读写TM1620B管脚********************************************/

        ②发送一个字节

/*!
 * @brief 发送一个数据字节
 * @param Data 
 */
void TM1620B_SendByte( uint8_t Data )
{                                                              
    for (uint8_t i = 0; i < 8; i++)
    {
        TM1620B_W_DIO( Data & ( 0x01 << i ) );                                      //低位先行
        TM1620B_W_CLK( 0 );
        TM1620B_W_CLK( 1 );                                                         //在时钟的上升沿操作
    }
}

        先改变数据位,后产生一个上升沿,低位先行。

(3)第GRID位显示数字Num

uint8_t Code_LedData[]={
	0x3F,  //"0"
    0x06,  //"1"
    0x5B,  //"2"
    0x4F,  //"3"
    0x66,  //"4"
    0x6D,  //"5"
    0x7D,  //"6"
    0x07,  //"7"
    0x7F,  //"8"
    0x6F,  //"9"
    0x77,  //"A"
    0x7C,  //"B"
    0x39,  //"C"
    0x5E,  //"D"
    0x79,  //"E"
    0x71,  //"F"
    0x76,  //"H"
    0x38,  //"L"
    0x37,  //"n"
    0x3E,  //"u"
    0x73,  //"P"
    0x5C,  //"o"
    0x40,  //"-"
    0x00  //熄灭
	};      //7段共阴数码管编码

uint8_t TM1620B_GRID[] = { 0xC0,0xC2,0xC4,0xC6,0xC8,0xCA,0xCC };        //6位,第一位的共阴的地址
uint8_t TM1620B_SEG[2][24];        //用以区分7段数码管的低六段和高第七段,0:低六段 1:高第七段

        

        TM1620B_GRID公共端GRID1~6的地址(SEG1~6的,SEG12的话地址加1),TM1620B_SEG用来分开段码(分为SEG1~6和SEG12)。

/*!
 * @brief 第GRID位显示数字Num
 * @param GRIDNum 
 * @param Num 
 */
void TM1620B_ShowNum( uint8_t GRIDNum , uint8_t Num )
{
    GRIDNum--; 
    for (uint8_t i = 0; i < 24; i++)
    {
        TM1620B_SEG[0][i] = Code_LedData[i] & 0x3F;
        TM1620B_SEG[1][i] = (Code_LedData[i] & 0x40) >> 3 ;
    }
    
    for (uint8_t i = 0; i < 2; i++)
    {
        TM1620B_W_STB(0);       //开始发数据
        TM1620B_SendByte(0x02);      //0000 0010    6位7段
        TM1620B_W_STB(1);
        TM1620B_W_STB(0);
        TM1620B_SendByte(0x44);      //0100 0(普通模式)1(固定地址)00(写数据到显示寄存器)
        TM1620B_W_STB(1);
        TM1620B_W_STB(0);
        TM1620B_SendByte( TM1620B_GRID[GRIDNum] +i );      //i[0:低六段 1:高第七段]
        TM1620B_SendByte( TM1620B_SEG[i][Num] );     
        TM1620B_W_STB(1);
        TM1620B_W_STB(0);
        TM1620B_SendByte(0x89);     //1000 1(显示开)1XX(XX越大越亮)
        TM1620B_W_STB(1);   
    }
}

        按照固定地址模式去设置TM1620B的输出。        

        分两次显示,分别显示7段数码管的a~f和g。

(4)读按键

/*!
 * @brief 读3个字节的按键信号
 * @param  
 * @return 
 */
uint32_t TM1620B_Read3Byte(void)
{
    uint32_t Bytes = 0x0000 ;
    TM1620B_W_DIO(1);       //释放数据线
    TM1620B_W_CLK(0);
    for (uint8_t i = 0; i < 24; i++)
    {
        
        TM1620B_W_CLK(1);
        if (TM1620B_R_DIO()==1)
        {
            Bytes = Bytes | ( 0x0001 << i ) ;
        }
        TM1620B_W_CLK(0);
    }
    TM1620B_W_CLK(1);
    return Bytes;
}

        返回3个字节的按键信号。

(5)在第GRID_Num([1:3])个数码管上显示数字Num(二位十进制数),同时可以读按键

/*!
 * @brief 在第GRID_Num([1:3])个数码管上显示数字Num(二位十进制数)
 * @param GRID_Num 
 * @param Num 
 * @return 
 */
uint32_t TM1620B_ShowNumAndReadKey( uint8_t GRID_Num , uint8_t Num )
{
    if (GRID_Num)
    {
        TM1620B_ShowNum(2*GRID_Num-1,Num/10);
        TM1620B_ShowNum(2*GRID_Num,Num%10);
    }
    TM1620B_W_STB(0);       //开始收按键数据
    TM1620B_SendByte(0x42);     //0100 0(普通模式)0(自动地址增加)10(读键扫数据)
    uint32_t KeyBytes = TM1620B_Read3Byte();
    TM1620B_W_STB(1);
    return KeyBytes;
}

3、实物现象

/*****************数码管显示时间的程序 */
TaskHandle_t LED_Time_TaskHandler;
void LED_Time_Task( void *arg )
{
    uint8_t LED_Num = 0;
    while (1)
    {
        TM1620B_ShowNumAndReadKey(1,Time_Data[2]);
        TM1620B_ShowNumAndReadKey(2,Time_Data[1]);
        TM1620B_ShowNumAndReadKey(3,Time_Data[0]);
        if (TM1620B_ShowNumAndReadKey(0,1) == 0x0002 )
        {
            //vTaskDelay(20);
            if (TM1620B_ShowNumAndReadKey(0,1)== 0x0002)
            {
                while (TM1620B_ShowNumAndReadKey(0,1)== 0x0002)
                {
                }
                LED_Num = (LED_Num+1)%20;
            }
        }
        TM1616_ShowLed(LED_Num);
    }
}

        时钟芯片是RX8025T,分别在三组数码管上显示时分秒。

        欢迎各位大佬批评指正。

        另外板子是从嘉立创嫖的(感谢立创)。

作者:在海防吃馅饼的蟠桃

物联沃分享整理
物联沃-IOTWORD物联网 » STM32+TM1620B实现按键识别和数码管驱动

发表回复