打印
[STM32L0]

【NUCLEO-64试用】STM32G431 TM1638控制数码管

[复制链接]
1856|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 qjp1988113 于 2020-10-10 10:43 编辑

最近一个项目用到TM1628模块控制数码管,手头上正好有TM1638这个模块。
比较了TM628和TM1638,发现除了后者寄存器多一组外,其他操作几乎一致,可以验证。
就用STM32G431 NUCLEO试了一下,也不能浪费它啊,毕竟它是ST最近的主推呢。
外设配置直接用STM32CUBEMX配置,简单省事,这也是ST生态软件
做的好的缘故,让人有欲望用。
控制TM138用模拟的IO来实现的。TM1638是国产的芯片,数据手册
全中文,阅读很方便,唯一的一个坑就是这货需要一定的初始化时间,
我之前给的时间不够,就不能正确控制。
CUBEMX仅定义3个IO口:


TM1368的基本读写操作时序(主意:最小延时间隔1us):

TM1368的自增1地址操作的时序:

TM1368的固定地址操作的时序:

TM1368读操作时序:


具体c及头文件h:


#include "tm1628.h"

uint8_t SMG_Value[6]={0,0,0,0,0,0};//6个数码管
//共阴数码管显示代码 1~10 A B C D E F
//仅占用数码管的1~7位 其余8,9,10,12
const uint8_t Numtab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
                           0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
/***************************************************
*程 序 名:Tm1628_DATA_PINDIR(uint8_t dir)
*作    用:DAT引脚配置
*输入参数:dir(0=输出,1=输入) 默认状态下为输出
*转出参数:无
***************************************************/
void Tm1628_DATA_PINDIR(uint8_t dir)                  //DAT端口配置(根据需要配置成输出或输入模式)
{
        GPIO_InitTypeDef GPIO_InitStruct;
        if(dir == 0)
        {
                GPIO_InitStruct.Pin         = TM1638_DIO_Pin; //SDA输出模式、弱上拉
                GPIO_InitStruct.Mode         = GPIO_MODE_OUTPUT_PP;
                GPIO_InitStruct.Pull         = GPIO_NOPULL;
                GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
                HAL_GPIO_Init(TM1638_DIO_GPIO_Port, &GPIO_InitStruct);
        }
        else
        {
                GPIO_InitStruct.Pin         = TM1638_DIO_Pin; //SDA输入模式
                GPIO_InitStruct.Mode         = GPIO_MODE_INPUT;
                HAL_GPIO_Init(TM1638_DIO_GPIO_Port, &GPIO_InitStruct);
        }
        HAL_GPIO_WritePin(TM1638_DIO_GPIO_Port,TM1638_DIO_Pin,GPIO_PIN_SET);
}
/*************************************
函数名称:Tm1628_Write_Byte
函数说明:写单个字节
函数参数:命令参数
函数返回:NULL
*************************************/
void Tm1628_Write_Byte(uint8_t data)
{
        uint8_t i;
        Tm1628_CKL_H;
        Tm1628_DIO_H;
        for(i = 0; i < 8; i++)
        {
                Tm1628_CKL_L;
                delay_us(10);
                if((data & 0x01) == 1)
                        Tm1628_DIO_H;
                else
                        Tm1628_DIO_L;
                data = data        >> 1;
                Tm1628_CKL_H;
                delay_us(10);
        }        
}
/*************************************
函数名称:Tm1628_Read_Byte
函数说明:读单个字节   Tm1628_DIO_Value
函数参数:命令参数
函数返回:NULL
*************************************/
uint8_t Tm1628_Read_Byte(void)                                        //读数据函数
{
        uint8_t i;
        uint8_t temp=0;
        Tm1628_DATA_PINDIR(1);        //设置为输入
        delay_us(10);
        for(i=0;i<8;i++)
        {
                temp>>=1;
                Tm1628_CKL_L;
                delay_us(10);
                if(Tm1628_DIO_Value)
                        temp|=0x80;
                Tm1628_CKL_H;
                delay_us(10);
        }
        Tm1628_DATA_PINDIR(0);        //设置为输出
        delay_us(10);
        return temp;
}
/*************************************
函数名称:Tm1628_Write_Command
函数说明:写命令
函数参数:命令参数
函数返回:NULL
*************************************/
void Tm1628_Write_Command(uint8_t cmd)
{
        Tm1628_STB_L;
        delay_us(10);
        Tm1628_Write_Byte(cmd);
        Tm1628_STB_H;
        delay_us(10);
}
/*************************************
函数名称:Tm1628_Write_Command
函数说明:写命令
函数参数:命令参数
函数返回:NULL
*************************************/
uint8_t Tm1628_Read_key(void)
{
               
        uint8_t c[4],i,key_value=0;
        Tm1628_STB_L;
        delay_us(10);
        Tm1628_Write_Byte(0x42);                           //读键扫数据 命令
        for(i=0;i<4;i++)               
                c=Tm1628_Read_Byte();
        Tm1628_STB_H;               
        delay_us(10);        //4个字节数据合成一个字节
        for(i=0;i<4;i++)
                key_value|=c<<i;
        for(i=0;i<8;i++)
                if((0x01<<i)==key_value)
                        break;
        return i;
               
}
/*************************************
函数名称:Tm1628init
函数说明:TM1628初始化
函数参数:NULL
函数返回:NULL
*************************************/
void Tm1628init(void)
{
  uint8_t InitData[14]={Numtab[0],Numtab[0],Numtab[0],Numtab[0],Numtab[0],
        Numtab[0],Numtab[0],Numtab[0],Numtab[0],Numtab[0],Numtab[0],Numtab[0],Numtab[0],Numtab[0]};
        //Tm1628_Write_Command(0x03);          //7位10段
        //Tm1628_Write_Command(MODE_COMMAND|MODE_6W11D);          //6位11段
        
        Tm1628_Write_Command(MODE_COMMAND|MODE_7W10D);          //7位10段
        
        Tm1628_ClearDisplay();        //清屏
        Tm1628_GrayScale(8);        //亮度2
        //Tm1628_Fixed(0xc2,0XFF);
        //初始化每个显示0
        Tm1628_Continuous(0XC0, 14, InitData);
}

