STM32使用定时器进行串口通信和点灯及输出PWM完成呼吸灯

一、定时器的基本介绍

1、定时器概念

STM32定时器具有多个定时/计数通道,可以高精度地计算时间,并可配置为不同的模式以满足各种应用需求。它不仅可以作为独立的时间测量工具,还可以与其他外设模块(如ADC、DAC、GPIO等)进行协作,提供丰富的功能。

2、定时器分类

STM32定时器主要分为以下几类:

  1. 高级定时器:功能最全,如STM32的TIM1和TIM8,挂载在APB2总线上。它们增加了重复计数器、死区生成、互补输出、刹车输入等功能,适用于需要高精度和高可靠性的应用。

  2. 通用定时器:最常用,如STM32的TIM2、TIM3、TIM4、TIM5,挂载在APB1总线上。它们具有内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等功能,适用于各种通用应用。

  3. 基本定时器:功能最简单,如STM32的TIM6和TIM7,挂载在APB1总线上。它们只有定时中断和DAC功能,适用于基本的传感器应用。

3、定时器模式

STM32定时器可以配置为多种模式,以满足不同的应用需求。以下是一些常见的模式:

  1. 向上计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数,并产生一个计数器溢出事件。

  2. 向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件。

  3. 中央对齐模式:计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数。

此外,STM32定时器还支持输入捕获模式、PWM输出模式等。

4、定时器计算方法

STM32定时器的定时时间可以通过以下公式计算:

定时时间=(Prescaler+1)×(Counter Period+1)×1/定时器时钟频率

其中,Prescaler是预分频器的值,Counter Period是自动重装载寄存器的值(也称为计数周期),定时器时钟频率是定时器的时钟信号频率。

5、定时器工作过程

STM32定时器的工作过程如下:

  1. 时钟信号输入:定时器接收来自内部或外部的时钟信号。

  2. 预分频器处理:时钟信号经过预分频器进行分频处理,得到较低的频率信号。

  3. 计数器计数:分频后的信号送入计数器进行计数。计数器可以向上、向下或中央对齐模式进行计数。

  4. 产生中断或DMA请求:当计数器达到预设的计数周期(即自动重装载寄存器的值)时,产生计数器溢出事件,进而触发中断或DMA请求。

  5. 处理中断或DMA请求:CPU响应中断或DMA请求,执行相应的中断服务程序或DMA传输操作。

 二、使用定时器进行串口通信和点灯

1、工程建立

(1)创建项目,点击ACCEE TO MCU SELECTOR

(2)配置RCC

(3)配置SYS

(4)配置USART1

(5)设置输出引脚(此处笔者设置的PA1)

(6)配置定时器

这里我们使用定时器2和定时器3来实现定时的功能。如图所示,依次点击位置1,选中定时器2;位置2,配置定时器2的时钟源为内部时钟;位置3,分频系数为71,向上计数模式,计数周期为5000,使能自动重载模式。

TIM3与TIM2几乎相同,只有圈中所示位置不同

注意;分频系数那里虽然写的是71,但系统处理的时候会自动加上1,所以实际进行的是72分频。由于时钟我们一般会配置为72MHZ,所以72分频后得到1MHZ的时钟。1MHZ的时钟,计数5000次,得到时间5000/1000000=0.005秒。也就是每隔0.005秒定时器2会产生一次定时中断。

(7)配置NVIC中的中断

(8)时钟配置

如下图所示配置即可

(9)配置项目相关配置

(10)生成项目

2、代码编写

(1)启动定时器

	HAL_TIM_Base_Start_IT(&htim2);
	HAL_TIM_Base_Start_IT(&htim3);

(2)串口通信

首先在main.c中定义STM32需要给上位机发送的消息

	uint8_t hello[20]="hello windows!\r\n";

