功能实现:
- 采用定时器PWM功能实现呼吸灯的功能,PWM频率为1KHz,呼吸灯周期为1s
准备工作:
- 1、STM32开发板(我的是STM32F103VET6)
- 2、STM32CubeMx软件、 IDE: Keil软件
- 3、按键管脚 : PA0 PC13
- 4、LED管脚 : PB0 PB1 PB5
什么是PWM
脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。
原理讲解:
下图为向上计数模式:
- 在PWM输出模式下,除了CNT(计数器当前值)、ARR(自动重装载值)之外,还多了一个值CCRx(捕获/比较寄存器值)。
- 当CNT小于CCRx时,TIMx_CHx通道输出低电平;
- 当CNT等于或大于CCRx时,TIMx_CHx通道输出高电平。
PWM的一个周期
- 定时器从0开始向上计数
- 当0-t1段,定时器计数器TIMx_CNT值小于CCRx值,输出低电平
- t1-t2段,定时器计数器TIMx_CNT值大于CCRx值,输出高电平
- 当TIMx_CNT值达到ARR时,定时器溢出,重新向上计数...循环此过程
- 至此一个PWM周期完成
总结:
-
每个定时器有四个通道,每一个通道都有一个捕获比较寄存器,
-
将寄存器值和计数器值比较,通过比较结果输出高低电平,便可以实现脉冲宽度调制模式(PWM信号)
-
TIMx_ARR寄存器确定PWM频率,
-
TIMx_CCRx寄存器确定占空比
PWM的工作模式:
- PWM模式1(向上计数) :计数器从0计数加到自动重装载值(TIMx_ARR),然后重新从0开始计数,并且产生一个计数器溢出事件
- PWM模式2(向下计数) :计数器从自动重装载值(TIMx_ARR)减到0,然后重新从重装载值(TIMx_ARR)开始递减,并且产生一个计数器溢出事件
STM32定时器输出通道引脚
具体不同定时器对应引脚在对应芯片数据手册的引脚说明(pin description) 中查看
这里我们以TIM3_CH1 PA6作为讲解
新建工程
1.1 New Project
- 1 搜索芯片型号
- 2选择芯片
- 3创建工程
1.2设置时钟源RCC
- 系统时钟源选择外部晶振时钟源
设置时钟
- 设置倍频为4,则定时器的时钟源频率为32M,这个数值需要用到计算定时器的定时周期
定时器设置
- 选择TIM3
- 设置定时器时钟源为内部时钟源
- 设置定时器CH1为PWM模式,对应管脚自动设置为复用模式
- 使能定时器中断
定时器参数设置
- prescaler(预分频) 31
- counter mode(基数模式) up
- counter period(计数周期) 999
- auto-reload preload(自动装载) enable
- Mode 选择PWM模式1
- Pulse(占空比值) 先给0
- PWM 极性: 设置为High,根据自己的LED连接电路设置,高电平亮就设为high,低电平亮就设为low
4项目文件设置
- 设置项目名称
- 选择所用IDE
生成代码
main函数中代码
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM3_Init();
/* USER CODE BEGIN 2 */
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
for(int i=0;i<=1000;i+=10)
{
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_1,i);
HAL_Delay(10);
}
for(int i=1000;i>=0;i-=10)
{
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_1,i);
HAL_Delay(10);
}
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
函数解析:
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1); //使能TIM3的PWM Channel1 输出
__HAL_TIM_SetCompare(&htim3, TIM_CHANNEL_1, value); //定时器的值与value比较,如果低于value,输出为低,否则为高