首页 > 其他分享 >【嵌入式】微芯旺KungFu32A156MQT使用TM1638和TIMER实现流水灯和时钟

【嵌入式】微芯旺KungFu32A156MQT使用TM1638和TIMER实现流水灯和时钟

时间:2023-02-07 13:34:10浏览次数:43  
标签:KungFu32A156MQT void unsigned TIMER char BTIM 微芯旺 TM1638 include

TM1638代码如下

#ifndef TM1638_H_
#define TM1638_H_

#include"system_init.h"
#include"MYGPIO.h"

#define DIO_GPIO_SFR        GPIOA_SFR
#define DIO_GPIO_PIN_MASK    GPIO_PIN_MASK_1
#define CLK_GPIO_SFR        GPIOD_SFR
#define CLK_GPIO_PIN_MASK    GPIO_PIN_MASK_4
#define STB_GPIO_SFR        GPIOD_SFR
#define STB_GPIO_PIN_MASK    GPIO_PIN_MASK_5

#define    TM1638_DIO_H    TM1638_DIO_on()        ///<DIO拉高
#define    TM1638_DIO_L    TM1638_DIO_off()    ///<DIO拉低
#define TM1638_DIO_READ    TM1638_DIO_read()    ///<读取DIO

#define    TM1638_CLK_H    TM1638_CLK_on()                ///<CLK拉高
#define    TM1638_CLK_L    TM1638_CLK_off()            ///<CLK拉低
#define    TM1638_STB_H    TM1638_STB_on()                ///<STB拉高
#define    TM1638_STB_L    TM1638_STB_off()            ///<STB拉低

//共阴数码管显示代码
extern unsigned char dis[11];
extern unsigned char dis2;
extern unsigned char dis3;

void TM1638_DIO_on();

void TM1638_CLK_on();

void TM1638_STB_on();

void TM1638_DIO_off();

void TM1638_CLK_off();

void TM1638_STB_off();

int TM1638_DIO_read();

//写数据函数
void TM1638_Write(unsigned char Data);

//发送命令
void Write_Command(unsigned char Command);

//指定地址写入数据
void Write_Data(unsigned char add,unsigned char Data);

//读数据函数
unsigned char TM1638_Read(void);

//读取按键值
unsigned char Read_key(void);

//TM1638初始化函数
void TM1638_init(void);

#endif /* TM1638_H_ */
#include"tm1638.h"
#include"MYGPIO.h"

//共阴数码管显示代码
unsigned char dis[11]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00};
unsigned char dis2=0x40;//一杠
unsigned char dis3=0x80;//一点

void TM1638_DIO_on(){
    GPIOInit_Output_Config(DIO_GPIO_SFR, DIO_GPIO_PIN_MASK);
    GPIO_Set_Output_Data_Bits(DIO_GPIO_SFR, GPIO_PIN_MASK_1, Bit_SET);///<DIO拉高
}

void TM1638_CLK_on(){
    GPIOInit_Output_Config(CLK_GPIO_SFR, CLK_GPIO_PIN_MASK);
    GPIO_Set_Output_Data_Bits(CLK_GPIO_SFR, CLK_GPIO_PIN_MASK, Bit_SET);///<DIO拉高
}

void TM1638_STB_on(){
    GPIOInit_Output_Config(STB_GPIO_SFR, STB_GPIO_PIN_MASK);
    GPIO_Set_Output_Data_Bits(STB_GPIO_SFR, STB_GPIO_PIN_MASK, Bit_SET);///<DIO拉高
}

void TM1638_DIO_off(){
    GPIOInit_Output_Config(DIO_GPIO_SFR, DIO_GPIO_PIN_MASK);
    GPIO_Set_Output_Data_Bits(DIO_GPIO_SFR, DIO_GPIO_PIN_MASK, Bit_RESET);///<DIO拉低
}

void TM1638_CLK_off(){
    GPIOInit_Output_Config(CLK_GPIO_SFR, CLK_GPIO_PIN_MASK);
    GPIO_Set_Output_Data_Bits(CLK_GPIO_SFR, CLK_GPIO_PIN_MASK, Bit_RESET);///<DIO拉低
}

void TM1638_STB_off(){
    GPIOInit_Output_Config(STB_GPIO_SFR, STB_GPIO_PIN_MASK);
    GPIO_Set_Output_Data_Bits(STB_GPIO_SFR, STB_GPIO_PIN_MASK, Bit_RESET);///<DIO拉低
}

int TM1638_DIO_read(){
    GPIOInit_Input_Config(DIO_GPIO_SFR, DIO_GPIO_PIN_MASK);
    return GPIO_Read_Input_Data_Bit(DIO_GPIO_SFR, DIO_GPIO_PIN_MASK);
}

//写数据函数
void TM1638_Write(unsigned char Data){
    unsigned char i;
    for(i=0;i<8;i++){
        TM1638_CLK_L;
        if(Data&0x01)
            TM1638_DIO_H;
        else
            TM1638_DIO_L;
        Data>>=1;
        TM1638_CLK_H;
    }
}