(3)定时器中断回调函数

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	static uint32_t time_cnt =0;
	static uint32_t time_cnt3 =0;
	if(htim->Instance == TIM2)
	{
		if(++time_cnt >= 400)
		{
			time_cnt =0;
			HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_1);
		}
	}
	if(htim->Instance == TIM3)
	{
		if(++time_cnt3 >= 1000)
		{
			time_cnt3 =0;
    HAL_UART_Transmit(&huart1,hello,20,100000);
		}
			
	}
}

该函数为定时器的中断回调函数,当产生定时中断的时候,会自动调用这个函数。在函数内部定义了定时器的一个静态变量:time_cnt与定时器3 的time_cnt3。
例如time_cnt,当它大于等于100的时候,才会执行if里面的代码。也就是说需要发生400次中断,才会让LED的状态翻转。前面已经算过了,一次定时中断的时间是0.005秒,所以400次中断的时间是0.005400=2秒。也就是说每隔2秒,LED的状态翻转一次。
例如time_cnt3,当它大于等于1000的时候,才会执行if里面的代码。也就是说需要发生1000次中断,才会让串口发一次消息。0.0051000=5秒,符合题目要求。

结果展示

三、PWM基本介绍

定义

PWM是通过编程控制输出方波的频率和占空比(高低电平的比例)来模拟模拟信号的一种技术。

基本原理

PWM的基本原理是利用微处理器的数字输出来对模拟电路进行控制。在一个PWM周期内,信号处于高电平(或有效电平)的时间与整个周期时间的比例被称为占空比。通过改变占空比,可以控制模拟电路的输出功率。

