作业内容
完成PWM实验:实现蜂鸣器发出响声、马达震动和风扇转动
思路分析
1. 电路分析
蜂鸣器:TIM4_CH1---->PB6 gpio toggle gpiob6
风扇:TIM1_CH1---->PE9 gpio toggle gpioe9
马达:TIM16_CH1---->PF6 gpio toggle gpiof6
2. RCC章节分析
- 设置GPIOB控制器使能:RCC_MP_AHB4ENSETR[1] = 1
- 设置TIM4控制器使能:RCC_MP_APB1ENSETR[2] = 1
3. GPIO章节分析
- 设置PB6引脚为复用功能:GPIOB_MODER[13:12] = 10
- 设置PB6引脚复用功能为TIM4_CH1:GPIOB_AFRL[27:24] = 0010
4. TIM4章节分析(以蜂鸣器为例)
- TIM4_CR1[7] = 1 ------>自动重载计数器预加载使能
TIM4_CR1[6:5] = 00 ------>设置边沿对齐模式
TIM4_CR1[4] = 1 ------>设置递减计数器
TIM4_CR1[0] = 1 ------>设置计数器使能 - TIM4_CCMR1[16][6:4] = 0110------>设置为PWM1模式
TIM4_CCMR1[3] = 1 ------>设置预加载使能
TIM4_CCMR1[1:0] = 00 ------>设置为输出模式 - TIM4_CCER[3] = 0------>设置TIM4_CH1通道为输出模式
TIM4_CCER[1] = 0------>设置TIM4_CH1起始状态高电平
TIM4_CCER[0] = 1------>设置TIM4_CH1输出使能 - TIM4_PSC------>设置预分频寄存器的值
- TIM4_ARR------>设置PWM方波最终周期
- TIM4_CCR1------>设置PWM方波的占空比
代码实现
pwm.h
#ifndef __PWM_H__
#define __PWM_H__
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_tim.h"
void buzzer_init(void);
void motor_init(void);
void fan_init(void);
#endif
pwm.c
#include "pwm.h"
void buzzer_init(void)
{
//设置GPIOB,TIM4的时钟使能
RCC->MP_AHB4ENSETR |= (0x1 << 1);
RCC->MP_APB1ENSETR |= (0x1 << 2);
//设置PB6引脚为复用功能
GPIOB->MODER &= (~(0x3 << 12));
GPIOB->MODER |= (0x2 << 12);
//设置PB6引脚为TIM4_CH1功能
GPIOB->AFRL &= (~(0xf << 24));
GPIOB->AFRL |= (0x2 << 24);
//设置TIM4_CH1通道的预装载寄存器的缓冲区的使能
//TIM4_CR1[7] = 0x1
TIM4->CR1 |= (0x1 << 7);
//设置定时器的计数方式,边沿对齐
//TIM4_CR1[6:5] = 0x0
TIM4->CR1 &= (~(0x3 << 5));
//设置定时器计数的方向,采用递减计数/递增计数
//TIM4_CR1[4] = 0x1 | 0x0
TIM4->CR1 |= (0x1 << 4);
//使能TIM4_CH1计数器
//TIM4_CR1[0] = 0x1
TIM4->CR1 |= (0x1 << 0);
//设置TIM4_CH1通道为PWM1模式
//TIM4_CCMR1[16] TIM4_CCMR1[6:4]
//pwm模式1 = 0b0110
TIM4->CCMR1 &= (~(0x1 << 16));
TIM4->CCMR1 &= (~(0x7 << 4));
TIM4->CCMR1 |= (0x6 << 4);
//设置TIM4_CH1通道使能TIMx_CCR1预加载使能寄存器
//TIM4_CCMR1[3] = 0x1
TIM4->CCMR1 |= (0x1 << 3);
TIM4->CCMR1 &= (~(0x3 << 0));
//设置TIM4_CH1通道输出PWM方波的极性,
//TIM_CCER[3] = 0b0 TIM4_CCER[1] = 0x1 or 0x0
TIM4->CCER &= (~(0x1 << 3));
TIM4->CCER &= (~(0x1 << 1));
//设置TIM4_CH1通道的输出使能位,输出PWM方波
//TIM4_CCER[0] = 0x1
TIM4->CCER |= (0x1 << 0);
//设置预分频寄存器,TIM4_PSC[15:0] CK_PSC = 209MHz
//提供给TIM4的时钟源的频率是209MHz
TIM4->PSC = 209 - 1;
//设置PWM方波的最终的周期 TIM4_ARR[16:0]
//得到一个1000-2000Hz的方波
TIM4->ARR = 1000;
//设置PWM方波的占空比 TIM4_CCR1[16:0]
TIM4->CCR1 = 700;
}
void motor_init(void)
{
//设置GPIOF,TIM16的时钟使能
RCC->MP_AHB4ENSETR |= (0x1 << 5);
RCC->MP_APB2ENSETR |= (0x1 << 3);
//设置PF6引脚为复用功能
GPIOF->MODER &= (~(0x3 << 12));
GPIOF->MODER |= (0x2 << 12);
//设置PF6引脚为TIM16_CH1功能
GPIOF->AFRL &= (~(0xf << 24));
GPIOF->AFRL |= (0x1 << 24);
//设置TIM16_CH1通道的预装载寄存器的缓冲区的使能
//TIM16_CR1[7] = 0x1
TIM16->CR1 |= (0x1 << 7);
//设置定时器的计数方式,边沿对齐
//TIM16_CR1[6:5] = 0x0
//TIM16->CR1 &= (~(0x3 << 5));
//设置定时器计数的方向,采用递减计数/递增计数
//TIM16_CR1[4] = 0x1 | 0x0
//TIM16->CR1 |= (0x1 << 4);
//使能TIM16_CH1计数器
//TIM16_CR1[0] = 0x1
TIM16->CR1 |= (0x1 << 0);
//设置TIM16_CH1通道为PWM1模式
//TIM16_CCMR1[16] TIM16_CCMR1[6:4]
//pwm模式1 = 0b0110
TIM16->CCMR1 &= (~(0x1 << 16));
TIM16->CCMR1 &= (~(0x7 << 4));
TIM16->CCMR1 |= (0x6 << 4);
//设置TIM16_CH1通道使能TIMx_CCR1预加载使能寄存器
//TIM16_CCMR1[3] = 0x1
TIM16->CCMR1 |= (0x1 << 3);
TIM16->CCMR1 &= (~(0x3 << 0));
//设置TIM16_CH1通道输出PWM方波的极性,
//TIM_CCER[3] = 0b0 TIM16_CCER[1] = 0x1 or 0x0
//TIM16->CCER &= (~(0x1 << 3));
TIM16->CCER &= (~(0x1 << 1));
//设置TIM16_CH1通道的输出使能位,输出PWM方波
//TIM16_CCER[0] = 0x1
TIM16->CCER |= (0x1 << 0);
//设置预分频寄存器,TIM16_PSC[15:0] CK_PSC = 209MHz
//提供给TIM4的时钟源的频率是209MHz
TIM16->PSC = 209 - 1;
//设置PWM方波的最终的周期 TIM16_ARR[16:0]
//得到一个1000-2000Hz的方波
TIM16->ARR = 1000;
//设置PWM方波的占空比 TIM16_CCR1[16:0]
TIM16->CCR1 = 700;
TIM16->BDTR |= (0x1 << 15);
}
void fan_init(void)
{
//设置GPIOE,TIM1的时钟使能
RCC->MP_AHB4ENSETR |= (0x1 << 4);
RCC->MP_APB2ENSETR |= (0x1 << 0);
//设置PE9引脚为复用功能
GPIOE->MODER &= (~(0x3 << 18));
GPIOE->MODER |= (0x2 << 18);
//设置PE9引脚为TIM1_CH1功能
GPIOE->AFRH &= (~(0xf << 4));
GPIOE->AFRH |= (0x1 << 4);
//设置TIM1_CH1通道的预装载寄存器的缓冲区的使能
//TIM1_CR1[7] = 0x1
TIM1->CR1 |= (0x1 << 7);
//设置定时器的计数方式,边沿对齐
//TIM1_CR1[6:5] = 0x0
TIM1->CR1 &= (~(0x3 << 5));
//设置定时器计数的方向,采用递减计数
//TIM1_CR1[4] = 0x1
TIM1->CR1 |= (0x1 << 4);
//使能TIM1_CH1计数器
//TIM1_CR1[0] = 0x1
TIM1->CR1 |= (0x1 << 0);
//设置TIM1_CH1通道为PWM1模式
//TIM1_CCMR1[16] TIM1_CCMR1[6:4]
//pwm模式1 = 0b0110
TIM1->CCMR1 &= (~(0x1 << 16));
TIM1->CCMR1 &= (~(0x7 << 4));
TIM1->CCMR1 |= (0x6 << 4);
//设置TIM1_CH1通道使能TIMx_CCR1预加载使能寄存器
//TIM1_CCMR1[3] = 0x1
TIM1->CCMR1 |= (0x1 << 3);
TIM1->CCMR1 &= (~(0x3 << 0));
//设置TIM1_CH1通道输出PWM方波的极性,
//TIM1_CCER[3] = 0b0 TIM1_CCER[1] = 0x1 or 0x0
TIM1->CCER &= (~(0x1 << 1));
//设置TIM1_CH1通道的输出使能位,输出PWM方波
//TIM1_CCER[0] = 0x1
TIM1->CCER |= (0x1 << 0);
//设置预分频寄存器,TIM1_PSC[15:0] CK_PSC = 209MHz
//提供给TIM1的时钟源的频率是209MHz
TIM1->PSC = 209 - 1;
//设置PWM方波的最终的周期 TIM1_ARR[16:0]
//得到一个1000-2000Hz的方波
TIM1->ARR = 1000;
//设置PWM方波的占空比 TIM1_CCR1[16:0]
TIM1->CCR1 = 700;
TIM1->BDTR |= (0x1 << 15);
}
main.c
#include "pwm.h"
extern void printf(const char *fmt, ...);
int main(void)
{
buzzer_init();
motor_init();
fan_init();
while(1);
return 0;
}