【RTT-Studio】详细使用教程十:TM1638驱动数码管

【RTT-Studio】详细使用教程十:TM1638驱动数码管RTT Studio 详细使用教程十 TM1638 驱动数码管 tm1638

大家好,欢迎来到IT知识分享网。

一、简介

器件特性

  • 采用功率CMOS 工艺,串行接口(CLK,STB,DIO)
  • 显示模式 10 段×8 位
  • 键扫描(8×3bit)
  • 8级辉度可调,内置上电复位电路
  • 振荡方式:RC 振荡(450KHz+5%)

引脚功能说明

  • STB:片选端;在上升或下降沿初始化串行接口,随后等待接收指令。当STB 为高时,CLK被忽略
  • DIO:数据端;在时钟上升沿输入/输出串行数据
  • CLK:时钟端;输入时钟信号
  • K1~K3:键扫输入;输入该脚的数据在显示周期结束后被锁存。
  • SEG1/KS1~SEG8/KS8:段输出;P管开漏输出,也用作键扫描
  • SEG9,SEG10:段输出;P管开漏输出
  • GRID1~GRID8:位输出;N管开漏输出

二、TM1638地址组

1.显存地址中,如果GRIDn和SEGn对应的地址里数据为1,则连接到GRIDn和SEGn上的LED段落将会被点亮。 例如00H的数据为0X0F,则连到GIRD1和SEG1、SEG2、SEG3、SEG4上的LED段落将会被点亮。
在这里插入图片描述

2.每个Byte里储存6个键值数据,相对应的位置为1则代表对应位置有键按下。
在这里插入图片描述

B7 B6 指令类型
0 1 数据命令
1 1 地址命令
1 0 显示控制命令

在这里插入图片描述
在这里插入图片描述

4.地址命令用来设置要写入的数据的地址。数据写入有自增址和固定址两种,固定址每次写入数据需要指定要写入数据的地址。
在这里插入图片描述
显示控制命令主要是用来设置LED的亮度,以及显示开关。


三、TM1638的两种数码管使用方式

(1)共阴方式
  共阴数码管使用同一个阴极和多个阳极,因为GRID始终为低电平,所以只能由1个GRIDn端作为共阴极,而8个SEG端作为阳极。在这里插入图片描述
  在这里插入图片描述

这时每个数码管的显示数据由8个SEGn对应1个GRIDn端组成,由显存地址关系图可知每个非奇数地址便储存着1个数码管的显示数据。
  共阴数码管的显存数据写入比共阳方便很多,只用向一个地址写入8位数据即可。例如GRID1和SEG1~SEG8对应共阴LED1,要让其显示 0 则只用向 00H 地址写入 0X3F;
在这里插入图片描述
  共阴方式的不足则是无法使用SEG9和SEG10来组成共阴数码管,所以共阴方式最多可以使用8个数码管。多余的SEG9和SEG10仍可以使用,但必须采用共阳方式。

(2)共阳方式
  共阴数码管使用同一个阳极和多个阴极,因为GRID始终为低电平,所以只能由8个GRIDn端作为阴极,1个SEG端作为共阳极。
  在这里插入图片描述

这时每个数码管的显示数据由8个GRIDn对应1个SEGn端组成,由显存地址关系图可知:由8个偶数/奇数地址的共同一位组成一个数码管的8位显示数据。
  共阳数码管的数据写入比较麻烦,每为一个数码管写入一次数据都要向8个地址分别写入1位数据。例如GRID1~GRID8和SEG1对应共阴LED1,要让其显示0则要00H,02H,04H,06H,08H,0AH都写入1,向0CH和0EH中写入0
  在这里插入图片描述
  共阳方式的优点是可以使用多至10个数码管;缺点啧是数据的写入方式比较繁琐,并且需要额外增加数据转换。


四、TM1638数据格式

  • TM1638的数据读取和发送都在CLK的上升沿进行,因为DIO在时钟的下降沿控制N管动作,此时读数不稳定。
  • TM1638采取低位在前的数据格式,每次发送和读取都是1byte长度,即8位二进制数据
  • 每次STB拉低之后的第一个字节作为指令,处理指令时当前其它处理被终止。

