CH32V103单片机驱动TM1638多功能数码管LED按键模块

CH32V103单片机驱动TM1638多功能数码管LED按键模块

参考

CSDN hug567:STM32控制TM1638模块——基于正点原子精英STM32F103ZET6开发板

显示效果

TM1638显示CH32V103

接线

  • 硬件连接:
    • 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
    }
}


posted on 2021-09-29 11:32  lixiaole  阅读(829)  评论(0编辑  收藏  举报

导航