/*************************************
函数名称:Tm1628_Fixed
函数说明:固定写显示
函数参数:(1)data 地址
(2)add        数据
函数返回:NULL
*************************************/
void Tm1628_Fixed(uint8_t add, uint8_t data)
{
        Tm1628_Write_Command(0x44);
        Tm1628_STB_L;
        delay_us(10);
        Tm1628_Write_Byte(add);
        Tm1628_Write_Byte(data);
        Tm1628_STB_H;
        delay_us(10);
}

/*************************************
函数名称:Tm1628_Continuous
函数说明:连续写显示
函数参数:(1)data 地址  从C0开始
(2)num        数据
(3)add  数量        最大14
函数返回:NULL
*************************************/
void Tm1628_Continuous(uint8_t add, uint8_t num, uint8_t *data)
{
        uint8_t i;
        Tm1628_Write_Command(0x40);
        Tm1628_STB_L;
        delay_ms(1);
        Tm1628_Write_Byte(add);
        for(i = 0; i < num; i++)
        {
                Tm1628_Write_Byte(data);
        }
        Tm1628_STB_H;
        delay_ms(1);
}
/*************************************
函数名称:Tm1628_ClearDisplay
函数说明:清屏
函数参数:NULL
函数返回:NULL
*************************************/
void Tm1628_ClearDisplay(void)
{
        uint8_t i;
        Tm1628_Write_Command(0x40);
        Tm1628_STB_L;
        delay_ms(1);
        Tm1628_Write_Byte(0xC0);
        for(i = 0; i < 14; i++)
        {
                Tm1628_Write_Byte(0x00);
        }
        Tm1628_STB_H;
        delay_ms(1);
}

/*************************************
函数名称:Tm1628_GrayScale
函数说明:用于亮度调节 0 - 9
函数参数:亮度 0 - 9
函数返回:NULL
*************************************/
void Tm1628_GrayScale(uint8_t data)
{
        switch(data)
        {
                case(0): Tm1628_Write_Command(DISP_COMMAND|DISP_GrayScale_OFF);break;//关闭
                case(1): Tm1628_Write_Command(DISP_COMMAND|DISP_GrayScale_ON|DISP_GrayScale1);         break;
                case(2): Tm1628_Write_Command(DISP_COMMAND|DISP_GrayScale_ON|DISP_GrayScale2);         break;
                case(3): Tm1628_Write_Command(DISP_COMMAND|DISP_GrayScale_ON|DISP_GrayScale3);        break;        
                case(4): Tm1628_Write_Command(DISP_COMMAND|DISP_GrayScale_ON|DISP_GrayScale4);        break;
                case(5): Tm1628_Write_Command(DISP_COMMAND|DISP_GrayScale_ON|DISP_GrayScale5);        break;
                case(6): Tm1628_Write_Command(DISP_COMMAND|DISP_GrayScale_ON|DISP_GrayScale6);        break;
                case(7): Tm1628_Write_Command(DISP_COMMAND|DISP_GrayScale_ON|DISP_GrayScale7);        break;
                case(8): Tm1628_Write_Command(DISP_COMMAND|DISP_GrayScale_ON|DISP_GrayScale8);        break;
        }

}
//由于使用了1~10 12 超出了8位 每次写一个数码管数据 需占用2个字节 2个地址
//固定地址写 其实地址只能是 0XC0 0XC2 0XC4 0XC6 0XC8 0XCA 0XCC
//函数参数:(1)data 地址  从C0开始
//(2)num        数据
//(3)add  数量        最大14
void Tm1628_WriteOneSMG(uint8_t add, uint16_t data)
{
        uint8_t tmp[2];
        tmp[0]=data&0xFF;//低8位
        tmp[1]=data>>8;//高8位
        
        Tm1628_Continuous(add,2,tmp);
}