串行数据传输格式
在这里插入图片描述

自增址模式下,只用写入一次地址即首地址,之后依次写入数据,每次写入数据,地址自动增加0X01。数据全部写入之后,上拉STB来作为结束的信号。
在这里插入图片描述

固定址模式下,每次写入数据需要先写入一次地址,为要写入的数据指定写入的地址,之后写入数据,然后上拉STB结束一次写入。
在这里插入图片描述

读数据以拉低STB写入读键值指令(0X42)作为开始,之后TM1638会依次按从低到高的顺序传送4byte的键值数据。读取4byte数据之后上拉STB结束读取。
在这里插入图片描述


五、按键扫描和键扫复用

按键扫描电路
  电路的连接方式如下图,Kn端作为列线,KSn端作为行线,当有键按下被扫描到,数据被存入键值寄存器。
在这里插入图片描述

按键扫描时在端口上的波形:
在这里插入图片描述

按键复用
  SEG1/KS1~SEG8/KS8是复用的端口,作为显示输出同时作为键扫输出端口。当存在按钮同时按下时,如S1,S2,SEG1和SEG2相当于被短路,此时D1,2D两个LED都会被点亮,从而造成显示错误。
  解决方法之一是在每个按键上串联一个二极管,如下图所示,也可以换成510Ω大小的电阻。
  在这里插入图片描述


六、完整代码

1.tm1638.c

/* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2024-05-09 IBM the first version */ #include "tm1638.h" #include "gpio.h" /*===================================================== 全局变量定义 =================================================*/ uint8_t segmented[10] = { 
   0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f}; // 段码值 uint16_t buffer[8] = { 
   0}; // 数据缓冲器 uint8_t sendData[16] = { 
   0}; // 发送数据缓冲区 /*===================================================== END =================================================*/ /*===================================================== 静态函数调用 ==================================================*/ / * @brief TM1638发送数据 * @param DATA:数据 */ static void TM1638_Write(uint8_t DATA) { 
    uint8_t i; for (i = 0; i < 8; i++) // 1Byte 8位数据 { 
    TM1638_CLK_LOW; // 拉低时钟线 if (DATA & 0x01) // 发送数据 { 
    TM1638_DIO_HIGH; } else { 
    TM1638_DIO_LOW; } DATA >>= 1; // 数据格式:低位在前 TM1638_CLK_HIGH; // 拉高时钟线,写入数据 } } / * @brief TM1638发送命令 * @param cmd */ static void TM1638_WriteCOM(uint8_t cmd) { 
    TM1638_STB_LOW; // 拉低片选线 TM1638_Write(cmd); // 写命令 TM1638_STB_HIGH; // 拉高片选线 } / * @brief 单个数码管显示值 * @param lednum :数码管编号 1 - 9 * @param value :显示的值 0 - 9 * @param decimal:是否带小数点 0 - 不带 1 - 带 */ static void LED_Display_value(uint8_t lednum, uint8_t value, uint8_t decimal) { 
    uint8_t i; for (i = 0; i < 8; i++) { 
    if (segmented[value] & (0x01 << i)) { 
    buffer[i] |= (0x01 << (lednum - 1)); } } if (decimal == 1) { 
    buffer[7] |= (0x01 << (lednum - 1)); } } / * @brief u16数据转成u8数据 */ static void Data_U16_To_U8(void) { 
    for (int i = 0; i < 16; i += 2) { 
    sendData[i] = buffer[i / 2]; sendData[i + 1] = buffer[i / 2] >> 8; } } / * @brief 发送数据到数码管 */ static void Send_Data_To_LED(void) { 
    TM1638_STB_LOW; // 拉低片选线,开始写数据 TM1638_Write(REG_FIRST_ADDR); // 写首地址 for (int i = 0; i < 16; ++i) // 发数据 { 
    TM1638_Write(sendData[i]); } TM1638_STB_HIGH; } / * @brief 关闭LED数码管显示 */ static void LED_Close_Display(void) { 
    memset(buffer, 0, sizeof(buffer)); Data_U16_To_U8(); Send_Data_To_LED(); } /*===================================================== END =================================================*/ /*===================================================== 外部调用 ==================================================*/ / * @brief TM1638初始化设置 */ void TM1638_Init(void) { 
    TM1638_WriteCOM(DATA_CMD_ADDR); // 设置地址自增 TM1638_WriteCOM(LED_DISPLAY_ADDR); // LED亮度设置 } / * @brief LED数码管显示 * @param pwr: 输出功率 * @param pt :输出脉宽 * @param it :输出时间间隔 */ void LED_Display_Value(uint16_t pwr, uint16_t pt, uint16_t it) { 
    LED_Close_Display(); LED_Display_value(1, pwr / 100, 0); LED_Display_value(2, pwr % 100 / 10, 0); LED_Display_value(3, pwr % 10, 0); LED_Display_value(4, pt / 100, 0); LED_Display_value(5, pt % 100 / 10, 0); LED_Display_value(6, pt % 10, 0); LED_Display_value(7, it / 100, 0); LED_Display_value(8, it % 100 / 10, 0); LED_Display_value(9, it % 10, 0); Data_U16_To_U8(); // u16数据转成u8数据 Send_Data_To_LED(); // 发送数据到数码管 } / * @brief 测试demo程序 */ void Test_Demo(void) { 
    LED_Close_Display(); LED_Display_value(1, 1, 1); LED_Display_value(2, 2, 1); LED_Display_value(3, 3, 1); LED_Display_value(4, 4, 1); LED_Display_value(5, 5, 1); LED_Display_value(6, 6, 1); LED_Display_value(7, 7, 1); LED_Display_value(8, 8, 1); LED_Display_value(9, 9, 1); Data_U16_To_U8(); // u16数据转成u8数据 Send_Data_To_LED(); // 发送数据到数码管 for (int i = 0; i < 8; i++) { 
    printf("buffer[%d]: 0x%x\n", i, buffer[i]); } for (int i = 0; i < 16; i++) { 
    printf("sendData[%d]: 0x%x\n", i, sendData[i]); } } /*===================================================== END =================================================*/ 

