硬件学习之路——STM32之TM1638

   日期:2021-02-28     浏览:315    评论:0    
核心提示:目录一.芯片简介二.模块介绍三.代码实现1)一些说明2)上代码四.文末一.芯片简介TM1638是带键盘扫描接口的LED(发光二极管显示器)驱动控制专用电路,内部集成有MCU 数字接口、数据锁存器、LED 高压驱动、键盘扫描等电路。主要应用于冰箱、空调 、家庭影院等产品的高段位显示屏驱动。• 采用功率CMOS 工艺 • 显示模式 10 段×8 位 • 键扫描(8×3bit)• 辉度调节电路(占空比8 级可调)• 串行接口(CLK,STB,DIO) • 振荡方式:RC 振荡(

目录

  • 一.芯片简介
  • 二.模块介绍
  • 三.代码实现
    • 1)一些说明
    • 2)上代码
  • 四.文末

一.芯片简介

TM1638是带键盘扫描接口的LED(发光二极管显示器)驱动控制专用电路,内部集成有MCU 数字接口、数据锁存器、LED 高压驱动、键盘扫描等电路。主要应用于冰箱、空调 、家庭影院等产品的高段位显示屏驱动。
• 采用功率CMOS 工艺 • 显示模式 10 段×8 位 • 键扫描(8×3bit)• 辉度调节电路(占空比8 级可调)
• 串行接口(CLK,STB,DIO) • 振荡方式:RC 振荡(450KHz+5%) • 内置上电复位电路 • 采用SOP28封装

更多详细资料请下载TM1638官网数据手册

二.模块介绍

  1. 八位数码管,八个发光二极管,八个按键(这个模块真吉利)
  2. 左侧引出VCC-GND-STB-CLK-DIO五个引脚
  3. 平台用的是手头的STM32F103C8T6最小系统板,J-Link下载器

三.代码实现

1)一些说明

  • 通过学习其他博主对于该芯片的讲解的相关代码1,我进行了整合与修改,加入了自己的一些元素,部分逻辑我进行了优化,使代码执行效率提高,但也有不足的地方,还请大家指正。
  • TM1638_Display_Num()函数这里的参量可以优化成字符串类型的,然后在函数内部利用C语言字符串相关函数进行串的相关转换,这里我就不做了,大家有兴趣可以试一下。

2)上代码

  1. TM1638.h
#ifndef _TM1638_H_
#define _TM1638_H_

#include "stm32f10x.h"
 
typedef enum { N = 0x00, Y = 0x80} PointState; //是否带小数点 Y:带,N:不带
 
typedef enum { OFF = 0x00, ON = 0x01} LightState; //灯开关状态 On:开,Off:关

//TM1638模块相关引脚定义
#define STB GPIO_Pin_5
#define CLK GPIO_Pin_6
#define DIO GPIO_Pin_7
#define GPIO_TM1638 GPIOA
#define GPIO_Pin_TM1638 STB|CLK|DIO
#define RCC_TM1638 RCC_APB2Periph_GPIOA

//引脚高低电平设置
#define STB_0() GPIO_ResetBits(GPIO_TM1638,STB)
#define STB_1() GPIO_SetBits(GPIO_TM1638,STB)

#define CLK_0() GPIO_ResetBits(GPIO_TM1638,CLK)
#define CLK_1() GPIO_SetBits(GPIO_TM1638,CLK)

#define DIO_0() GPIO_ResetBits(GPIO_TM1638,DIO)
#define DIO_1() GPIO_SetBits(GPIO_TM1638,DIO)

#define DIO_Read() GPIO_ReadInputDataBit(GPIO_TM1638,DIO)

//用户层函数
void TM1638_Init(void); //TM1638初始化函数
void TM1638_Display_Num(u32 data); //显示数字
void TM1638_Display_SEG(unsigned int num,unsigned char seg,PointState p); //选择数码管显示0-F
void TM1638_Display_LED(unsigned int num,LightState light); //指定led亮灭

