无题
发表于|更新于
|阅读量:
8.4 PWM输出功能
title: 定时器
8.4.1 基本介绍
PWM( Pulse Width Modulation ) 脉冲带宽调制是一种对模拟信号电平进行数字编码的方式。
$$
占空比:Duty=\frac{T_{on}}{period}\times100%
$$
$$
平均电压=峰值\times占空比
$$
8.4.2 捕获 / 比较通道
![[Pasted image 20240516200510.png]]
![[Pasted image 20240516200614.png]]
- 捕获 / 比较通道由三个模块组成:输入捕获单元、捕获/比较寄存器、输出比较单元。
- 每个计时器都有4个通道:
- 每个通道都有3个模块,但每个通道只能选择一个,捕获或是比较功能。
- 每个通道的模块是独立的,但是==共用一个时基单元,故可产生不同占空比的PWM波,但他们的周期是一样的,CCCR不同,ARR和PSC相同==
8.4.3 PWM的数据类型data type
1 OCMode 输出比较模式
2 Pulse
用于设置捕获比较值CCR
3 OCPolarity 极性 & PWM1、2
相同==增减方式==和相同==有效电平==情况下,PWM1和PWM2为==互补输出==。
4 OCFastMode
8.4.4 PWM输出的两个HAL函数
1 2 3 4 5 6 7
| >> 轮询方式启动PWM HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel); HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
>> 设置 CRR 捕获比较值 __HAL_TIM_SET_COMPARE(__HANDLE_, ___CHANNEL__, ___COMPARE__); __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, duty);
|
8.5 输入捕获
8.5.1 公式
![[Pasted image 20240516220912.png]]
![[Pasted image 20240516221006.png]]
==如果信号周期大于完整的计数周期(0–ARR)==
$$
Diff=COUNT*(ARR+1)-CCRx_1+CCRx_2
$$
8.5.x 信号测量
1 任务要求
2 实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| >> 主程序 >> period = CapVal[2]-CapVal[0] >> hightime = CapVal[1]-CapVal[0] >> uint32_t CapVal[3] = {0}; uint32_t CapIndex = 0;
volatile uint32_t CapFlag = 0; uint32_t period = 0; uint32_t hightime = 0;
int main(void) { printf("/* Timer Capture Function */ \r\n"); HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
while(1) { if( CapFlag == 1 ) { if( CapVal[2] >= CapVal[0] ) { period = CapVal[2]-CapVal[0]; } else { period = 0xFFFFFFFF + 1 - CapVal[0] + CapVal[2]; } printf("Period :%.2fms\r\n", period/100000.0); printf("frequency:%dHz\r\n", 100000000/period); if( CapVal[1] >= CapVal[0] ) { hightime = CapVal[1]-CapVal[0]; } else { hightime = 0xFFFFFFFF + 1 - CapVal[0] + CapVal[1]; } printf("hightime :%.2fms\r\n", hightime/100000.0); printf("duty :%.1f%%\r\n", hightime/period*100.0); printf("*******************************\r\n"); CapFlag = 0;
HAL_Delay(1000); HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); } } }
|
- 0xFFFFFFFF即自动重载值,避免溢出时造成计数混乱。
- period / 100,000 是因为tim2未PSC,只有ARR=0xFFFFFFFF,但这与计数count无关,所以count的周期为0.01us=1/100,000ms,周期单位为ms.
- 其中频率为100,000,000 / period是因为上面的周期是ms单位,那么频率是跟s有关的,所以乘1000.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| >>回调函数 void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if( htim->Instance == TIM2 ) { if( htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1 ) { switch( CapIndex ) { case 0: { CapVal[0] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, \ TIM_INPUTCHANNELPOLARITY_FALLING); CapIndex = 1; break; } case 1: { CapVal[1] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); __HAL_TIM_SET_CAPTUREPOLARITY(htim, TIM_CHANNEL_1, \ TIM_INPUTCHANNELPOLARITY_RISING); CapIndex = 2; break; } case 2: { CapVal[2] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); HAL_TIM_IC_Stop_IT(htim, TIM_CHANNEL_1); CapIndex = 0; CapFlag = 1; break; } default: { Error_Handler(); break; } } } } }
|
- 其中判断中断采用的时==ACTIVE_CHANNEL_1==,表示的是判断中断产生中==正在活动的通道==。
- 还可以在一次上升沿之后修改为双边沿,就少修改一次触发方式,见[[嵌入式/作业/8 定时器 timer#6.3 Answer|8 定时器 timer]]