void Tm1628_Write_allLED(unsigned char LED_flag)                                        //控制全部LED函数,LED_flag表示各个LED状态
{
        unsigned char i;
        for(i=0;i<8;i++)
                {
                        if(LED_flag&(1<<i))
                                //Write_DATA(2*i+1,3);
                                Tm1628_Fixed(0xc0|(2*i)+1,1);
                        else
                                Tm1628_Fixed(0xc0|(2*i+1),0);
                }
}

//////////////////////////////////////////
#ifndef __TM1628_H
#define __TM1628_H


#include "main.h"
#include "delay.h"

//控制引脚定义        
#define Tm1628_CKL_H HAL_GPIO_WritePin(TM1638_CLK_GPIO_Port,TM1638_CLK_Pin,GPIO_PIN_SET)
#define Tm1628_CKL_L HAL_GPIO_WritePin(TM1638_CLK_GPIO_Port,TM1638_CLK_Pin,GPIO_PIN_RESET)

#define Tm1628_DIO_H HAL_GPIO_WritePin(TM1638_DIO_GPIO_Port,TM1638_DIO_Pin,GPIO_PIN_SET)
#define Tm1628_DIO_L HAL_GPIO_WritePin(TM1638_DIO_GPIO_Port,TM1638_DIO_Pin,GPIO_PIN_RESET)

#define Tm1628_STB_H HAL_GPIO_WritePin(TM1638_STB_GPIO_Port, TM1638_STB_Pin,GPIO_PIN_SET)
#define Tm1628_STB_L HAL_GPIO_WritePin(TM1638_STB_GPIO_Port, TM1638_STB_Pin,GPIO_PIN_RESET)

#define Tm1628_DIO_Value HAL_GPIO_ReadPin(TM1638_DIO_GPIO_Port,TM1638_DIO_Pin)

//指令定义 B7 B6 区别不同的指令
//   B7      B6      指令
//   0       0       显示模式命令设置
//   0       1       数据命令设置
//   1       0       显示控制命令设置
//   1       1       地址命令设置
#define MODE_COMMAND  0X00    //显示模式
#define        DATA_COMMAND        0X40    //数据
#define        DISP_COMMAND        0x80    //显示控制指令
#define        ADDR_COMMAND        0XC0    //地址

//显示模式 B1 B0
#define MODE_4W13D    0x00    //4位13段
#define MODE_5W12D    0x01    //5位12段
#define MODE_6W11D    0x02    //6位11段
#define MODE_7W10D    0x03    //7位10段
//真正调用某指令 如6位11段  MODE_COMMAND|MODE_6W11D 即可

//数据   B3 B2 B1 B0
#define DATA_WRITEMODE 0X00  //写数据到显示寄存器
#define DATA_READMODE  0X02  //读按键扫描数据
#define DATA_AUTOADDADDRESS 0X00 //地址自动加1模式
#define DATA_FIXADDRESS 0X04 //固定地址模式
//例:设置写数据 固定地址 DATA_COMMAND|DATA_WRITEMODE|DATA_FIXADDRESS

//显示控制 B3 B2 B1 B0  共8级辉度可调
#define DISP_GrayScale_OFF 0x00 //关显示
#define DISP_GrayScale_ON  0x08 //开显示
#define DISP_GrayScale1    0x00 //灰度等级1
#define DISP_GrayScale2    0x01 //灰度等级2
#define DISP_GrayScale3    0x02 //灰度等级3
#define DISP_GrayScale4    0x03 //灰度等级4
#define DISP_GrayScale5    0x04 //灰度等级5
#define DISP_GrayScale6    0x05 //灰度等级6
#define DISP_GrayScale7    0x06 //灰度等级7
#define DISP_GrayScale8    0x07 //灰度等级8
//例:设置开显示 辉度2  DISP_COMMAND|DISP_GrayScale_ON|DISP_GrayScale2

