这几天在写一个程序,顺带完成了STM32F1版本的计时器程序,用的是正点原子的F1精英版开发板。
实现的功能是:当按下KEY1按键时,程序开始计时,当再次按下KEY1按键时,程序停止计时。并且显示当前的时间计数(总共计时了多少秒)。
这个程序比较简单,这里提供的是一个简单的模型,有需要的话可以后期在此基础上进行进一步的开发。整个程序主体的思想如下:使用STM32的定时器3不断地进行时间计数,即从1s开始一直计时到60s,之后清零秒计时,在分钟计数里面加一,完成分钟计时,如此循环,设置系统标准时间。
之后按键KEY1按下时,给按键按下时刻以一个系统时间,设置为系统开始时间。当按键KEY1再次按下时,设置一个系统结束时间,再将这两个时间相减就可以得到总计数时间了。按键KEY0则负责将计时清零。
具体代码如下:
main.c
- #include "delay.h"
- #include "key.h"
- #include "sys.h"
- #include "lcd.h"
- #include "timer.h"
- #include "string.h"
- /************************************************
- 蓝牙通讯主程序
- 作者:亦舒斋
- ************************************************/
- extern u8 time;//计数秒
- extern u8 minute;//计数分钟
- int main(void)
- {
- u8 key;//定义按键的状态
- u8 time1=0; //计数开始秒
- u8 minute1=0;//计数开始分钟
- u8 minute2=0;//计数结束分钟
- u16 time2=0;//计数结束秒
- u8 press=0;//判断开始计数或者是停止计数
- u32 count1;//计数开始值
- u32 count2;//计数结束值
- delay_init(); //延时函数初始化
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
- uart_init(115200); //串口初始化为115200
- LCD_Init(); //LCD端口初始化
- KEY_Init(); //初始化按键
- TIM3_Int_Init(9999,7199); //72000000/(9999+1)(7199+1)=1Hz----1s
- LCD_showzys(); //显示时间脉冲和接收值
- while(1)
- {
- key=KEY_Scan(0);//开始按键扫描
- if(key==KEY1_PRES) //开始计时
- {
- if(press==0)//当开始按下时
- {
- time1=time;//初始秒
- minute1=minute;//初始分钟
- press=1;//按键状态取反
- LCD_ShowString(30,120,200,16,16,"START:"); //显示接收到的字符
- LCD_ShowxNum(156,120,time1,3,16,0);//显示时间
- }
- else //当想要结束计时
- {
- minute2=minute;//结束时分钟
- press=0;//状态再次取反
- time2=time+60-time1+(minute2-minute1-1)*60;//计算总共计数时间
- count2=TIM5CH1_CAPTURE_COUNT-count1; //计算总共计数脉冲
- LCD_ShowString(30,140,200,16,16,"END:"); //显示计数时间
- LCD_ShowxNum(156,140,time2,3,16,0);//显示时间
- }
- }
- else if(key==KEY0_PRES)//按下KEY0清除显示
- {
- LCD_Fill(30,100,240,180,WHITE); //清除显示
- }
- TIM_SetCompare2(TIM3,2500);
- LCD_showtime(); //显示时间
- }
复制代码
之后是lcd.c,里面的需要在正点原子例程里面额外添加的函数,然后lcd.h文件里面也不要忘了添加头文件,否则编译会出错。
- extern u8 time;//时间
- extern u8 minute;//分钟
- //显示基础坐标
- void LCD_showzys()
- {
- LCD_ShowString(30,200,200,16,16,"Position:"); //显示时间
- LCD_ShowString(30,220,200,16,16,"Time:"); //显示时间
- LCD_ShowString(30,300,200,16,16,"Minute:"); //显示分钟
- }
- //显示时间
- void LCD_showtime()
- {
- LCD_ShowxNum(156,220,time,3,16,0);//显示时间
- LCD_ShowxNum(156,300,minute,3,16,0);//显示分钟的值
- }
复制代码
lcd.h中需要添加的:
- void LCD_showtime(void); //显示时间信息
- void LCD_showzys(void); //显示时间信息
复制代码
timer.c中:需要的是定时器3
- #include "timer.h"
- #include "led.h"
- #include "stdlib.h"
- #include "math.h"
- #include "lcd.h"
- #include "sys.h"
- #include "delay.h"
- #include "usart.h"
- #include "string.h"
- #include "key.h"
- void TIM3_Int_Init(u16 arr,u16 psc)//定时器3初始化
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
- TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000为500ms
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 10Khz的计数频率
- TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
- TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
- TIM_ITConfig( //使能或者失能指定的TIM中断
- TIM3, //TIM2
- TIM_IT_Update | //TIM 中断源
- TIM_IT_Trigger, //TIM 触发中断源
- ENABLE //使能
- );
- NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
- NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
- TIM_Cmd(TIM3, ENABLE); //使能TIM3外设
- }
- u8 time=0;//时间
- u8 minute=0;//分钟计数
- //定时器3中断服务程序
- void TIM3_IRQHandler(void) //TIM3中断
- {
- if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否
- {
- if(time++==60)//当计数满60秒时
- {
- time=0; //将时间清零
- minute++;
- }
- }
- TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx的中断待处理位:TIM 中断源
- }
复制代码
|
|