《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.8 TIM---PWM输出实验

写在前面——
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.8 TIM—PWM输出实验,讲解TIM 定时与PWM输出的STM32CubeMX配置和程序设计方法
官方例程下载:https://pan.baidu.com/s/1QC5BnDgY1m1me6-ihQ_OUQ?pwd=nqb1
提取码:nqb1

目录

  • 4.8 TIM---PWM输出实验
    • 4.8.1. 实验任务
    • 4.8.2. TIM原理解析
    • 4.8.3. TIM定时作用
      • 1. 初始化配置(STM32CubeMX)
      • 2. 应用程序设计(KEIL5)
    • 4.8.4. PWM输出
      • 1. 初始化配置(STM32CubeMX)
      • 2. 可修改频率、占空比的PWM波
      • 3. 小练习
    • 4.8.5. 小结

4.8 TIM—PWM输出实验

4.8.1. 实验任务

  1. TIM定时作用:参考官方例程HAL_10_TIM_BASE,实现流水灯。
  2. TIM PWM输出:产生PWM波(频率固定、占空比可调),实现呼吸灯
  3. TIM PWM输出:可调频率/占空比的PWM波

4.8.2. TIM原理解析

  定时器(Timer)最基本的功能就是定时,可以延伸到测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和PWM)等。
  STM32G4 的定时器功能十分强大,共有10个定时器:
  表1 定时器类型
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.8 TIM---PWM输出实验_第1张图片
查看STM32G431RB数据手册(资料包芯片手册中),可获得各个定时器通道的引脚分布,如《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.8 TIM---PWM输出实验_第2张图片
可以汇总为表2:
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.8 TIM---PWM输出实验_第3张图片
STM32G431的通用 TIMx定时器功能特点包括:
 16 /32 位向上、向下、向上/向下(中心对齐)计数模式,自动装载计数器(TIMx_CNT)。
 16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数 为 1~65535 之间的任意数值。
 4 个独立通道(TIMx_CH1~4)
计数器模式
通用定时器可以向上计数、向下计数、向上向下双向计数模式。
 向上计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且产生一个计数器溢出事件。
 向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件。
 中央对齐模式(向上/向下计数):计数器从0开始计数到最大值,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数。
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.8 TIM---PWM输出实验_第4张图片
定时时间计算
  基本定时器计数过程主要涉及到三个寄存器内容,分别是计数器寄存器(TIMx_CNT)、预分频器寄存器(TIMx_PSC)、自动重载寄存器(TIMx_ARR),这三个寄存器都是 16 位有效数字,即可设置值为 0 至 65535。
  CNT表示当前计数值,ARR是自动重载的最大计数值。PSC是分频系数,对定时器时钟AB1或AB2进行分频,得到当前计数器的频率。)
  首先设置预分频器寄存器TIMx_PSC (简写成PSC),得到分频后的频率,频率的倒数就是周期时长。如,定时器时钟fCK_PSC =80MKz、(PSC+1)设为(7999+1),这样fCK_CNT /(PSC+1)分频后的频率值就为10kHz,每一个周期时长也就是0.1ms。
  fCK_CNT = fCK_PSC/(PSC+1) // fCK_PSC为定时器时钟频率,来自APB1或者APB2。
  再把把(ARR+1)设为(9999+1)。这样我们得到的定时时长就是1s。
  Tout(定时时间)=(ARR+1)(PSC+1)/ fCK_PSC
PWM波输出
  PWM 输出就是产生一个周期的方波信号,频率、占空比(高电平占总周期的比值)是它的关键参数。
  如下图,假定定时器工作在向上计数PWM模式,且当 CNT(当前计数值)=CCRx 时输出 1。实际上配置CCRx、ARR的数值,就控制PWM波的输出脉宽了。
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.8 TIM---PWM输出实验_第5张图片
  STM32G431 定时器可以用来产生 PWM 输出,其中高级定时器 TIM1 可以输出 4 路。而通用定时器(TIM2、TIM3、TIM4)也可同时产生多达 4 路的 PWM 输出。
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.8 TIM---PWM输出实验_第6张图片
  通常单片机GPIO口只能输出高电平和低电平,可以利用PWM波,通过改变PWM方波的占空比,从而获得不同的模拟电压值。如,100%对应5v,0%对应0v,50%对应2.5v。
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.8 TIM---PWM输出实验_第7张图片
  因此,利用PWM波,可以实现呼吸灯(电压值变化,导致LED亮度强弱变化)、电机调速(电压值变化,导致电机速度变化)等。

4.8.3. TIM定时作用

  定时器(Timer)最基本的功能就是定时,这里以官方例程HAL_10_TIM_BASE为例,阐述TIM定时作用的设计方法,实现流水灯。
