完成PWM

master
高宏宇 11 months ago
parent 124760c2e6
commit 8dcbd539d7

@ -377,19 +377,253 @@ HAL_TIM_PeriodElapsedCallback 是我们在主函数中定义的用户逻辑函
# 4. PWM输出功能
[什么是PWM](https://www.bilibili.com/video/BV1HD4y1k74L/?spm_id_from=333.337.search-card.all.click&vd_source=3c8e333d6657680a469ddf0238f01d6a)
![image-20240923144915112](./img/image-20240923144915112.png)
上述视频是以电压来讲的,我们试图用能量的方式给大家理解:
![占空比100%](img/pwm1.drawio.png)
上图是占空比 100% 的波形,显然就是直流。那么我们看做功的关系应该怎么计算?
功率U<sup>2</sup>/R
做功TxU<sup>2</sup>/R
显然这里负责的R应该是一个常量。
![占空比70%](img/pwm2.drawio.png)
同样占空比为70%的波形做功应该是:
做功DxTxU<sup>2</sup>/R
这里的D表示占空比。
如果负载是一个LED做功多就亮做功少就暗这就达到了调光的效果同样也可以调整电机的快慢。
> 注意PWM并不适合所有的功率调节例如LED灯的调光如果使用简单的PWM其实是LED不断的闪烁亮的时间和灭的时间比例。如果闪烁频率低会造成人眼的疲劳导致眼睛的疾病。目前的LED调光大多是使用调整电压电流来进行的。对电压或者电流的调整基础一般还是PWM不过后级需要更多的滤波电路以及电压电流检测电路来形成反馈回路使得输出更为稳定。
## 4.1. 捕获/比较通道
## 4.2. PWM实现原理
[动画讲解轻松学会STM32的PWM](https://www.bilibili.com/video/BV1Yx4y1x7xY/?spm_id_from=333.337.search-card.all.click&vd_source=3c8e333d6657680a469ddf0238f01d6a)
![image-20240923145011576](./img/image-20240923145011576.png)
1. 输入捕获单元:用于信号测量;
2. 捕获/比较寄存器TIMx_CCR在输入模式下用于存放存放事件的计数边缘检测时计数是多少可以测量波长和占空比输出模式下存放一个比较值用于和计数器寄存器CNT进行比较实现信号的反转从而实现PWM的占空比调整后面讲
3. 输出比较单元:根据 CCR/ARR/CNT来产生波形PWM
> 每个定时器都有14个上述的电路通道。因此一个时钟可以同时进行1-4个不同的PWM或者输入信号测量。后续的代码演示中我们一般只使用一个确定定时器的一个通道。
## 4.2. PWM实现原理p233
![image-20240923160332784](./img/image-20240923160332784.png)
1. 缺省情况下,输出为高电平;
2. TIMx_CLK经过PSC分频后为定时器提供计数脉冲
3. 计数脉冲使得CNT的计数从0进行累加
4. 当CNT和CCR的值相等后输出极性反转从高电平变为低电平
5. CNT持续计数
6. 当CNT与ARR值相等的时候极性再次反转从低电平变成高电平一个周期结束CNT被重新设置成0
因此:
1. CK_PSCTIMx_CLK、PSC、ARR 共同决定了PWM波形输出的频率这一点和作为定时器是一致的
2. CCR和ARR+1的比值决定了占空比
![image-20240923161420980](./img/image-20240923161420980.png)
> 公式8-7与公式8-4是一致的其基本原理也是一致的。
课堂练习:
如图所示:
![image-20240923162226052](./img/image-20240923162226052.png)
需要一个频率1000Hz占空比 30 % 的PWM 应该如何进行设置?
如果选用TIM1作为PWM的时钟PSC、ARR、CCR的值应该如何选取
如果选用TIM4作为PWM的时钟PSC、ARR、CCR的值应该如何选取
如果选用TIM2作为PWM的时钟PSC、ARR、CCR的值应该如何选取
## 4.3. PWM输出功能的数据类型p234
```c
typedef struct
{
uint32_t OCMode; /*!< Specifies the TIM mode.
This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */
uint32_t Pulse; /*!< Specifies the pulse value to be loaded into the Capture Compare Register.
This parameter can be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF */
uint32_t OCPolarity; /*!< Specifies the output polarity.
This parameter can be a value of @ref TIM_Output_Compare_Polarity */
uint32_t OCNPolarity; /*!< Specifies the complementary output polarity.
This parameter can be a value of @ref TIM_Output_Compare_N_Polarity
@note This parameter is valid only for timer instances supporting break feature. */
uint32_t OCFastMode; /*!< Specifies the Fast mode state.
This parameter can be a value of @ref TIM_Output_Fast_State
@note This parameter is valid only in PWM1 and PWM2 mode. */
uint32_t OCIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state.
This parameter can be a value of @ref TIM_Output_Compare_Idle_State
@note This parameter is valid only for timer instances supporting break feature. */
uint32_t OCNIdleState; /*!< Specifies the TIM Output Compare pin state during Idle state.
This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State
@note This parameter is valid only for timer instances supporting break feature. */
} TIM_OC_InitTypeDef;
```
### 4.3.1. OCMode
![image-20240923164850677](./img/image-20240923164850677.png)
### 4.3.2. Pulse(CCR)
整形这个值与ARR共同确定占空比。
### 4.3.3. OCPolarity
输出极性,如果是低电平有效,相当于占空反向;
![image-20240923165059143](./img/image-20240923165059143.png)
### 4.3.4. OCFastMode
PWM快速模式使能
![image-20240923165314079](./img/image-20240923165314079.png)
### 4.3.5. PWM1/PWM2
![image-20240923165429185](./img/image-20240923165429185.png)
其实就是极性发转。注意通常使用PWM1方式如果是PWM2方式占空比是100%-(CCR/(ARR+1)x100%)。
## 4.4. PWM输出功能的接口函数、
### 4.4.1. PWM 轮询方式启动函数(HAL_TIM_PWM_Start)
该函数用于在轮询方式下启动PWM信号的输出具体描述如表8-18所示。
![image-20240923165831385](./img/image-20240923165831385.png)
### 4.4.2. 捕获/比较寄存器设置函数(__HAL_TIM_SET_COMPARE)
该函数用于设置捕获/比较寄存器TIMxCCRn的内容采用带参数的宏实现(宏函数),具体描述如表 8-19 所示。该函数可以在任何时间改变CCR的值用于动态改变占空比。
## 4.3. PWM输出功能的数据类型
![image-20240923165956941](./img/image-20240923165956941.png)
## 4.4. PWM输出功能的接口函数
## 4.5. 基础任务输出PWM信号注意与书上不一致
使用定时器产生一个频率为1000Hz占空比为50%的方波,用于驱动蜂鸣器。
### 4.5.1. 实现过程
1. 建立一个项目 Buzzer
2. 蜂鸣器是在PB9上设置PB9的功能是 **TIM4_CH4**
![image-20240924181442772](./img/image-20240924181442772.png)
3. 配置TIM4
![image-20240924182053112](./img/image-20240924182053112.png)
注意这里缺省配置的APB1上的定时器时钟是8M要实现1000Hz的频率PSC=79ARR=99。注意在设置的时候ARR+1最好是100或者是1000等10的整数倍数。因为Pulse和ARR+1的比值决定了占空比。设置Pulse(CCR)为50这样就有了1000Hz50%的占空比。
4. 在main.c 的大约92行加入代码
```c
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_4);
/* USER CODE END 2 */
```
5. 编译下载后,可以听到蜂鸣器的声音。
### 4.5.2. 代码分析
main.c 大约147行左右是定时器的初始化
```c
static void MX_TIM4_Init(void) {
/* USER CODE BEGIN TIM4_Init 0 */
/* USER CODE END TIM4_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = { 0 };
TIM_MasterConfigTypeDef sMasterConfig = { 0 };
TIM_OC_InitTypeDef sConfigOC = { 0 };
/* USER CODE BEGIN TIM4_Init 1 */
/* USER CODE END TIM4_Init 1 */
htim4.Instance = TIM4;
htim4.Init.Prescaler = 79;
htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
htim4.Init.Period = 99;
htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim4) != HAL_OK) {
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK) {
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim4) != HAL_OK) {
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig)
!= HAL_OK) {
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 50;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_4)
!= HAL_OK) {
Error_Handler();
}
/* USER CODE BEGIN TIM4_Init 2 */
/* USER CODE END TIM4_Init 2 */
HAL_TIM_MspPostInit(&htim4);
}
```
main.c 的92行用户代码
```c
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_4);
/* USER CODE END 2 */
```
## 4.5. 基础任务输出PWM信号
上述代码是以查询方式启动TIM4的PWM因为没有使用中断。htim4是TIM4的结构体该结构书上没有说明和定时中断中的结构体是一致的可以理解成C语言的对象包括数据与很多函数指针。
## 4.6. 进阶任务:实现呼吸灯
## 4.6. 进阶任务:实现呼吸灯(略)
# 5. 输入捕获功能

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Loading…
Cancel
Save