草庐IT

蓝桥杯嵌入式第四课--定时器

背影疾风 2023-04-04 原文

前言

蓝桥杯对于定时器这部分的考察主要集中在定时器中断PWM输出以及输入捕获三个方面,本节课着眼于应用,介绍一下定时器的使用。

定时器中断

一、基础概念

对没接触过定时器的新手来说,如果想要快速上手定时器的使用,首先要先对定时器建立一个初步的印象。我们所说的定时器,从本质上看其实是一个计数器,可以从零开始计数,计到一个最大值,我们称其为 自动重装载值(ARR),然后清零,再重新开始计数,如此往复。这就是最基础也是最常用的向上计数模式,在此基础上,还有向下计数,和中央对齐计数(即从0到ARR,再从ARR到0)。

在计数器的基础上打个比方,如果我们需要定时10秒,我们只需让计数器每秒加1,加到10之后告诉我们时间到了,然后再从零开始即可。

针对上面的描述,我们又引出一个参数:定时器的频率。针对我们的比赛,计数器每计一个数需要消耗的时间 t = 系统时钟频率/预分频值。也就是:

f = 80Mhz/psc

并且,定时器到时间后还需要提醒我们,因此,每当计数值满了时(即溢出),都要产生一个定时器中断。

二、配置操作

一、CubeMx激活定时器

如上图所示:

  1. 选择一个定时器

  1. 选择定时器的时钟源

  1. 配置定时器的预分频系数 Prescaler、以及自动重装载值ARR

这里的重点在于Psc参数和ARR参数的设置。公式如下:

二、使能中断

我们使用定时器的更新中断作为实验的中断源。

三、编写代码

定时器中断主要添加两个函数即可:

  HAL_TIM_Base_Start_IT(&htim1);   //该函数开启定时器,置于main.c中定时器初始化代码之后

以及回调函数:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ //置于main()函数之后
    if(htim == &htim1)  //判断中断是否来自于定时器1
   {
       代码;
   }
}

这样当计数器溢出时,中断就会触发,并执行回调函数。

四、实验任务

如果你现在看到这了,请完成一个,每隔1s加一的计时器,并将结果显示在LCD上(5分钟即可解决,代码后续我会附上)。

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM1_Init();
  HAL_TIM_Base_Start_IT(&htim1);   //启动计数
  LCD_Init();
  /* USER CODE BEGIN 2 */
  char text[30];
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
    
    LCD_Clear(White);
    LCD_SetBackColor(Blue);
    LCD_SetTextColor(Black);
 
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
sprintf(text,"    t = %d   ",i);
 LCD_DisplayStringLine(Line4,(unsigned char *)text);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){
    if(htim == &htim1)  //判断中断是否来自于定时器1
   {
       i++;
   }
}

任意占空比PWM输出

一、基础概念

PWM输出其实是在定时器的基础上发展而来的一个外设。核心原理就是设置一个数,我们称之为CCR(比较寄存器),当我们的计数值CNT小于CCR时,输出高电平,大于CCR时,输出低电平,只要我们改变CCR的值就可以实现占空比可调的PWM波输出。

二、配置操作

  1. 选择输出管脚

像上面这种带N的和其它一些奇怪的都不要选择,我们可以选择TIM4_CH4作为输出PWM的定时器通道。

  1. 选择时钟源和输出模式

3.配置定时器的PSC和ARR

这两个参数对PWM的频率产生决定性的影响,需要好好计算一下,上面的参数配置了PWM的频率为1000Hz。

4.配置通道的参数

对于通道而言,这个的Mode选择PWM mode 1,并且,Pulse参数设置的是占空比,这里我们设置为零,这个参数在程序中可以通过函数进行实时设置。

三、编写代码

在代码中,需要补充如下函数:

1、HAL_TIM_PWM_Start;开启PWM输出

