打印
[STM32F1]

基于使用STM32F1制作一个计时器经验分享

[复制链接]
4634|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
flycamelaaa|  楼主 | 2023-5-26 09:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这几天在写一个程序,顺带完成了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 中断源
  • }


复制代码


使用特权

评论回复
沙发
keaibukelian| | 2023-6-10 11:08 | 只看该作者
请教一个 我们经常会遇到两个定时器串联使用的情况,那么如何保证两个定时器的同步呢

使用特权

评论回复
板凳
wowu| | 2023-6-10 11:38 | 只看该作者
keaibukelian 发表于 2023-6-10 11:08
请教一个 我们经常会遇到两个定时器串联使用的情况,那么如何保证两个定时器的同步呢 ...

选用同样的时钟源,同样的分频系数,同时启动不就可以了吗?

使用特权

评论回复
地板
heimaojingzhang| | 2023-6-10 11:47 | 只看该作者
wowu 发表于 2023-6-10 11:38
选用同样的时钟源,同样的分频系数,同时启动不就可以了吗?

也可以不用同时启动 感觉可以通过一个定时器启动另一个定时器的

使用特权

评论回复
5
wakayi| | 2023-6-10 11:57 | 只看该作者
可以产生pwm的定时器和普通定时器的区别是 什么呢

使用特权

评论回复
6
renzheshengui| | 2023-6-10 13:11 | 只看该作者
这样的计时器的计时精度不会很高,因为为了防抖会有一定的延时

使用特权

评论回复
7
tpgf| | 2023-6-10 13:29 | 只看该作者
renzheshengui 发表于 2023-6-10 13:11
这样的计时器的计时精度不会很高,因为为了防抖会有一定的延时

那也不是 我们可以做算法 当检测到信号不是干扰信号的时候将延时计算进去就行了

使用特权

评论回复
8
AloneKaven| | 2023-6-10 23:46 | 只看该作者
keaibukelian 发表于 2023-6-10 11:08
请教一个 我们经常会遇到两个定时器串联使用的情况,那么如何保证两个定时器的同步呢 ...

同样的参数应该计数结果一致吧

使用特权

评论回复
9
Jacquetry| | 2023-6-11 23:02 | 只看该作者
这样要是有延迟的话是不是就不能同步了

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

658

主题

2751

帖子

0

粉丝