STM32呼吸灯实验(寄存器版本)
在继定时器中断之后,开始PWM的学习,
脉冲宽度调制(PWM),是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制。
以下就是原子的PWM的原理图
图中,我们假定定时器工作在向上计数PWM模式,且当CNT<CCRx时,输出0,当CNT>=CCRx时输出1。那么就可以得到如上的PWM示意图:当CNT值小于CCRx的时候,IO输出低电平(0),当CNT值大于等于CCRx的时候,IO输出高电平(1),当CNT达到ARR值的时候,重新归零,然后重新向上计数,依次循环。改变CCRx的值,就可以改变PWM输出的占空比,改变ARR的值,就可以改变PWM输出的频率,这就是PWM输出的原理。 STM32的定时器除了TIM6和7。其他的定时器都可以用来产生PWM输出。其中高级定时器TIM1和TIM8可以同时产生多达7路的PWM输出。而通用定时器也能同时产生多达4路的PWM输出。(选自《不完全手册》)
废话不多说直接说代码:
我是外接了一个LED灯进行呼吸灯的实验。
首先是捕获/比较模式寄存器(TIMx_CCMR1/2),该寄存器总共有2个,TIMx _CCMR1和TIMx _CCMR2。TIMx_CCMR1控制CH1和2,而TIMx_CCMR2控制CH3和4。
图1
图2
在这里,我们用的是[PB1]的io口,同时采用TIM3定时器。
..图3
注意这里是TIM3_CH4,所以我们在配置CCMR时采用的是上图2中黄色笔标记的位。捕获比较的都是4通道,具体配置查看中文参考手册14.4
我们在这里设置PWM1模式
代码如下:.
TIM3->CCMR2|=6<<12; //CH4 PWM2模式
TIM3->CCMR2|=1<<11; //CH4预装载使能
关键配置就是以上操作:具体步骤查看具体代码:(一定要注意注释!!!!!)
time.h
#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"
#define LED0_PWM_VAL TIM3->CCR4 //注意:我们要捕获的是4通道
void TIM3_Int_Init(u16 arr,u16 psc);
void TIM3_PWM_Init(u16 arr,u16 psc);
#endif
time.c
#include "timer.h"
#include "led.h"
//TIM3_CH1 PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void TIM3_PWM_Init(u16 arr,u16 psc)
{
//此部分需手动修改IO口设置
RCC->APB1ENR|=1<<1; //TIM3时钟使能
GPIOB->CRL&=0XFFFFFF0F; //PB1清除之前的设置
GPIOB->CRL|=0X000000B0; //复用功能输出
TIM3->ARR=arr; //设定计数器自动重装值
TIM3->PSC=psc; //预分频器设置
TIM3->CCMR2|=6<<12; //CH4 PWM2模式
TIM3->CCMR2|=1<<11; //CH4预装载使能
TIM3->CCER|=1<<12; //OC4 输出使能
//TIM1->BDTR|=1<<15; //MOE 主输出使能
TIM3->CR1=0x0080; //ARPE使能
TIM3->CR1|=0x01; //使能定时器3
}
led.c
#include "sys.h"
#include "led.h"
void LED_Init(void)
{
RCC->APB2ENR|=1<<3;
GPIOB->CRL&=0XFFFFFF0F;
GPIOB->CRL|=0x00000030;
GPIOB->ODR|=1<<1;//PB1
}
main.c
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "timer.h"
int main(void)
{
u16 led0pwmval=0;
u8 dir=1;
Stm32_Clock_Init(9); //系统时钟设置
delay_init(72); //延时初始化
uart_init(72,9600); //串口初始化
LED_Init(); //初始化与LED连接的硬件接口
TIM3_PWM_Init(899,0);//不分频。PWM频率=72000/(899+1)=80Khz
while(1)
{
//delay_ms(10);
if(dir)led0pwmval++;
else led0pwmval--;
if(led0pwmval>300)dir=0;
if(led0pwmval==0)dir=1;
LED0_PWM_VAL=led0pwmval;
//printf("%d\r\n",LED0_PWM_VAL);
}
}
这样代码就完成了!
暗
较暗
亮
OK!今天笔记记于此结束!