【嵌入式】微芯旺KungFu32A156MQT使用TM1638和TIMER实现流水灯和时钟
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){ } }