//发送命令
void Write_Command(unsigned char Command){
    TM1638_STB_L;
    TM1638_Write(Command);
    TM1638_STB_H;
}

//指定地址写入数据
void Write_Data(unsigned char add,unsigned char Data){
    TM1638_STB_L;
    TM1638_Write(0x00|add);
    TM1638_Write(Data);
    TM1638_STB_H;
}

//读数据函数
unsigned char TM1638_Read(void)
{
    unsigned char i;
    unsigned char temp=0;
    TM1638_DIO_READ;
    for(i=0;i<8;i++)
    {
        temp>>=1;
        TM1638_CLK_L;
        if(TM1638_DIO_READ)
            temp|=0x80;
        TM1638_CLK_H;
    }
    return temp;
}

//读取按键值
unsigned char Read_key(void)
{
    unsigned char c[4],i,key_value=0;
    TM1638_STB_L;
    TM1638_Write(0x42);                   //读键扫数据 命令
    for(i=0;i<4;i++)
        c[i]=TM1638_Read();
    TM1638_STB_H;
    //4个字节数据合成一个字节
    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;
}

//TM1638初始化函数
void TM1638_init(void){
    unsigned char i;
    GPIOInit_Output_Config(DIO_GPIO_SFR, DIO_GPIO_PIN_MASK);///<DIO
    GPIOInit_Output_Config(CLK_GPIO_SFR, CLK_GPIO_PIN_MASK);///CLK
    GPIOInit_Output_Config(STB_GPIO_SFR, STB_GPIO_PIN_MASK);///STB
    Write_Command(0x8F);
    Write_Command(0x40);        //采用地址自动加1
    TM1638_STB_L;
    TM1638_Write(0xc0);         //设置起始地址
    for(i=0;i<16;i++)             //传送16个字节的数据
    TM1638_Write(0x00);
    TM1638_STB_H;
    for(i=0;i<8;i++)
        Write_Data(i,dis[10]);    //初始化寄存器
}

TIMER配置代码如下

#ifndef TIMER_H_
#define TIMER_H_

#include "system_init.h"

/*描述基本定时器初始化配置
* 输入  BTIMx:取值为T14_SFR
*    Peripheral:取值为INT_T14
*/
void BASIC_TIMER_Config(BTIM_SFRmap* BTIMx, InterruptIndex Peripheral);

#endif /* TIMER_H_ */
#include"TIMER.h"
/*描述基本定时器初始化配置
* 输入  BTIMx:取值为T14_SFR
*    Peripheral:取值为INT_T14
*/
void BASIC_TIMER_Config(BTIM_SFRmap* BTIMx, InterruptIndex Peripheral)
{
    //定时器时钟源选用SCLK  设周期为50000 设预分频23+1=24分频 120M主频 定时10ms进一次中断
    //分频后,定时器的频率为120/24=5M,每秒进入中断的次数为5M/50000=100次,,即是10ms进一次
    TIM_Reset(BTIMx);                                                //定时器外设复位,使能外设时钟
    BTIM_Updata_Immediately_Config(BTIMx,TRUE);                        //立即更新控制
    BTIM_Updata_Enable(BTIMx,TRUE);                                    //配置更新使能
    BTIM_Work_Mode_Config(BTIMx,BTIM_TIMER_MODE);                    //定时模式选择
    BTIM_Set_Counter(BTIMx,0);                                        //定时器计数值
    BTIM_Set_Period(BTIMx,50000);                                    //定时器周期值50000
    BTIM_Set_Prescaler(BTIMx,23);                                    //定时器预分频值23+1=24
    BTIM_Counter_Mode_Config(BTIMx,BTIM_COUNT_UP_OF);                //向上计数,上溢产生中断标志
    BTIM_Clock_Config(BTIMx,BTIM_SCLK);                                //选用SCLK时钟
    INT_Interrupt_Priority_Config(Peripheral,4,0);                    //抢占优先级4,子优先级0
    BTIM_Overflow_INT_Enable(BTIMx,TRUE);                            //计数溢出中断使能
    INT_Interrupt_Enable(Peripheral,TRUE);                            //外设中断使能
    INT_Clear_Interrupt_Flag(Peripheral);                            //清中断标志
    BTIM_Cmd(BTIMx,TRUE);                                            //定时器启动控制使能
    INT_Stack_Align_Config(INT_STACK_SINGLE_ALIGN);                    //中断自动堆栈使用单字对齐
    INT_All_Enable (TRUE);                                            //全局可屏蔽中断使能,该中断使能控制不包含复位/NMI/硬件错误中断
}

时钟clock代码如下

#ifndef CLOCK_H_
#define CLOCK_H_

#include"tm1638.h"
#include"TIMER.h"

extern unsigned char hh;
extern unsigned char mm;
extern unsigned char ss;

void refresh();
void clock_init();

#endif /* CLOCK_H_ */
#include"clock.h"

unsigned char hh=17;//小时
unsigned char mm=30;//分数
unsigned char ss=50;//秒数