定时器的定时设计方法:
 参数配置:PSC、ARR,开启定时中断。可采用STM32CubeMX或者程序设计来实现。
 main.c中调用TIM初始化语句、开启定时中断HAL_TIM_Base_Start_IT(&htim1)。
 编写中断回调函数HAL_TIM_PeriodElapsedCallback,实现功能要求。

1. 初始化配置(STM32CubeMX)

  定时器的参数配置,可以首先使用STM32CubeMX进行初步设置。还可以在程序设计时,进行二次修改。
  以TIM3为例,配置出1HZ的频率,也就是1s发生一次溢出中断。
  80MHZ经过PSC分频,80MHZ/(7999+1) ,得到10KHZ的时钟频率(周期0.0001s)。ARR设为10K-1,则计数10K次,产生溢出中断,即实现1s的计时 。
  STM32CubeMX配置,如下图:
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.8 TIM---PWM输出实验_第8张图片
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.8 TIM---PWM输出实验_第9张图片

2. 应用程序设计(KEIL5)

1)定时器参数配置二次修改、初始化
  如上,STM32CubeMX参数配置完成后,在工程项目中生成对应的初始化函数MX_TIM1_Init(),并在main.c中自动调用。该函数包含了CubeMX所配置的各项参数。
在这里插入图片描述
  PSC、ARR等参数,还可以通过对函数MX_TIM1_Init()内部参数进行二次修改,如,官方例程HAL_10_TIM_BASE中:
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.8 TIM---PWM输出实验_第10张图片
  如上图,其与前述STM32CubeMX中TIM1设置不一样,也就是说MX_TIM1_Init()内部参数可以进行二次修改。PSC=1000,ARR=79,也就是实现近似1/1000s=0.001s计时。
2)开启定时器中断
  定时器初始化配置后,还需要开启定时器中断,使用函数 HAL_TIM_Base_Start_IT (&htim1);其中htim1表示定时器TIM1,定义方法:TIM_HandleTypeDef htim1。通常,通过STM32CubeMX配置TIM1后,在time.c文件中自动定义,直接使用它即可。
在这里插入图片描述
在这里插入图片描述
3)编写中断回调函数
  中断回调函数HAL_TIM_PeriodElapsedCallback()是实现TIM定时的关键。按照其设计框架,需要手动编写其代码,实现不同功能要求。
  从定时器中断原理来说,每个定时器中断,就执行其中断服务函数HAL_TIM_IRQHandler(在库stm32g4xx_hal_tim.c中已定义)。中断服务函数HAL_TIM_IRQHandler,由HAL库提供,无需用户编辑,但其内部自动执行中断回调函数HAL_TIM_PeriodElapsedCallback。
  因此,我们需要编写中断回调函数HAL_TIM_PeriodElapsedCallback,以实现不同功能要求。如官方例程HAL_10_TIM_BASE中,使用TIM1,实现0.1s流水灯效果。中断回调函数HAL_TIM_PeriodElapsedCallback代码编辑为:

/* USER CODE BEGIN 0 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	static uint16_t counter = 0;
	static uint16_t led = 0x0001, i = 0, dir = 0;
	
	if(++counter == 100){
		counter = 0;
		GPIOC->ODR = ~(led << (8 + i));
		GPIOD->BSRR |= GPIO_PIN_2;
		__nop();__nop();__nop();
		GPIOD->BRR |= GPIO_PIN_2;
		
		if(dir == 0){
			if(++i == 7){
				dir = 1;
			}
		}else{
			if(--i == 0){
				dir = 0;
			}
		}
	}
	//HAL_TIM_Base_Start_IT(&htim1);
}
/* USER CODE END 0 */

  前面参数配置中,实现了定时器0.001s计时,也就是说0.001s发生一次中断,每0.001s执行一次中断回调函数HAL_TIM_PeriodElapsedCallback。因此,中断回调函数内部每100次执行一次LED显示、移位操作,从而实现0.001s *100=0.1s流水灯。

4.8.4. PWM输出

这里,要求实现(固定频率,占空比可调:呼吸灯):初始化定时器定时10ms,输出PWM,使LED1闪烁。

1. 初始化配置(STM32CubeMX)

STM32CubeMX中,对定时器PWM方式配置分成2个方面:
1)PWM输出引脚的设定
LED1对应的GPIO是PC8,查阅STM32G431RB数据手册,PC8可用的定时器可用TIM3的通道3。若选用其他GPIO输出PWM,同理,还得查阅该手册,找到合适的TIM通道:
在这里插入图片描述
  STM32CubeMX中设置PC8输出方式为TIM3_CH3。PD2设置为Output。
其他GPIO、SYS、时钟树(80MHz)配置参考前述。(图略)
2)TIM3的PWM方式配置
  如下图,STM32CubeMX中对TIM3的PWM设置。