unsigned char TM1638_ReadKey(void); //TM1638读键扫数据函数
void TM1638_SEG_Off(unsigned char num);  //TM1638关闭指定数码管函数
void TM1638_Clear(void); //TM1638全清

//底层函数
void TM1638_Write_Byte(u8 byte); //TM1638单写数据,需要在函数外对STB操作
void TM1638_Write_Data(u8 data); //TM1638一个完整数据写入
void TM1638_Write_Addr_Bond(u8 addr,u8 data); //TM1638指定地址写入数据
unsigned char TM1638_Read(void); //TM1638读数据函数
void TM1638_GPIO_Init(void); //TM1638引脚初始化函数

#endif

  1. TM1638.c


#include "stm32f10x.h" //stm32f10x系列芯片头文件
#include "TM1638.h" //tm1638模块实现头文件

unsigned char TM1638_Arr_SEG[]= { 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07, //共阴极数码管段码,不带小数点
                                 0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
                                 0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,  //共阴极数码管段码,带小数点
                                 0xFF,0xEF,0xF7,0xFC,0xB9,0xDE,0xF9,0xF1
                                }; //0~F,1亮0灭

//共阴极数码管段码,不带小数点,display函数用
unsigned char TM1638_Arr_SEG_Display[]= {    0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
                                            0,   0,   0,   0,   0,   0,0x3F,0x06,0x5B,0x4F,//0-9
                                            0x66,0x6D,0x7D,0x07,0x7F,0x6F,   0,   0,   0,   0,
                                            0,   0,   0,0x77,0x7C,0x39,0x5E,0x79,0x71,   0
                                        };

u8 TM1638_Addr_SEG[8]= { 0xC0,0xC2,0xC4,0xC6,0xC8,0xCA,0xCC,0xCE}; //模块从右到左的八个数码管
u8 TM1638_Addr_LED[8]= { 0xC1,0xC3,0xC5,0xC7,0xC9,0xCB,0xCD,0xCF}; //模块从右到左的八个发光二极管

void TM1638_Write_Byte(u8 byte) //TM1638单写数据
{ 
    u8 i;
    for(i=0; i<8; i++)
    { 
        CLK_0(); //CLK=0
        if(byte&0x01)
        { 
            DIO_1(); //DIO=1
        }
        else
        { 
            DIO_0(); //DIO=0
        }
        byte>>=1;
        CLK_1(); //CLK=1
    }
}


void TM1638_Write_Data(u8 data) //TM1638写数据函数
{ 
    STB_0();
    TM1638_Write_Byte(data);
    STB_1();
}

void (*TM1638_Write_Cmd)(u8)=TM1638_Write_Data;//给函数起一个别名,函数指针




void TM1638_Write_Addr_Bond(u8 addr,u8 data) //TM1638写数据函数
{ 
    STB_0();
    TM1638_Write_Byte(addr);
    TM1638_Write_Byte(data);
    STB_1();
}




void TM1638_Display_Num(u32 data)
{ 
    unsigned int dataL=0,dataR=0;
    dataL=data/10000;
    dataR=data%10000;
    TM1638_Write_Cmd(0x44);//固定地址,写数据
    TM1638_Write_Cmd(0x88);//显示开,亮度1

    TM1638_Write_Addr_Bond(TM1638_Addr_SEG[0],TM1638_Arr_SEG[dataL/1000]);
    TM1638_Write_Addr_Bond(TM1638_Addr_SEG[1],TM1638_Arr_SEG[dataL%1000/100]);
    TM1638_Write_Addr_Bond(TM1638_Addr_SEG[2],TM1638_Arr_SEG[dataL%100/10]);
    TM1638_Write_Addr_Bond(TM1638_Addr_SEG[3],TM1638_Arr_SEG[dataL%10]);
    TM1638_Write_Addr_Bond(TM1638_Addr_SEG[4],TM1638_Arr_SEG[dataR/1000]);
    TM1638_Write_Addr_Bond(TM1638_Addr_SEG[5],TM1638_Arr_SEG[dataR%1000/100]);
    TM1638_Write_Addr_Bond(TM1638_Addr_SEG[6],TM1638_Arr_SEG[dataR%100/10]);
    TM1638_Write_Addr_Bond(TM1638_Addr_SEG[7],TM1638_Arr_SEG[dataR%10]);
}