//显示屏幕
void refresh(){
    Write_Data(0xc0,dis[hh/10]);//数码管显示小时
    Write_Data(0xc0+2,dis[hh%10]);//数码管显示小时
    Write_Data(0xc0+4,dis2);//一杠
    Write_Data(0xc0+6,dis[mm/10]);//数码管显示分钟
    Write_Data(0xc0+8,dis[mm%10]);//数码管显示分钟
    Write_Data(0xc0+10,dis2);//一杠
    Write_Data(0xc0+12,dis[ss/10]);//数码管显示秒数
    Write_Data(0xc0+14,dis[ss%10]);//数码管显示秒数
}

//初始化时间
void clock_init (){
    BASIC_TIMER_Config(T14_SFR,INT_T14);     //配置使能定时器T14,定时10ms进一次中断
}

流水灯代码如下

#ifndef LED_H_
#define LED_H_

#include"tm1638.h"

//存储当前流水灯状态
extern unsigned char led_condition[8];

//刷新流水灯状态
void led_refresh();

//流水灯灯光show,第一种,20个状态为一个周期
void led_show1();

//流水灯灯光show,第二种,50个状态为一个周期
void led_show2();

#endif /* LED_H_ */
#include"led.h"

//存储当前流水灯状态
unsigned char led_condition[8]={0,0,0,0,0,0,0,0};

//刷新流水灯状态
void led_refresh(){
    unsigned char i=0;
    for(i=0;i<8;i++){
        Write_Data(0xc1+2*i,led_condition[i]);//显示当前灯光状态
    }
}

//流水灯灯光show,第一种,20个状态为一个周期
void led_show1(){
    unsigned char i=0;
    static unsigned char show1_mode[20]={
            0,1,2,3,4,5,6,7,8,9,
            9,8,7,6,5,4,3,2,1,0,
    };
    static unsigned char show1_num=0;
    for(i=0;i<8;i++){
        if(i<show1_mode[show1_num])
            led_condition[i]=1;
        else
            led_condition[i]=0;
    }
    show1_num=++show1_num%sizeof(show1_mode);
    led_refresh();
}

//流水灯灯光show,第二种,50个状态为一个周期
void led_show2(){
    unsigned char i=0;
    static unsigned char flag=0;
    static unsigned char show2_run=0;
    static unsigned char show2_add=0;
    if(show2_add<8){
        for(i=0;i<8;i++){
            if(show2_run==7-show2_add){
                show2_add=++show2_add;
                flag=1;
            }
            if(i==show2_run||i>7-show2_add)
                led_condition[i]=1;
            else
                led_condition[i]=0;
        }
        if(flag){
            show2_run=0;
            flag=0;
        }else{
            show2_run++;
        }
    }else if(show2_add<21){//补够50个周期
        show2_add++;
    }else{
        show2_add=0;
    }
    led_refresh();
}

 

TIMER中断函数如下

#include "system_init.h"
#include "clock.h"
#include "led.h"
#include "USART0.h"

volatile uint8_t Time14_CNT;

//*****************************************************************************************
//                              T14中断函数
//*****************************************************************************************    //
void __attribute__((interrupt))_T14_exception (void)
{
    BTIM_Clear_Updata_INT_Flag(T14_SFR);                //清更新时间标志位
    BTIM_Clear_Overflow_INT_Flag (T14_SFR);                //清T14溢出中断标志位

    Time14_CNT++;                                        //中断计数+1

    if(Time14_CNT%2==0){
        led_show2();            //每20ms刷新一次流水灯
//        for(int i=0;i<8;i++){    //串口发送流水灯状态
//            USART_SendData(USART0_SFR, '0'+led_condition[i]);
//        }
//        USART_SendData(USART0_SFR,'\0');
    }

    if(Time14_CNT>=100)        //1000ms执行一次
    {
        ss++;                //秒数+1
        if(ss==60){            //秒数等于60
            ss=0;            //秒数清0
            mm++;            //分钟+1
        }
        if(mm==60){            //分钟等于60
            mm=0;            //分钟清零
            hh++;            //小时+1
        }
        if(hh==24)            //小时等于24
            hh=0;            //小时清0
        refresh();            //重新显示屏幕
        Time14_CNT =0;        //中断计数清0
    }
}

 

主函数如下

#include"system_init.h"
#include"MYGPIO.h"
#include"PB10LED.h"
#include"tm1638.h"
#include"USART0.h"
#include"clock.h"

unsigned char i,j;

int main()
{
    SystemInit(120);            //初始化系统时钟为120M
    systick_delay_init(120);    //设置SysTick定时器作为延迟功能,输入频率为120M
    USART_Init();                //初始化串口
    TM1638_init();                //初始化TM1638
    clock_init();                //初始化时钟
    while(1){

    }
}

 

标签:KungFu32A156MQT,void,unsigned,TIMER,char,BTIM,微芯旺,TM1638,include
From: https://www.cnblogs.com/LPworld/p/17098060.html

相关文章