优点
  • 能量损耗小:PWM技术可以在保证输出效果的同时,降低能量损耗。
  • 控制简单:通过数字信号控制,使得PWM技术相对容易实现和控制。
  • 成本低廉:PWM技术所需的硬件成本相对较低,且易于集成到各种系统中。
  • 应用范围

    PWM已经广泛应用在各种需要模拟结果的数字控制环境中,如:

  • 调速风扇:通过PWM控制风扇电机的转速。
  • 调光灯具:利用PWM调节LED灯的亮度。
  • 伺服电机控制:在伺服电机控制系统中,PWM用于精确控制电机的转速和位置。
  • 电子调制器:PWM技术也应用于各种电子调制器中,用于调节输出电压和电流。
  • 主要参数
  • 频率:PWM波的频率,决定了PWM波形的周期。
  • 占空比:PWM波中高电平时间与整个周期时间的比例。
  • PWM的产生

    在STM32中,PWM是通过配置内部定时器来实现的。定时器的精确计数能力可以用来定义PWM信号的周期和占空比,从而生成非常精确的PWM波形。

    PWM工作原理

    PWM的工作原理基于定时器和比较寄存器的配合。定时器从0开始计数,当计数器的值达到比较寄存器的值时,输出电平发生翻转。通过不断改变比较寄存器的值,可以控制PWM波的占空比。在一个周期内,定时器的值从0计数到自动重装载值(ARR),然后溢出并重新开始计数。这个过程中,PWM波的频率由定时器的时钟频率、预分频器(PSC)和自动重装载值(ARR)共同决定。

    PWM输出的模式区别

    STM32中的PWM输出模式有多种,如PWM模式1和PWM模式2等。这些模式的主要区别在于输出电平的翻转时机和占空比的计算方式。例如,在PWM模式1中,当计数器的值小于比较寄存器的值时,输出高电平;而在PWM模式2中,则相反。

    PWM的计数模式

    STM32的定时器支持多种计数模式,如向上计数模式、向下计数模式和中心对齐模式等。这些计数模式决定了PWM波的波形和对称性。例如,在向上计数模式下,定时器的值从0开始递增到ARR值;而在向下计数模式下,则相反。中心对齐模式则是向上和向下计数模式的结合,生成一个对称的PWM波形。

    PWM相关配置寄存器

    在STM32中,PWM的相关配置主要通过以下几个寄存器来实现:

  • TIMx_PSC:预分频器寄存器,用于设置定时器的时钟分频系数。
  • TIMx_ARR:自动重装载寄存器,用于设置PWM波的周期。
  • TIMx_CCRx:捕获/比较寄存器,用于设置PWM波的占空比。
  • TIMx_CCMRx:捕获/比较模式寄存器,用于设置PWM的输出模式和极性。
  • 四、输出PWM完成呼吸灯

    1、创建项目

    其他设置基本与前一个实验相同,不用设置中断与USART1,这次我们选择的是TIM3与TIM4,配置方法相同。

    设置完毕后便生成项目

    2、代码编写

    (1)在int main添加如下代码

      uint16_t pwmVal = 0;  //占空比大小(CCRx的大小)
        uint8_t direction = 1;  //呼吸灯方向: 1. 越来越亮   2. 越来越暗
    

    HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);
    	HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_1);

    (2)在while(1)下添加以下代码

    HAL_Delay(3);  //控制呼吸灯呼吸速率
                       //控制占空比大小,即修改CCRx的大小
            if(direction){
                pwmVal++;
            }else{
                pwmVal--;
            }
            //设置了ARR为499,因此每计数500为一个周期
            if(pwmVal > 500){ 
                direction = 0;  //改变呼吸灯方向
            }else if(pwmVal == 0){
                direction = 1;  //改变呼吸灯方向
            }
            //修改定时器4通道三的PWM的占空比
            __HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1,pwmVal);
            __HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_1,pwmVal);
    

    四.硬件连接

    1.线路连接

    根据查询数据手册可发现定时器3,4的一通道分别对应引脚PA6 PB6,然后题目要求还需要直接驱动PC13(最小开发板上已焊接的LED(固定接在 PC13 GPIO端口)),故而我们将对应PWM波作为输入,连接其对应引脚即可实现所需完成功能。

    结果图

    五,利用keil仿真并观察波形

    点击魔术棒,在Debug选项卡中按照下图的方式进行配置。

    然后点击快捷工作栏的Debug选项 ,在下图列表中找到逻辑分析仪

    或者在快捷工作栏找到。

    然后再弹出的逻辑分析仪窗口的左上角找到Set up选项,在其中添加USART1_SR,如下图所示。

    点击colse保存关闭后,就能得到如下的波形,可以看到波形随时间有明显变化。

    六,总结

    在本次STM32的实验中,笔者深入学习了如何使用定时器实现时间的精准控制,并通过PWM波形驱动LED实现呼吸灯效果。这两个实验不仅让笔者对STM32的定时器功能有了更深入的了解,也让笔者在实践中掌握了多任务并发运行的基本思想。

    在第一个实验中,笔者通过配置TIM2和TIM3定时器,分别实现了5秒串口通信和2秒LED闪烁的功能。在配置定时器时,笔者深刻体会到了定时器分频系数、计数周期等参数对定时时间的影响。通过不断调试和优化,笔者成功实现了每隔5秒从串口发送“hello windows!”字符串,并且LED每隔2秒闪烁一次。这个过程不仅锻炼了笔者的动手能力,也让笔者更加理解了定时器的工作原理。

    在第二个实验中,笔者使用了TIM3和TIM4定时器输出PWM波形,通过改变PWM的占空比实现了两个LED的呼吸灯效果。在配置PWM时,笔者遇到了一些挑战,如如何选择合适的PWM频率和占空比以实现平滑的呼吸效果。通过查阅资料和不断尝试,笔者最终成功实现了两个LED的呼吸灯效果,并且效果非常理想。

    通过这次实验,笔者不仅掌握了STM32定时器和PWM的基本使用方法,还学会了如何根据实际需求进行参数配置和调试。同时,笔者也深刻体会到了理论与实践相结合的重要性。在未来的学习和工作中,笔者将继续运用所学知识,不断探索和实践,努力提高自己的专业技能和实践能力。

    作者:Budong..

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32使用定时器进行串口通信和点灯及输出PWM完成呼吸灯

    发表回复