1、PWM相关概念
pwm : 脉冲宽度调制
脉冲 :高低电平变化的方波信号
频率(单位Hz) : 1s钟产生方波信号的个数
周期(单位s) : 一个方波信号的时间
周期和频率成倒数的关系 : T = 1s / F
占空比:一个方波周期内,高电平占整个方波周期的百分比。
__ __
__| |__| 占空比 = 50%
pwm使用的场合:无源蜂鸣器的驱动,电机的调速, 屏幕的背光
2、分析蜂鸣器的电路图
有源蜂鸣器:
有源蜂鸣器内部有一个震荡源,当给有源蜂鸣器供电时,
内部的震荡源就会按照一定的频率震荡产生一个一定频率的方波信号,
实现蜂鸣器的发声。因此有源蜂鸣器一般使用高低电平驱动。
无源蜂鸣器:
无源蜂鸣器内部没有震荡源,因此需要人为的提供一个一定频率
变化的方波信号,最终实现控制无源蜂鸣器的发声。因此,无源蜂鸣器
的驱动使用PWM方波信号进行控制。
FSMP1A开发板使用的是有源蜂鸣器。
3、 分析芯片手册
3.1 分析2.5.2章节,确定GPIOB,TIM4,RCC外设控制器分别接到哪根总线上,以及外设控制器寄存器对应的基地址
3.2 分析RCC章节,使用GPIOB,TIM4外设控制器的时钟源
3.3 分析GPIO章节,设置PB6引脚为TIM4_CH1的复用功能
3.3.1 GPIOx_MODER寄存器
GPIOx_OTYPER : 默认为推挽输出
GPIOx_OSPEEDR : 默认为低速模式
GPIOx_PUPDR : 默认禁止上下拉电阻
以上三个寄存器可以设置,也可以不设置,使用默认值即可。
3.3.2 GPIOx_AFRL寄存器
3.4 分析TIM4章节,设置TIM4输出一个PWM方波信号
up:递增计数器 down :递减计数器 up/down:递增递减计数器
分频器的描述:
递增计数器:
递减计数器:
递增递减计数器:
2.4.1 TIMx_CR1寄存器
2.4.2 TIMx_CCMR1寄存器
2.4.3 TIMx_CCER寄存器
2.4.4 TIMx_PSC寄存器
2.4.5 TIMx_ARR寄存器
2.4.6 TIMx_CCR1寄存器
4、 编写驱动代码
beep.h
#ifndef _BEEP_H_
#define _BEEP_H_
#include "gpio.h"
#include "../common/include/stm32mp1xx_tim.h"
void hal_beep_init();
#endif /*_BEEP_H_*/
beep.c
#include "../include/beep.h"
void hal_beep_init(){
//使能时钟
RCC->MP_AHB4ENSETR |=(1<<1);
RCC->MP_APB1ENSETR |=(1<<2);
//GPIO
GPIOB->MODER &=~(0b11<<12);
GPIOB->MODER |=(0b10<<12);
GPIOB->AFRL &=~(0b1111<<24);
GPIOB->AFRL |=(0b0010<<24);
//
TIM4->CCMR1 &=~(1<<16);
TIM4->CCMR1 &=~(0b111<<4);
TIM4->CCMR1 |=(0b110<<4);
TIM1->CCMR1 &=~(1<<3);// OC1PE
TIM4->CCMR1 &=~(0b11);
TIM4->CCER &=~(1<<3);
TIM4->CCER &=~1;
TIM4->CCER |=1;
TIM4->CCER &=~(1<<1);
TIM4->PSC=208;
TIM4->ARR=1000;
TIM4->CCR1=700;
TIM4->CR1 &=~(1<<7);
TIM4->CR1 &=~(0b11<<5);
TIM4->CR1 &=~(1<<4);
TIM4->CR1 &=~(1);
TIM4->CR1 |=1;
}
5、 编译,下载,调试
6、完成风扇和马达的实验
对于风扇和马达使用的时TIM1_CH1和TIM16_CH1, 要想输出PWM方波信号,
必须的设置TIMx_BDTR寄存器的MOE位,设置为主输出使能,方能输出PWM方波。
motor.h
#ifndef _MOTOR_H_
#define _MOTOR_H_
#include "gpio.h"
#include "../common/include/stm32mp1xx_tim.h"
void hal_motor_init();
#endif /*_MOTOR_H_*/
motor.c
#include "../include/motor.h"
void hal_motor_init(){
//使能时钟
RCC->MP_AHB4ENSETR |=(1<<5);//使能GPIOE时钟
RCC->MP_APB2ENSETR |=(1<<3);//使能TIM1时钟
//GPIOF
GPIOF->MODER &=~(0b11<<12);//MODER 10 复用模式 PE9
GPIOF->MODER |=(0b10<<12);
GPIOF->AFRL &=~(0b1111<<24);
GPIOF->AFRL |=(0b0001<<24);//AFRH 0001
//
TIM16->CCMR1 &=~(1<<16);//TIM4->CCMR1[16,6:4] 0110
TIM16->CCMR1 &=~(0b111<<4);
TIM16->CCMR1 |=(0b110<<4);
TIM16->CCMR1 &=~(1<<3);// OC1PE
TIM16->CCMR1 &=~(0b11);//CC1S
TIM16->CCER &=~(1<<3);//CC1NP
TIM16->CCER &=~1;//CC1P
TIM16->CCER |=1;
TIM16->CCER &=~(1<<1); //CC1E
TIM16->PSC=208;
TIM16->ARR=1000;
TIM16->CCR1=500;
TIM16->BDTR &=~(1<<15);
TIM16->BDTR |=(1<<15);
TIM16->CR1 &=~(1<<7);// TIM4->CR1[7]=0 ARPE=0 不用管
TIM16->CR1 &=~(0b11<<5);// TIM4->CR1[6:5]=0b00 边沿对齐
TIM16->CR1 &=~(1<<4);
TIM16->CR1 |=(1<<4);// TIM4->CR1[4]=0 递减计数器
TIM16->CR1 &=~(1);
TIM16->CR1 |=1;// TIM4->CR1[1]=1 使能计数器
}
fan.h
#ifndef _FAN_H_
#define _FAN_H_
#include "gpio.h"
#include "../common/include/stm32mp1xx_tim.h"
void hal_fan_init();
#endif /*_FAN_H_*/
fan.c
#include "../include/fan.h"
void hal_fan_init(){
//使能时钟
RCC->MP_AHB4ENSETR |=(1<<4);//使能GPIOE时钟
RCC->MP_APB2ENSETR |=(1);//使能TIM1时钟
//GPIO
GPIOE->MODER &=~(0b11<<18);//MODER 10 复用模式 PE9
GPIOE->MODER |=(0b10<<18);
GPIOE->AFRH &=~(0b1111<<4);
GPIOE->AFRH |=(0b0001<<4);//AFRH 0001
//
TIM1->CCMR1 &=~(1<<16);//TIM4->CCMR1[16,6:4] 0110
TIM1->CCMR1 &=~(0b111<<4);
TIM1->CCMR1 |=(0b110<<4);
TIM1->CCMR1 &=~(1<<3);// OC1PE
TIM1->CCMR1 &=~(0b11);//CC1S
TIM1->CCER &=~(1<<3);//CC1NP
TIM1->CCER &=~1;//CC1P
TIM1->CCER |=1;
TIM1->CCER &=~(1<<1); //CC1E
TIM1->PSC=208;
TIM1->ARR=1000;
TIM1->CCR1=500;
TIM1->BDTR &=~(1<<15);
TIM1->BDTR |=(1<<15);
TIM1->CR1 &=~(1<<7);// TIM4->CR1[7]=0 ARPE=0 不用管
TIM1->CR1 &=~(0b11<<5);// TIM4->CR1[6:5]=0b00 边沿对齐
TIM1->CR1 &=~(1<<4);
TIM1->CR1 |=(1<<4);// TIM4->CR1[4]=0 递减计数器
TIM1->CR1 &=~(1);
TIM1->CR1 |=1;// TIM4->CR1[1]=1 使能计数器
}
main.c
#include "include/led.h"
#include "include/key.h"
#include "include/uart4.h"
#include "include/beep.h"
#include "include/fan.h"
#include "include/motor.h"
void delay_ms(unsigned int ms){
int i, j;
for (i = 0; i < ms; i++)
for (j = 0; j < 1800; j++)
;
}
int my_strcmp(const char* src,const char *dst){
int ret = 0;
while( !(ret = *(unsigned char*)src - *(unsigned char*)dst) && *dst)
{
src ++;
dst ++;
}
if( ret < 0) ret = -1;
else if(ret > 0) ret = 1;
return ret;
}
int main(){
//hal_fan_init();
hal_motor_init();
//hal_beep_init();
while (1){
}
}