请选择 进入手机版 | 继续访问电脑版

你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

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

[复制链接]
攻城狮Melo 发布时间:2023-5-23 19:09
这几天在写一个程序,顺带完成了STM32F1版本的计时器程序,用的是正点原子的F1精英版开发板。
  实现的功能是:当按下KEY1按键时,程序开始计时,当再次按下KEY1按键时,程序停止计时。并且显示当前的时间计数(总共计时了多少秒)。
  这个程序比较简单,这里提供的是一个简单的模型,有需要的话可以后期在此基础上进行进一步的开发。整个程序主体的思想如下:使用STM32的定时器3不断地进行时间计数,即从1s开始一直计时到60s,之后清零秒计时,在分钟计数里面加一,完成分钟计时,如此循环,设置系统标准时间。
之后按键KEY1按下时,给按键按下时刻以一个系统时间,设置为系统开始时间。当按键KEY1再次按下时,设置一个系统结束时间,再将这两个时间相减就可以得到总计数时间了。按键KEY0则负责将计时清零。
  具体代码如下:
  main.c
  1. #include "delay.h"
  2. #include "key.h"
  3. #include "sys.h"
  4. #include "lcd.h"
  5. #include "timer.h"                           
  6. #include "string.h"           
  7. /************************************************
  8. 蓝牙通讯主程序
  9. 作者:亦舒斋
  10. ************************************************/
  11. extern u8 time;//计数秒
  12. extern u8 minute;//计数分钟
  13.    int main(void)
  14. {                     
  15.           u8 key;//定义按键的状态
  16.       u8 time1=0;        //计数开始秒
  17.           u8 minute1=0;//计数开始分钟
  18.           u8 minute2=0;//计数结束分钟
  19.           u16 time2=0;//计数结束秒
  20.       u8 press=0;//判断开始计数或者是停止计数        
  21.           u32 count1;//计数开始值
  22.           u32 count2;//计数结束值
  23.           delay_init();                     //延时函数初始化         
  24.           NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);         //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
  25.           uart_init(115200);                 //串口初始化为115200
  26.           LCD_Init();          //LCD端口初始化         
  27.           KEY_Init();                                //初始化按键                        
  28.           TIM3_Int_Init(9999,7199);         //72000000/(9999+1)(7199+1)=1Hz----1s
  29.           LCD_showzys();        //显示时间脉冲和接收值
  30.           while(1)
  31.         {                                
  32.                 key=KEY_Scan(0);//开始按键扫描
  33.                 if(key==KEY1_PRES)                                                //开始计时
  34.                 {
  35.        if(press==0)//当开始按下时
  36.                          {
  37.                                  time1=time;//初始秒
  38.                                  minute1=minute;//初始分钟
  39.                                  press=1;//按键状态取反
  40.                                  LCD_ShowString(30,120,200,16,16,"START:");       //显示接收到的字符
  41.                                  LCD_ShowxNum(156,120,time1,3,16,0);//显示时间        
  42.                          }
  43.                                 else //当想要结束计时
  44.                          {
  45.                                  minute2=minute;//结束时分钟
  46.                                  press=0;//状态再次取反
  47.                                  time2=time+60-time1+(minute2-minute1-1)*60;//计算总共计数时间
  48.                                  count2=TIM5CH1_CAPTURE_COUNT-count1;                //计算总共计数脉冲                 
  49.                                  LCD_ShowString(30,140,200,16,16,"END:");       //显示计数时间
  50.                                  LCD_ShowxNum(156,140,time2,3,16,0);//显示时间                        
  51.                          }                                 
  52.                  }
  53.                 else if(key==KEY0_PRES)//按下KEY0清除显示
  54.                 {
  55.                     LCD_Fill(30,100,240,180,WHITE);        //清除显示                        
  56.                 }
  57.                   TIM_SetCompare2(TIM3,2500);               
  58.                   LCD_showtime(); //显示时间                                                                                                                          
  59.    }
复制代码
之后是lcd.c,里面的需要在正点原子例程里面额外添加的函数,然后lcd.h文件里面也不要忘了添加头文件,否则编译会出错。

  1. extern u8  time;//时间
  2. extern u8  minute;//分钟
  3. //显示基础坐标
  4. void LCD_showzys()
  5. {        
  6.         LCD_ShowString(30,200,200,16,16,"Position:");       //显示时间           
  7.         LCD_ShowString(30,220,200,16,16,"Time:");       //显示时间           
  8.         LCD_ShowString(30,300,200,16,16,"Minute:");       //显示分钟        
  9. }        

  10. //显示时间
  11. void LCD_showtime()
  12. {
  13.           LCD_ShowxNum(156,220,time,3,16,0);//显示时间        
  14.           LCD_ShowxNum(156,300,minute,3,16,0);//显示分钟的值        
  15. }

复制代码
lcd.h中需要添加的:

  1. void LCD_showtime(void);                            //显示时间信息
  2. void LCD_showzys(void);                             //显示时间信息
复制代码


timer.c中:需要的是定时器3
  1. #include "timer.h"
  2. #include "led.h"
  3. #include "stdlib.h"
  4. #include "math.h"
  5. #include "lcd.h"
  6. #include "sys.h"
  7. #include "delay.h"
  8. #include "usart.h"                  
  9. #include "string.h"           
  10. #include "key.h"
  11. void TIM3_Int_Init(u16 arr,u16 psc)//定时器3初始化
  12. {
  13.     TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  14.         NVIC_InitTypeDef NVIC_InitStructure;

  15.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

  16.         TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值         计数到5000为500ms
  17.         TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率  
  18.         TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
  19.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
  20.         TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

  21.         TIM_ITConfig(  //使能或者失能指定的TIM中断
  22.         TIM3, //TIM2
  23.         TIM_IT_Update  |  //TIM 中断源
  24.         TIM_IT_Trigger,   //TIM 触发中断源
  25.         ENABLE  //使能
  26.                 );
  27.         NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
  28.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
  29.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
  30.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
  31.         NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
  32.         TIM_Cmd(TIM3, ENABLE);  //使能TIM3外设                                                         
  33. }
  34. u8  time=0;//时间
  35. u8  minute=0;//分钟计数
  36. //定时器3中断服务程序
  37. void TIM3_IRQHandler(void)   //TIM3中断
  38. {
  39.         if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)  //检查TIM3更新中断发生与否
  40.                 {
  41.                         
  42.                         if(time++==60)//当计数满60秒时
  43.                         {
  44.                 time=0;                 //将时间清零                                
  45.                                 minute++;
  46.                     }
  47.                 }
  48.                         TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源
  49. }
  50.                                                                                                                                                                                     
复制代码


————————————————
版权声明:亦舒斋
如有侵权请联系删除


收藏 评论1 发布时间:2023-5-23 19:09

举报

1个回答
bitterheart 回答时间:6 天前

可以可以

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版