void TM1638_Display_SEG(unsigned int num,unsigned char seg,PointState p)
{ 
    TM1638_Write_Cmd(0x44);//固定地址,写数据
    TM1638_Write_Cmd(0x88);//显示开,亮度1

    TM1638_Write_Addr_Bond(TM1638_Addr_SEG[num-1],TM1638_Arr_SEG_Display[seg-32]|p);
}




void TM1638_Display_LED(unsigned int num,LightState light)
{ 
    TM1638_Write_Cmd(0x44);//固定地址,写数据
    TM1638_Write_Cmd(0x88);//显示开,亮度1

    TM1638_Write_Addr_Bond(TM1638_Addr_LED[num],light);
}




void TM1638_Clear(void)
{ 
    u8 i;
    TM1638_Write_Data(0x44); //普通模式,固定地址,写数据到显示寄存器
    TM1638_Write_Data(0x88); //显示开,亮度第1级
    for(i=0; i<16; i++)
    { 
        TM1638_Write_Addr_Bond(0xC0+i,0x00); //全地址写入0x00
    }
}




void TM1638_SEG_Off(unsigned char num)  //TM1638关闭指定数码管函数
{ 
    TM1638_Write_Cmd(0x44);//固定地址,写数据
    TM1638_Write_Cmd(0x88);//显示开,亮度1

    TM1638_Write_Addr_Bond(TM1638_Addr_SEG[num-1],0x80);
}




unsigned char TM1638_Read(void) //读数据函数
{ 
    unsigned char i,data,temp=0;

    DIO_1();  //DIO=1,设置为输入
    for(i=0; i<8; i++)
    { 
        temp>>=1;
        CLK_0(); //CLK=0
        data = DIO_Read();  //读取DIO值
        if(data) temp|=0x80; //按位或:与0或不变、与1或置1
        CLK_1(); //CLK=1
    }
    return temp;
}




unsigned char TM1638_ReadKey(void)  //TM1638读键扫数据函数
{ 
    unsigned char c[4],i,key_value=0;

    STB_0();  //STB=0,开始写命令
    TM1638_Write_Byte(0x42);  //普通模式,地址自动增加,读键扫数据
    for(i=0; i<4; i++)	c[i]=TM1638_Read(); //读取键值
    STB_1();  //STB=1,读键值结束

    //数据处理
    for(i=0; i<4; i++)
        key_value|=c[i]<<i;
    for(i=0; i<8; i++)
        if((0x01<<i)==key_value) break;
    return (i+1);//返回按键值,与模块上的相对应
}




void TM1638_GPIO_Init(void)
{ 
    GPIO_InitTypeDef GPIO_InitStructure; //GPIO参数设置结构体
    RCC_APB2PeriphClockCmd(RCC_TM1638,ENABLE);  //APB2外设时钟使能:GPIOA

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_TM1638; //选定引脚
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //工作方式:推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //最大速度50MHz
    GPIO_Init(GPIO_TM1638, &GPIO_InitStructure); //初始化引脚
}




void TM1638_Init(void) //TM1638初始化函数
{ 
    TM1638_GPIO_Init();//GPIO初始化
    TM1638_Clear();
}


  1. main.h以及完整测试工程已上传,正在审核,粉丝们可以在这里下载。

四.文末

最后看一下效果图吧,后面有时间再做一个看数据手册写模块驱动的文章吧,最近忙比赛去了。

  1. https://blog.csdn.net/qtyt567/article/details/79827436 ↩︎

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
更多>相关资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服