2.tm1638.h

/* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2024-05-09 IBM the first version */ #ifndef APPLICATIONS_HARDWARE_INC_TM1638_H_ #define APPLICATIONS_HARDWARE_INC_TM1638_H_ #include <rtthread.h> #include <drv_common.h> #include <string.h> /==================================================== 宏定义 ==================================================*/ #define DATA_CMD_ADDR 0x40 // 写数据、地址自增、普通模式 #define REG_FIRST_ADDR 0xc0 // 寄存器首地址 #define LED_DISPLAY_ADDR 0x8F // 显示开、亮度8级 #define LED_CLOSE_ADDR 0x80 // 显示关、亮度0级 #define TM1638_STB_HIGH rt_pin_write(TM1638_STB, SET); // 片选引脚拉高 #define TM1638_STB_LOW rt_pin_write(TM1638_STB, RESET); // 片选引脚拉低 #define TM1638_CLK_HIGH rt_pin_write(TM1638_CLK, SET); // 时钟引脚拉高 #define TM1638_CLK_LOW rt_pin_write(TM1638_CLK, RESET); // 时钟引脚拉低 #define TM1638_DIO_HIGH rt_pin_write(TM1638_DIO, SET); // 数据引脚拉高 #define TM1638_DIO_LOW rt_pin_write(TM1638_DIO, RESET); // 数据引脚拉低 /==================================================== END =================================================*/ /================================================= 函数及变量声明 ===============================================*/ extern void TM1638_Init(void); // TM1638初始化设置 extern void LED_Display_Value(uint16_t pwr, uint16_t pt, uint16_t it); // LED数码管显示 extern void Test_Demo(void); // 测试demo程序 /==================================================== END =================================================*/ #endif /* APPLICATIONS_HARDWARE_INC_TM1638_H_ */ 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/154337.html

(0)
上一篇 2025-02-26 17:26
下一篇 2025-02-26 17:33

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信