//地址 B3 B2 B1 B0 。最多有效地址为14位(C0H-CDH),如果地址设为CEH或更高,数据被忽
//略,直到有效地址被设定。上电时,地址默认设为C0H。
#define ADDR_SFR_00H  0X00
#define ADDR_SFR_01H  0X01
#define ADDR_SFR_02H  0X02
#define ADDR_SFR_03H  0X03
#define ADDR_SFR_04H  0X04
#define ADDR_SFR_05H  0X05
#define ADDR_SFR_06H  0X06
#define ADDR_SFR_07H  0X07
#define ADDR_SFR_08H  0X08
#define ADDR_SFR_09H  0X09
#define ADDR_SFR_0AH  0X0A
#define ADDR_SFR_0BH  0X0B
#define ADDR_SFR_0CH  0X0C
#define ADDR_SFR_0DH  0X0D
//例:设置地址0x01有效  ADDR_COMMAND|ADDR_SFR_01H

#define SMG1_ADDR   ADDR_COMMAND|ADDR_SFR_00H
#define SMG2_ADDR   ADDR_COMMAND|ADDR_SFR_02H
#define SMG3_ADDR   ADDR_COMMAND|ADDR_SFR_04H
#define SMG4_ADDR   ADDR_COMMAND|ADDR_SFR_06H
#define SMG5_ADDR   ADDR_COMMAND|ADDR_SFR_08H
#define SMG6_ADDR   ADDR_COMMAND|ADDR_SFR_0AH

#define SMG7_ADDR   ADDR_COMMAND|ADDR_SFR_0CH

extern const uint8_t Numtab[];

void Tm1628init(void);          //TM1628初始化
void Tm1628_DATA_PINDIR(uint8_t dir);
uint8_t Tm1628_Read_key(void);
void Tm1628_Fixed(uint8_t add, uint8_t data);        //固定写显示 data 地址 add        数据
void Tm1628_Continuous(uint8_t add, uint8_t num, uint8_t *data);        //连续写显示
void Tm1628_ClearDisplay(void);        //清屏
void Tm1628_GrayScale(uint8_t data);        //亮度调节
void Tm1628_WriteOneSMG(uint8_t add, uint16_t data);
void Tm1628_Write_allLED(unsigned char LED_flag);

#endif

main函数调用,初始化加测试显示:uint8_t num[8];                //各个数码管显示的值
uint8_t test1Num[14]={Numtab[0],0,Numtab[1],0,Numtab[2],0,Numtab[3],0,
                                                                                                Numtab[4],0,Numtab[5],0,Numtab[6]};

//tm1628.h 里面的函数控制 --PASS
Tm1628init();
delay_ms(2000);
Tm1628_WriteOneSMG(SMG1_ADDR,Numtab[2]);//写一个数码管
delay_ms(2000);
Tm1628_Fixed(SMG2_ADDR,Numtab[2]);//固定地址写
delay_ms(2000);
Tm1628_Continuous(0XC0, 14, test1Num);//连续地址写
delay_ms(2000);
Tm1628_ClearDisplay();        //清屏
delay_ms(2000);
while(1)
{
    i=Tm1628_Read_key();
    if(i<8)
   {
        num++;
        while(Tm1628_Read_key()==i);                       //等待按键释放
        if(num>15)
        num=0;
        Tm1628_Fixed(0XC0|(i*2),Numtab[num]);
                        
        Tm1628_Write_allLED(1<<i);
                        
   }
}
编译,下载,观察现象:











使用特权

评论回复
沙发
zeshoufx| | 2020-10-10 15:01 | 只看该作者
谢谢分享【STM32G431 TM1638控制数码管】

使用特权

评论回复
板凳
zhuotuzi| | 2020-10-10 15:33 | 只看该作者
非常棒的操作。

使用特权

评论回复
地板
zhuotuzi| | 2020-10-10 15:35 | 只看该作者
楼主用的HAL库啊,可以试试LL库。

使用特权

评论回复
5
qjp1988113|  楼主 | 2020-10-10 16:04 | 只看该作者
zhuotuzi 发表于 2020-10-10 15:35
楼主用的HAL库啊,可以试试LL库。

哪天试试啊,我还没用过LL库呢~

使用特权

评论回复
6
zhuotuzi| | 2020-10-12 11:47 | 只看该作者
LL的听说更轻便,前天试了一下写流水灯,还可以

使用特权

评论回复
7
yklstudent| | 2020-10-12 17:26 | 只看该作者
感谢楼主分享

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

111

主题

627

帖子

2

粉丝