历史上的今天
今天是:2024年09月28日(星期六)
2021年09月28日 | stm32f103pwm实现呼吸灯(寄存器)
2021-09-28 来源:eefocus
一、思路
通过 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


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;
}








史海拾趣
|
呵呵,ARM7、ARM9 还有PXA3XX 等等嵌入式ARM都存在高低温时容易爆发故障?尤其是主频越高的CPU,越容易爆发高低温故障? 这是为什么? 这是因为我们疏忽了对于整个系统中的很多关键信号的完整性的研究、分析与设计; 我们的硬件、软硬件协调设计 ...… 查看全部问答> |
|
我的设备中没有加声卡,只有一个蜂器鸣,写了个蜂鸣器的驱动,WINCE中的函数MessageBeep()如何去实现呢?MessageBeep()都调用了哪些函数和信息?请指点一下,谢谢!… 查看全部问答> |
|
cannot open file 'ceddk.lib'(急寻解决办法) 别人考我一个工程EVC的 在他那可以运行 在我电脑上运行报错如下: LINK : fatal error LNK1104: cannot open file \'ceddk.lib\' 是要将这个库加到工程中吗? 哪位有这个库的发我一个 万分感谢! mickeyhao66@163.com… 查看全部问答> |
|
WinCE中,在主对话框中有一子对话框,在子对话框中我用 CreateWindow(TEXT(\"DISPLAYCLASS\")……) 创建了一个IE控件,请问如何使当我鼠标指针只要一移到IE控件中就弹出一个消息框???… 查看全部问答> |
|
8mA的sink电流比较变态。。。。。。 STM8S没有Chip_ID比较变态。。。。。。 其他都是浮云。。。。。。 swim.jpg (11.35 KB) 下载次数:32 2009-12-31 15:54 … 查看全部问答> |