其中,TIM3的定时周期配置成10ms(PSC=7999,ARR=99),才能达到呼吸灯显示效果,否则呼吸灯显示不明显。
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.8 TIM---PWM输出实验_第11张图片
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.8 TIM---PWM输出实验_第12张图片
其中,PWM mode1和mode2的概念:
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.8 TIM---PWM输出实验_第13张图片
  模式1和模式2区别不大,选用模式1即可。
  上图中,占空比默认为0,后面在程序设计中可修改。
3)main.c程序设计
  与PWM相关的函数有4个:
 回调函数: void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
 开启PWM: HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
 停止PWM :HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);
 配置占空比:__HAL_TIM_SetCompare (&htim3,TIM_CHANNEL_3, i);//i取值0~ARR
 设置自动重装值: __HAL_TIM_SET_AUTORELOAD(htim, arr)
  这里,主要使用开启PWM、配置占空比2个函数,实现呼吸灯效果。main函数的程序设计如下:

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM3_Init();
  /* USER CODE BEGIN 2 */
  HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);//关闭锁存器
  HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_3);//使能定时器3的通道3,产生PWM
  /* USER CODE END 2 */
   /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);//开启锁存器
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_All, 1);//先全部关闭LED
		
	uint16_t i=0;
	for(i=0;i<100;i++){__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_3,i);HAL_Delay(20);}
	for(i=100;i>0;i--) {__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_3,i); HAL_Delay(20);}
		
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);//关闭锁存器
  }
}

  其中,HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_3)开启PWM输出,就是在引脚上输出所设定的PWM波。
  __HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_3,i),通过i的变化,使PWM波占空比变化,,LED显示出呼吸灯效果。
  编译、下载该程序,可实现固定频率,占空比可调的PWM波输出,显示呼吸灯效果。

2. 可修改频率、占空比的PWM波

  部分题目要求实现频率和占空比都可调节的PWM波,那么,在STM32CubeMX配置中略作修改。
  如下图,在STM32CubeMX中,对TIM设置成可修改频率和占空比:
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.8 TIM---PWM输出实验_第14张图片
  则,程序设计可使用以下2个宏定义函数,进行参数修改:

  • 设置自动重装值: __HAL_TIM_SET_AUTORELOAD (&htim3, arr)
    通过设置自动重装值,可获得PWM信号周期为Tpwm=(arr+1)(PSC+1)/ 80MHz,其中PSC由CubeMX配置(也可以TIM初始化程序中二次修改)。
  • 配置占空比:__HAL_TIM_SetCompare (htim, Channel, cmp);// cmp取值范围0~arr
    占空比=cmp/(arr+1)。

如,在main.c中编辑函数TIM_Proc():

void TIM_Proc(void)
{
    __HAL_TIM_SET_AUTORELOAD (&htim3, 9999);
    __HAL_TIM_SetCompare (&htim3, TIM_CHANNEL_3, 2000);
}

  最后在while中调用TIM_Proc(),就可以实现TIM3_CH1输出的PWM波,频率为100Hz(PSC=79,ARR=9999),占空比为20%(2000/(ARR+1))。
  一般题目中测量PWM波要求使用PA6或PA7引脚。查询TIM引脚分布,可选择PA6–》TIM3_CH1,PA7–》TIM3_CH2。STM32CubeMX配置和程序设计方法,参看前述。
在这里插入图片描述
使用示波器,就可以从PA6、PA7观测PWM波,或者打开KEIL仿真功能,检测PA6、PA7的输出波形。

3. 小练习

第十二届蓝桥杯嵌入式省赛对PWM的考察为例,PWM部分要求:
《STM32单片机开发应用教程(HAL库版)—基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第四章4.8 TIM---PWM输出实验_第15张图片
设计思路:
1) STM32CubeMX中配置PA7–》TIM3_CH2输出PWM波:2KHz(PSC=399,ARR=99)
2)利用函数__HAL_TIM_SetCompare (&htim3,TIM_CHANNEL_2,20),实现20%占空比。
注意开启PWM:HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1)
3) 按键切换控制,参看4.3节按键控制程序设计(按键扫描函数Key_scan,按键服务函数Key_proc)

4.8.5. 小结

STM32CubeMX配置:输出引脚,TIMx_CHx,PSC,ARR
TIM定时和PWM输出,对应的函数有所不同。

  • TIM定时(中断方式)的库函数:
     开启定时中断:HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim);
     关闭定时中断:HAL_StatusTypeDef HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim);
     中断回调函数:HAL_TIM_PeriodElapsedCallback(htim);
  • PWM的库函数/宏定义(_HAL):
     回调函数 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);
     开启PWM HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
     停止PWM HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);
     配置占空比: __HAL_TIM_SetCompare (htim, Channel, cmp);
     设置自动重装值ARR: __HAL_TIM_SET_AUTORELOAD (&htim3, arr);

你可能感兴趣的:(嵌入式,KEIL5,stm32CubeMX,stm32,蓝桥杯,c语言)