stm32f103pwm实现呼吸灯(寄存器)
一、思路
- 通过 Tim 定时器可以设置多路 PWM 实现呼吸灯,所以我们使能一个 TIM3,因为 TIM3 的通道2(CH2)正好映射到 PB5(LED)
- 然后配置 PB5 为复用推挽输出,50MHZ
- pwm通过定时器 TIM3 的计数器 CNT 从 0 到 ARR(ARR可以设置为0-65535) 进行周期的自增或自减, CNT 每自增或自减一次与 CCR2 比较一次,CCR2的值由我们自己设置,一般通过 while 循环按照我们希望的时间 比如1s增加1
如果在PWM模式1下 CNT向上计数时 CNT < CCR2 则将 PB5设为高电平
如果在PWM模式2下 CNT向上计数时 CNT < CCR2 则将 PB5设为低电平
通过 占空比 = 高电平时间 / 总时间 的变化实现呼吸灯效果
二、pwm_init()代码
void pwm_init() {
//1.配置AFIO 进行端口映射
//使能AFIO
RCC->APB2ENR |= 1 << 0;
//使能GPIOB RCC时钟
RCC->APB2ENR |= 1 << 3;
//使能TIM3
RCC->APB1ENR |= 1 << 1;
//把TIM3部分映射到GPIOB5
AFIO->MAPR |= 1 << 11;
AFIO->MAPR &= ~(1 << 10);
//2.配置GPIOB5端口
//设置GPIOB5为 复用推挽输出 即 [23:22] = CNF[1:0]
GPIOB->CRL |= 1 << 23;
GPIOB->CRL &= ~(1 << 22);
//设置GPIOB5为 输出模式 速度50MHZ 即 [21:20] = MODE[1:1]
GPIOB->CRL |= 1 << 21;
GPIOB->CRL |= 1 << 20;
//LED-OFF
GPIOB->ODR |= 1 << 5;
//3.配置TIM3
//PSC为定时器的分频器
TIM3->PSC = 0;
//ARR为定时器计数上限 设置自动重装载值
TIM3->ARR = 5000;
//TIM3->CH2 设置PWM模式1
TIM3->CCMR1 |= 6 << 12;
//TIM3->CH2 预装载使能
TIM3->CCMR1 |= 1 << 11;
//TIM3->CH2 输出使能
TIM3->CCER |= 1 << 4;
//使能 ARPE ARR寄存器的值被装入缓冲器。
TIM3->CR1 |= 1 << 7;
//使能计数器
TIM3->CR1 |= 1 << 0;
//通过while循环设置TIM3->CCR2的值
int nFlag = 1;
int nPwmValue = 0;
while (1) {
//通过for循环设置每次变化时间
for (volatile int i = 0; i < 100; i++) {}
//通过设置 nFlag 的设置自增或自减
if (nFlag) {
nPwmValue++;
} else {
nPwmValue--;
}
//设置周期最大值
if (nPwmValue >= 5000) {
nFlag = 0;
}
//设置周期最小值
if (nPwmValue <= 0) {
nFlag = 1;
}
//设置 CCR2 的值
TIM3->CCR2 = nPwmValue;
}
}
三、 分步讲解
1.配置AFIO 进行端口映射 (部分芯片可能不支持 可采用跳线方式实现)
//使能AFIO
RCC->APB2ENR |= 1 << 0;
//使能GPIOB RCC时钟
RCC->APB2ENR |= 1 << 3;
//使能TIM3
RCC->APB1ENR |= 1 << 1;
//把TIM3部分映射到GPIOB5
AFIO->MAPR |= 1 << 11;
AFIO->MAPR &= ~(1 << 10);
2.配置GPIOB5端口
//设置GPIOB5为 复用推挽输出 即 [23:22] = CNF[1:0]
GPIOB->CRL |= 1 << 23;
GPIOB->CRL &= ~(1 << 22);
//设置GPIOB5为 输出模式 速度50MHZ 即 [21:20] = MODE[1:1]
GPIOB->CRL |= 1 << 21;
GPIOB->CRL |= 1 << 20;
//LED-OFF
GPIOB->ODR |= 1 << 5;
3.配置TIM3
//PSC为定时器的分频器
TIM3->PSC = 0;
//ARR为定时器计数上限 设置自动重装载值
TIM3->ARR = 5000;
//TIM3->CH2 设置PWM模式1
TIM3->CCMR1 |= 6 << 12;
//TIM3->CH2 预装载使能
TIM3->CCMR1 |= 1 << 11;
//TIM3->CH2 输出使能
TIM3->CCER |= 1 << 4;
//使能 ARPE ARR寄存器的值被装入缓冲器。
TIM3->CR1 |= 1 << 7;
//使能计数器
TIM3->CR1 |= 1 << 0;
//通过while循环设置TIM3->CCR2的值
int nFlag = 1;
int nPwmValue = 0;
while (1) {
//通过for循环设置每次变化时间
for (volatile int i = 0; i < 100; i++) {}
//通过设置 nFlag 的设置自增或自减
if (nFlag) {
nPwmValue++;
} else {
nPwmValue--;
}
//设置周期最大值
if (nPwmValue >= 5000) {
nFlag = 0;
}
//设置周期最小值
if (nPwmValue <= 0) {
nFlag = 1;
}
//设置 CCR2 的值
TIM3->CCR2 = nPwmValue;
}