/**
  * @brief  Starts the PWM signal generation.
  * @param  htim TIM handle
  * @param  Channel TIM Channels to be enabled
  *          This parameter can be one of the following values:
  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
  *            @arg TIM_CHANNEL_5: TIM Channel 5 selected
  *            @arg TIM_CHANNEL_6: TIM Channel 6 selected
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel)

与此对应还有

HAL_StatusTypeDef HAL_TIM_PWM_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)

2、__HAL_TIM_SetCompare;设置占空比

__HAL_TIM_SetCompare(&htimx, TIM_CHANNEL_x, pwm_value); 

3、_HAL_TIM_SET_AUTORELOAD;设置频率

__HAL_TIM_SET_AUTORELOAD(&htimx, prc_value);    

小结

定时器最基本的两个应用就是定时器中断和PWM输出。定时器的配置过程为:

  1. 设置分频系数PSC与自动重装载值ARR,以确定定时器中断的触发时间

  1. 打开定时器中断

  1. 代码中启动定时器HAL_TIM_Base_Start_IT以及编写回调函数HAL_TIM_PeriodElapsedCallback

PWM的配置过程在前面基础上(可不开启中断):

  1. 配置PWM的模式,以及CCR寄存器值,以确定占空比

  1. 代码中启动PWM:HAL_TIM_PWM_Start,并且设置占空比__HAL_TIM_SetCompare与频率_HAL_TIM_SET_AUTORELOAD;

下一篇文章介绍输入捕获的配置!

有关蓝桥杯嵌入式第四课--定时器的更多相关文章

  1. ruby - Ruby 性能中的计时器 - 2

    我正在寻找一个用ruby​​演示计时器的在线示例,并发现了下面的代码。它按预期工作,但这个简单的程序使用30Mo内存(如Windows任务管理器中所示)和太多CPU有意义吗?非常感谢deftime_blockstart_time=Time.nowThread.new{yield}Time.now-start_timeenddefrepeat_every(seconds)whiletruedotime_spent=time_block{yield}#Tohandle-vesleepinteravalsleep(seconds-time_spent)iftime_spent

  2. 蓝桥杯备赛(二) - 2

    目录前言: 一、ASC分析代码实现二、 卡片分析代码实现三、 直线分析代码实现四、货物摆放分析代码实现小结:前言:  在刷题的过程中,发现蓝桥杯的题目和力扣的差别很大。让人有一种不一样的感觉,蓝桥杯题目偏向对于实际问题用编程去的解决,而力扣给人感觉很锻炼自己的编程思维,逻辑能力。两者结合去刷,相信会有不一样的收获。 一、ASC  已知大写字母A的ASCII码为65,请问大写字母L的ASCII码是多少?分析  这道题目看上去很简单,我们需确定自己计算的准确,所以我建议用编程去解决。代码实现publicclassTest8{publicstaticvoidmain(String[]args){Sy

  3. ruby-on-rails - Ruby:给定日期找到下一个第二或第四个星期二 - 2

    我似乎找不到一种优雅的方式来做到这一点......给定一个日期,我如何找到下一个星期二,即日历月的第2个或第4个星期二?例如:给定2012-10-19然后返回2012-10-23或给定2012-10-31然后返回2012-11-13OctoberNovemberSuMoTuWeThFrSaSuMoTuWeThFrSa12345612378910111213456789101415161718192011121314151617212223242526271819202122232428293031252627282930 最佳答案

  4. 蓝桥杯C/C++VIP试题每日一练之报时助手 - 2

    ?作者主页:静Yu?简介:CSDN全栈优质创作者、华为云享专家、阿里云社区博客专家,前端知识交流社区创建者?社区地址:前端知识交流社区?博主的个人博客:静Yu的个人博客?博主的个人笔记本:前端面试题个人笔记本只记录前端领域的面试题目,项目总结,面试技巧等等。接下来会更新蓝桥杯官方系统基础练习的VIP试题,依然包括解题思路,源代码等等。问题描述:给定当前的时间,请用英文的读法将它读出来。时间用时h和分m表示,在英文的读法中,读一个时间的方法是:  如果m为0,则将时读出来,然后加上“o’clock”,如3:00读作“threeo’clock”。  如果m不为0,则将时读出来,然后将分读出来,如5

  5. springboot定时任务 - 2

    如果您希望在Spring中启用定时任务功能,则需要在主类上添加 @EnableScheduling 注解。这样Spring才会扫描 @Scheduled 注解并执行定时任务。在大多数情况下,只需要在主类上添加 @EnableScheduling 注解即可,不需要在Service层或其他类中再次添加。以下是一个示例,演示如何在SpringBoot中启用定时任务功能:@SpringBootApplication@EnableSchedulingpublicclassApplication{publicstaticvoidmain(String[]args){SpringApplication.ru

  6. ruby-on-rails - 如何在 RoR 中使用 content_tag 嵌入标签? - 2

    我有这个可以为我生成一个超链接:我希望它显示在td标签中,所以我想使用这个content_tag来帮助我:"example")%>我想要我的td中的超链接,所以我有这样的东西:,:class=>"example")%>但是我收到语法错误,我该怎么办? 最佳答案 内联:'example')%>或block形式:'example')do%> 关于ruby-on-rails-如何在RoR中使用content_tag嵌入标签?,我们在StackOverflow上找到一个类似的问题:

  7. 十四届蓝桥青少组模拟赛Python-20221108 - 2

    十四届蓝桥青少组模拟赛Python-20221108T1.二进制位数十进制整数2在十进制中是1位数,在二进制中对应10,是2位数。十进制整数22在十进制中是2位数,在二进制中对应10110,是5位数。请问十进制整数2022在二进制中是几位数?print(len(bin(2022))-2)#运行结果:11T2.晨跑小蓝每周六、周日都晨跑,每月的1、11、21、31日也晨跑。其它时间不晨跑。已知2022年1月1日是周六,请问小蓝整个2022年晨跑多少天?#样例代码1ls=[0,31,28,31,30,31,30,31,31,30,31,30,31]ans=0k=6foriinrange(1,13)

  8. 蓝桥杯 stm32 MCP4017 - 2

    本文代码使用HAL库。文章目录前言一、MCP4017的重要特性二、MCP4017计算RBW阻值三、MCP4017地址四、MCP4017读写函数五、CubeMX创建工程(利用ADC测量MCP4017电压)、对应代码:总结前言一、MCP4017的重要特性蓝桥杯板子上的是MCP4017T-104ELT,如图1。MCP4017是一个可编程电阻,通过写入的数值可以改变电阻的大小。重点在于6引脚(W),5引脚(B&#

  9. C#初级_定时器 - 2

    文章目录一、引言二、Timers1.System.Threading.Timer1.1.简单使用1.2.注意点2.System.Timers.Timer2.1.概述🔺2.2.注意点三、总结一、引言在开发中,会遇到并行处理的需求。有时只需要使用task(底层是创建个线程)来处理一下就好了。而有时则在并行处理的基础上还有时间的要求,较常见的就是每隔一定时间处理一次。当然,这用task肯定可以实现,但是时间这块得自己控制,无疑增加了工作量和不确定性。.NET提供了叫做定时器(timer,也叫计时器)的类,它在并行处理的基础上,带了时间参数的设置,可以满足这一需求。其实本文标题与其叫C#定时器,不如叫

  10. [蓝桥杯单片机]学习笔记——串口通信的基本原理与应用 - 2

    目录一、原理部分1、什么是串行通信(1)并行通信与串行通信(2)串行通信的制式(3)串行通信的主要方式  2、配置串口(1)SCON和PCON:串行口1的控制寄存器(2)SBUF:串行口数据缓冲寄存器 (3)AUXR:辅助寄存器​编辑(4)ES、PS:与串行口1中断相关的寄存器(5)波特率设置  3、串口框架编写二、程序案例一、原理部分1、什么是串行通信(1)并行通信与串行通信微控制器与外部设备的数据通信,根据连线结构和传送方式的不同,可以分为两种:并行通信和串行通信。并行通信:数据的各位同时发送与接收,每个数据位使用一条导线,这种方式传输快,但是需要多条导线进行信号传输。串行通信:数据一位一

随机推荐