
Cubemx 配置


代码书写
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1); //启用PWM
uint16_t a = 100;
/* USER CODE END 2 */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_Delay(10);
a += 5;
if(a > 1000){
a = 100;
}
//通过这个宏改变占空比
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, a);
/* USER CODE END WHILE */
小灯正极连接到TIM2_CH1负极连接GND, 观察到小灯由暗到亮的过程实验成功
波形显示



/* USER CODE BEGIN Includes */
#include <stdint.h>
#include "stdio.h"
#include <string.h>
/* USER CODE END Includes */
/* USER CODE BEGIN 0 */
typedef unsigned char uint8_t_custom;
void Ano_SendPwmData(uint16_t duty, uint8_t_custom gpio_level) {
uint8_t_custom arr[12] = {0}; // 总长度12字节
// 帧头
arr[0] = 0xAB; // 帧头
// 设备地址
arr[1] = 0x01; // 源地址(自定义)
// 目标地址
arr[2] = 0x02; // 目标地址(匿名助手)
// 功能码
arr[3] = 0xF1; // 功能码(灵活数据帧)
// 数据长度(2字节,低字节在前)
uint8_t_custom flen = 4; // 4字节数据
arr[4] = flen; // 数据长度低字节
arr[5] = 0x00; // 数据长度高字节
// 数据部分(4字节)
arr[6] = duty & 0xFF; // PWM占空比低字节
arr[7] = (duty >> 8) & 0xFF; // PWM占空比高字节
arr[8] = gpio_level; // GPIO电平
arr[9] = 0x00; // 预留字节
// 计算校验和
uint8_t_custom sumcheck = 0;
uint8_t_custom addcheck = 0;
for(uint8_t_custom i = 0; i < (flen + 6); i++) {
sumcheck += arr[i];
addcheck += sumcheck;
}
// 填充校验和
arr[10] = sumcheck;
arr[11] = addcheck;
// 发送数据到串口
HAL_UART_Transmit(&huart1, arr, 12, HAL_MAX_DELAY);
}
/* USER CODE END 0 */
int main(void)
{
/* USER CODE BEGIN 1 */
uint8_t_custom ctrl_level = 0; // 电机/呼吸灯控制引脚电平
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
HAL_Init();
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM2_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); // 启动PWM输出
uint16_t duty = 0; // 占空比比较值(0~999对应0%~100%)
uint8_t dir = 1; // 占空比变化方向:1=增大,0=减小
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
// 1. 动态设置PWM占空比
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, duty);
// 2. 获取控制引脚电平(也可直接用PWM引脚控制电机/呼吸灯)
ctrl_level = HAL_GPIO_ReadPin(CTRL_PORT, CTRL_PIN);
// 3. 保留原格式发送PWM占空比+控制电平(不修改发送格式)
Ano_SendPwmData(duty, ctrl_level);
// 4. 占空比渐变逻辑(实现呼吸/电机转速变化)
if (dir) {
duty += 10; // 占空比+1%
if (duty >= 999) dir = 0;
} else {
duty -= 10; // 占空比-1%
if (duty <= 0) dir = 1;
}
HAL_Delay(20); // 控制渐变速度
/* USER CODE END WHILE */

这段代码产生的是占空比渐变的"三角波效果" (对应电机/呼吸灯的平滑变化),而非固定占空比的方波,核心原因是代码中实现了占空比的连续渐变逻辑,具体解析如下:
- 方波的本质是「固定占空比/突变占空比」
方波的特征是:PWM的占空比保持固定值 (如50%占空比,高低电平时间相等),或在两个固定值之间快速突变(如0%和100%切换),波形表现为"高低电平交替、占空比无渐变"。
- 这段代码的逻辑是「占空比平滑渐变」
代码中通过 duty(占空比比较值)的逐步增减+方向切换,实现了占空比的连续变化,最终呈现"三角波形状"的占空比曲线:
uint16_t duty = 0; // 占空比比较值(0~999对应0%~100%)
uint8_t dir = 1; // 方向:1=增大,0=减小
// 占空比渐变逻辑
if (dir) {
duty += 10; // 占空比+1%(逐步增大)
if (duty >= 999) dir = 0; // 到最大值后切换方向
} else {
duty -= 10; // 占空比-1%(逐步减小)
if (duty <= 0) dir = 1; // 到最小值后切换方向
}
-
duty从0→999→0循环变化,占空比随之从0%→100%→0%平滑渐变; -
结合
HAL_Delay(20)的延时,占空比的变化是缓慢且连续的,最终表现为"三角波效果"(对应电机转速/呼吸灯亮度的平滑变化)。
- 底层PWM仍是方波,但"宏观效果是三角波"
要明确两个层面的波形:
-
硬件层PWM :TIM2输出的是高频方波(周期固定,由TIM的ARR值决定);
-
功能层效果 :由于占空比在连续渐变,方波的"平均电压"(或设备响应)会呈现三角波形状(比如呼吸灯的亮度从暗→亮→暗的平滑过渡)。
总结
这段代码的核心逻辑是占空比的连续渐变 ,而非固定/突变占空比,因此呈现的是"三角波效果";若要实现方波,只需让占空比在两个固定值之间突变 (比如直接切换 duty=0 和 duty=999)即可。
遗留问题:怎么生成动态改变的PWM波!!!!!!