1.チップの紹介
TM1638は、MCUデジタルインターフェース、データラッチ、LED高電圧ドライブ、キーボードスキャン、およびその他の回路を統合した、キーボードスキャンインターフェースを備えたLED(発光ダイオードディスプレイ)ドライブ制御専用の回路です。主に冷蔵庫、エアコン、ホームシアターなどのハイエンドディスプレイドライバーに使用されています。 |
---|
•パワーCMOS技術の採用•表示モード10セグメント×8ビット•キースキャン(8×3ビット)•輝度調整回路(8レベル調整可能デューティサイクル) |
•シリアルインターフェース(CLK、STB、DIO)•発振モード:RC発振(450KHz + 5%)•内蔵パワーオンリセット回路•SOP28パッケージ |
詳細については、TM1638公式ウェブサイトのデータシートをダウンロードしてください。
2.モジュールの紹介
- 8つのデジタルチューブ、8つの発光ダイオード、8つのボタン(このモジュールは本当に縁起の良いものです)
- 5ピンVCC-GND-STB-CLK-DIOは左側にリードしています
- プラットフォームは、手元にある最小のSTM32F103C8T6システムボードであるJ-Linkダウンローダーを使用します
3.コードの実装
1)いくつかの説明
- 他のブロガーによるチップの説明の関連するコード1を研究することで、私は自分の要素のいくつかを統合および変更し、コード実行の効率を改善するためにロジックのいくつかを最適化しましたが、欠点もあります。訂正してください。
- ここでのTM1638_Display_Num()関数のパラメーターは、文字列型に最適化してから、C言語の文字列関連関数を使用して、関数内で文字列関連の変換を実行できます。ここでは行いません。興味がある場合は、試してみてください。
2)コード上
- TM1638.h
#ifndef _TM1638_H_
#define _TM1638_H_
/**
***************************************************************************************
* TM1638模块功能实现源文件
* 硬件连接:PA5--STB,PA6--CLK,PA7--DIO
* 创建人:郭凯瑞_carry
* 最后修改时间:2021-2-26
***************************************************************************************
**/
#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
- TM1638.c
/**
***************************************************************************************
* TM1638模块功能实现源文件
* 硬件连接:PA5--STB,PA6--CLK,PA7--DIO
* 创建人:郭凯瑞_carry
* 最后修改时间:2021-2-26
***************************************************************************************
**/
#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
}
}
/***************************************************************************************/
/**
* TM1638写数据/命令函数
* 参数:data:要写入的8位数据
* 返回值:无
*/
void TM1638_Write_Data(u8 data) //TM1638写数据函数
{
STB_0();
TM1638_Write_Byte(data);
STB_1();
}
void (*TM1638_Write_Cmd)(u8)=TM1638_Write_Data;//给函数起一个别名,函数指针
/***************************************************************************************/
/***************************************************************************************/
/**
* TM1638写地址+数码组合函数,用于固定地址显示
* 参数:cmd:要写入的8位数据
* 返回值:无
*/
void TM1638_Write_Addr_Bond(u8 addr,u8 data) //TM1638写数据函数
{
STB_0();
TM1638_Write_Byte(addr);
TM1638_Write_Byte(data);
STB_1();
}
/***************************************************************************************/
/***************************************************************************************/
/**
* TM1638固定地址显示函数
* 参数1:data:写入的数字,长度八位
* 返回值:无
*/
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]);
}
/***************************************************************************************/
/***************************************************************************************/
/**
* TM1638指定地址显示数码,0-F
* 参数1:num:数码管位置12345678
* 参数2:seg:字符0-F
* 参数3:p:N/Y
* 返回值:无
*/
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);
}
/***************************************************************************************/
/***************************************************************************************/
/**
* TM1638指定LED亮灭
* 参数1:num:LED位置
* 参数2:light:OFF/ON
* 返回值:无
*/
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);
}
/***************************************************************************************/
/***************************************************************************************/
/**
* TM1638全清
* 参数1:无
* 返回值:无
*/
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
}
}
/***************************************************************************************/
/***************************************************************************************/
/**
* TM1638关闭指定数码管函数
* 参数:serial:数码管序号1-8
* 返回值:无
*/
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);
}
/***************************************************************************************/
/***************************************************************************************/
/**
* TM1638读数据函数
* 参数:无
* 返回值:读取的8位数据
*/
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;
}
/***************************************************************************************/
/***************************************************************************************/
/**
* TM1638读键扫数据函数
* 参数:无
* 返回值:读取的按键号,1~8
*/
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);//返回按键值,与模块上的相对应
}
/***************************************************************************************/
/***************************************************************************************/
/**
* TM1638-GPIO初始化函数
* 参数:无
* 返回值:无
*/
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); //初始化引脚
}
/***************************************************************************************/
/***************************************************************************************/
/**
* TM1638初始化函数
* 参数:无
* 返回值:无
*/
void TM1638_Init(void) //TM1638初始化函数
{
TM1638_GPIO_Init();//GPIO初始化
TM1638_Clear();
}
/***************************************************************************************/
- main.hと完全なテストプロジェクトがアップロードされ、レビュー中です。ファンはここからダウンロードできます。
四.文末
最後に、レンダリングを見てみましょう。後で、時間があれば、データマニュアルにモジュールドライバーの記述に関する記事を書きます。最近、ゲームで忙しくしています。