CH32V103单片机驱动TM1638多功能数码管LED按键模块
CH32V103单片机驱动TM1638多功能数码管LED按键模块
参考
CSDN hug567:STM32控制TM1638模块——基于正点原子精英STM32F103ZET6开发板
显示效果
接线
- 硬件连接:
- PA5--STB
- PA6--CLK
- PA7--DIO
修改内容
- 数码管码表:
- 添加“H”,和“V”两个数码管码表,注意数码管是共阴极的
- 用户函数:
- void loopTest(); 数码吗循环显示数字1-8,然后数码管逐个熄灭,间隔0.5秒
- void show_wch(); 数码管显示CH32V103
- void show_led(); 所有LED灯点亮
代码
所有函数放入main.c 文件
/*
*@Note
串口打印调试例程:
USART1_Tx(PA9)。
本例程演示使用 USART1(PA9) 作打印调试口输出。
驱动TM1638模块
硬件连接:PA5--STB,PA6--CLK,PA7--DIO
*/
#include "debug.h"
/* Global typedef */
/**
***************************************************************************************
* TM1638模块初始化头文件
* 硬件连接:PA5--STB,PA6--CLK,PA7--DIO
* TubePoint:数码管显示数字是否带小数点
* LightState:LED灯亮灭状态
* TM1638_Init():TM1638初始化函数
* TM1638_WriteData():TM1638写数据函数
* TM1638_WriteAddressData():TM1638指定地址写数据函数
* TM1638_Tube():TM1638指定数码管序号与显示数字函数
* TM1638_TubeOff():TM1638关闭指定数码管函数
* TM1638_Light():TM1638指定LED灯序号num与亮灭state函数
* TM1638_Read():TM1638读数据函数
* TM1638_ReadKey():TM1638读键扫数据函数
* 创建人:hug567
* 最后修改时间:2018-4-5
***************************************************************************************
*/
typedef enum {NoPoint = 0, Point = !NoPoint} TubePoint; //是否带小数点,Point:带,NoPoint:不带
typedef enum {LightOff = 0, LightOn = !LightOff} LightState; //灯开关状态,LightOn:开,LightOff:关
/* Global define */
void TM1638_Init(void); //TM1638初始化函数
void TM1638_WriteData(unsigned char data); //TM1638写数据函数
void TM1638_WriteAddressData(unsigned char addr,unsigned char data); //TM1638指定地址写数据函数
void TM1638_Tube(unsigned char serial, unsigned char num, TubePoint point); //TM1638指定数码管序号与显示数字函数
void TM1638_TubeOff(unsigned char serial); //TM1638关闭指定数码管函数
void TM1638_Light(unsigned char num, LightState state); //TM1638指定LED灯序号num与亮灭state函数
unsigned char TM1638_Read(void); //TM1638读数据函数
unsigned char TM1638_ReadKey(void); //TM1638读键扫数据函数
/* Global Variable */
// 额外添加H,V(U)两个管段,共阴极,不带小数点
//unsigned char TM1638_LED[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07, //共阴极数码管段码,不带小数点
// 0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71}; //0~F,1亮0灭
unsigned char TM1638_LED[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07, //共阴极数码管段码,不带小数点
0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,0x76,0x3E}; //0~F,H,V亮0灭
unsigned char TM1638_LED_P[]={0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87, //共阴极数码管段码,带小数点
0xFF,0xEF,0xF7,0xFC,0xB9,0xDE,0xF9,0xF1}; //0~F,1亮0灭
/* User Test */
void loopTest();
void show_wch();
void show_led();
/*******************************************************************************
* Function Name : main
* Description : Main program.
* Input : None
* Return : None
*******************************************************************************/
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Init();
USART_Printf_Init(115200);
printf("SystemClk:%d\r\n",SystemCoreClock);
printf("This is printf example\r\n");
TM1638_Init();
// 数码管和LED状态会一直保持不变
show_led();
show_wch();
while(1)
{
show_led();
show_wch();
Delay_Ms(2000);
TM1638_Init(); //重新初始化清除所有显示内容
Delay_Ms(500);
loopTest(); // 循环点亮数码管和LED,间隔0.5秒
}
}
/*******************************************************************************
* Function Name : show_wch
* Description : 数码管显示 CH32V103
* Input : None
* Return : None
*******************************************************************************/
void show_wch()
{
// 数码管显示函数,参数分别代表从左到右第几段,显示数组中什么数字,无小数点
TM1638_Tube(1,0x0C,NoPoint); // C
TM1638_Tube(2,0x10,NoPoint); // H 0x10代表数组第17个元素H
TM1638_Tube(3,0x03,NoPoint); // 3
TM1638_Tube(4,0x02,NoPoint); // 2
TM1638_Tube(5,0x11,NoPoint); // V 0x10代表数组第18个元素V
TM1638_Tube(6,0x01,NoPoint); // 1
TM1638_Tube(7,0x00,NoPoint); // 0
TM1638_Tube(8,0x03,NoPoint); // 3
}
/*******************************************************************************
* Function Name : show_led
* Description : 所有LED指示灯点亮
* Input : None
* Return : None
*******************************************************************************/
void show_led()
{
for (int var = 1; var <= 8; ++var) {
TM1638_Light(var, LightOn);
}
}
/*******************************************************************************
* Function Name : loopTest
* Description : 循环点亮LED和数码管
* Input : None
* Return : None
*******************************************************************************/
void loopTest()
{
for (int var = 1; var <= 8; ++var) {
TM1638_Light(var, LightOn);
TM1638_Tube(var,var,NoPoint);
Delay_Ms(500);
}
Delay_Ms(500);
for (int var = 1; var <= 8; ++var) {
TM1638_Light(var, LightOff);
TM1638_TubeOff(var);
Delay_Ms(500);
}
Delay_Ms(500);
}
/**
* TM1638写数据函数
* 参数:data:要写入的8位数据
* 返回值:无
*/
void TM1638_WriteData(unsigned char data) //TM1638写数据函数
{
unsigned char i;
for(i=0;i<8;i++)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_6); //CLK=0
if(data&0x01)
{
GPIO_SetBits(GPIOA,GPIO_Pin_7); //DIO=1
}
else
{
GPIO_ResetBits(GPIOA,GPIO_Pin_7); //DIO=0
}
data>>=1;
GPIO_SetBits(GPIOA,GPIO_Pin_6); //CLK=1
}
}
/**
* TM1638指定地址写数据函数
* 参数1:addr:要写入数据的地址
* 参数2:data:要写入的8位数据
* 返回值:无
*/
void TM1638_WriteAddressData(unsigned char addr,unsigned char data) //TM1638指定地址写数据函数
{
GPIO_ResetBits(GPIOA,GPIO_Pin_5); //STB=0
TM1638_WriteData(addr); //地址
TM1638_WriteData(data); //数据
GPIO_SetBits(GPIOA,GPIO_Pin_5); //STB=1
}
/**
* TM1638指定数码管序号与显示数字函数
* 参数1:serial:数码管序号,1-8
* 参数2:num:要显示的数字,0-F
* 参数3:point:是否带小数点,Point:带,NoPoint:不带
* 返回值:无
*/
void TM1638_Tube(unsigned char serial, unsigned char num, TubePoint point) //TM1638指定数码管序号与显示数字函数
{
GPIO_ResetBits(GPIOA,GPIO_Pin_5); //STB=0
TM1638_WriteData(0x44); //普通模式,固定地址,写数据到显示寄存器
GPIO_SetBits(GPIOA,GPIO_Pin_5); //STB=1
GPIO_ResetBits(GPIOA,GPIO_Pin_5); //STB=0
TM1638_WriteData(0x88); //显示开,亮度第1级
GPIO_SetBits(GPIOA,GPIO_Pin_5); //STB=1
if(point == Point) //带小数点
{
TM1638_WriteAddressData(0XC0+2*(serial-1),TM1638_LED_P[num]); //第serial个数码管显示num,带小数点
}
else if(point == NoPoint) //不带小数点
{
TM1638_WriteAddressData(0XC0+2*(serial-1),TM1638_LED[num]); //第serial个数码管显示num,不带小数点
}
}
/**
* TM1638关闭指定数码管函数
* 参数:serial:数码管序号
* 返回值:无
*/
void TM1638_TubeOff(unsigned char serial) //TM1638关闭指定数码管函数
{
GPIO_ResetBits(GPIOA,GPIO_Pin_5); //STB=0
TM1638_WriteData(0x44); //普通模式,固定地址,写数据到显示寄存器
GPIO_SetBits(GPIOA,GPIO_Pin_5); //STB=1
GPIO_ResetBits(GPIOA,GPIO_Pin_5); //STB=0
TM1638_WriteData(0x88); //显示开,亮度第1级
GPIO_SetBits(GPIOA,GPIO_Pin_5); //STB=1
TM1638_WriteAddressData(0XC0+2*(serial-1),0x00); //第serial个数码管灭
}
/**
* TM1638指定LED灯序号num与亮灭state函数
* 参数1:num:LED灯序号
* 参数2:state:LED灯状态,LightOn:开,LightOff:关
* 返回值:无
*/
void TM1638_Light(unsigned char num, LightState state) //TM1638指定LED灯序号num与亮灭state函数
{
GPIO_ResetBits(GPIOA,GPIO_Pin_5); //STB=0
TM1638_WriteData(0x44); //普通模式,固定地址,写数据到显示寄存器
GPIO_SetBits(GPIOA,GPIO_Pin_5); //STB=1
GPIO_ResetBits(GPIOA,GPIO_Pin_5); //STB=0
TM1638_WriteData(0x88); //显示开,亮度第1级
GPIO_SetBits(GPIOA,GPIO_Pin_5); //STB=1
if(state == LightOn)
{
TM1638_WriteAddressData(0XC0+2*(num-1)+1,0X01); //第num个灯亮
}
else if(state == LightOff)
{
TM1638_WriteAddressData(0XC0+2*(num-1)+1,0X00); //第num个灯灭
}
}
/**
* TM1638读数据函数
* 参数:无
* 返回值:读取的8位数据
*/
unsigned char TM1638_Read(void) //读数据函数
{
unsigned char i,DIO,temp=0;
GPIO_SetBits(GPIOA,GPIO_Pin_7); //DIO=1,设置为输入
for(i=0;i<8;i++)
{
temp>>=1;
GPIO_ResetBits(GPIOA,GPIO_Pin_6); //CLK=0
DIO = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_7); //读取DIO值
if(DIO)
temp|=0x80; //按位或:与0或不变、与1或置1
GPIO_SetBits(GPIOA,GPIO_Pin_6); //CLK=1
}
return temp;
}
/**
* TM1638读键扫数据函数
* 参数:无
* 返回值:读取的按键号,1~8
*/
unsigned char TM1638_ReadKey(void) //TM1638读键扫数据函数
{
unsigned char c[4],i,key_value=0;
GPIO_ResetBits(GPIOA,GPIO_Pin_5); //STB=0,开始写命令
TM1638_WriteData(0x42); //普通模式,地址自动增加,读键扫数据
for(i=0;i<4;i++)
c[i]=TM1638_Read(); //读取键值
GPIO_SetBits(GPIOA,GPIO_Pin_5); //STB=1,读键值结束
for(i=0;i<4;i++)
{
if(c[i]!=0)
{
key_value = 2*i+(c[i]+14)/15;
key_value = (key_value+7*(1-key_value%2)+1)/2; //获取按键值(1-8)
break;
}
}
return key_value;
}
/**
* TM1638初始化函数
* 参数:无
* 返回值:无
*/
void TM1638_Init(void) //TM1638初始化函数
{
unsigned char i; //临时变量
GPIO_InitTypeDef GPIO_InitStructure; //GPIO参数设置结构体
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //APB2外设时钟使能:GPIOA
//接TM1638引脚: PA5--STB,PA6--CLK,PA7--DIO
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7; //选定引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //工作方式:推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //最大速度50MHz
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化引脚
GPIO_ResetBits(GPIOA,GPIO_Pin_5); //STB=0
TM1638_WriteData(0x44); //普通模式,固定地址,写数据到显示寄存器
GPIO_SetBits(GPIOA,GPIO_Pin_5); //STB=1
GPIO_ResetBits(GPIOA,GPIO_Pin_5); //STB=0
TM1638_WriteData(0x88); //显示开,亮度第1级
GPIO_SetBits(GPIOA,GPIO_Pin_5); //STB=1
for(i=0;i<16;i++)
{
TM1638_WriteAddressData(0XC0+i,0X00); //全地址写入0X00
}
}