本实验采用STM32MP157A
头文件:
#ifndef __PWM_H__
#define __PWM_H__
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_tim.h"
#include "stm32mp1xx_rcc.h"
//仨头文件里是别人封装好的地址结构体和宏定义
//初始化
void pwm_init();
//风扇
void fen_init();
//马达
void mada_init();
#endif
功能函数
原理上大同小异,本文以风扇为例。(PF9引脚)
一:?首先是RCC寄存器使能GPIOE和TIM1
查芯片手册可知,GPIOF为AHB4总线,TIM1为APB2总线
//RCC PE9使能(GPIOE)
RCC->MP_AHB4ENSETR |= (0x1 << 4);
//TIM1使能 [0] = 1
RCC->MP_APB2ENSETR |= (0x1 << 0);
二. GPIO初始化
设置引脚复用模式
查手册知,输出模式为AFRH[7:4]? ?=? ?0x1000
/*********GPIO章节初始化**************/
//设置引脚复用模式 GPIOE[19:18] = 0x01
GPIOE->MODER &= (~(0x3 << 18));
GPIOE->MODER |= (0x2 << 18);
//设置为AF1:0001 ,AFRH[7:4]
GPIOE->AFRH &= (~(0xf << 4));
GPIOE->AFRH |= (0x1 << 4);
三?TIM1设置
?根据系统处理图,
1. 先设置分频器 系统提供时钟源 209MHz 209
TIM1->PSC &= ~(0xffff);
TIM1->PSC |= 0xd0; //208
2.设置PWM方波最终周期1000Hz 对自动重载计数器进行赋值 1000
TIM1->ARR &= ~(0xffff);
TIM1->ARR |= (0x3E8); //1000
3.设置PWM方波占空比 对比较/捕获寄存器进行赋值 700
TIM1->CCR1 &= (~(0xffff));
TIM1->CCR1 |= (0x2bc);
4.设置TIM1_CH1通道为PWM1模式
设置pwm1模式TIM4_CCMR1的16、[6:4] = 0110
TIM1->CCMR1 &= (~(0x1 << 16)); //16位置0
TIM1->CCMR1 &= (~(0x7 << 4)); //6~4位清零
TIM1->CCMR1 |= (0x6 << 4); //置为110
5.设置TIM1_CH1通道预加载使能
TIM1->CCMR1 |= (0x1 << 3);
6.设置TIM1_CH1通道为输出模式
TIM1->CCMR1 &= (~(0x3 << 0));
7.设置TIM1_CH1通道输出模式极性高电平
TIM1->CCER &= (~(0x1 << 1));
8.设置TIM1_CH1通道比较捕获寄存器输出使能
TIM1->CCER |= (0x1 << 0);
?9~12步
//9.设置TIM1_CH1通道自动重载计数器预加载使能
TIM1->CR1 |= (0x1 << 7);
//10.设置TIM1_CH1通道采用边沿对其方式
TIM1->CR1 &= (~(0x3) << 5);
//11.设置TIM1_CH1通道采用递减计数方式
TIM1->CR1 |= (0x1 << 4);
//12.设置TIM1_CH1通道计数器使能
TIM1->CR1 |= (0x1 << 0);
*13.TIM1_BDTR,注意,此为风扇和马达特有的寄存器,蜂鸣器没有
TIM1->BDTR |= (0x1 << 15);
另外俩元件,TIMx寄存器设置方式相同,只是TIMx寄存器编号不同。而RCC寄存器使能和GPIO寄存器设置,则因为三个元件的引脚所在总线和引脚号的区别,导致都完全不同,要查表写。
以下附上完整代码,注意,因为不同芯片的引脚、总线可能不尽相同,此代码仅供参考,切勿照抄
#include "pwm.h"
void pwm_init()
{
/***********RCC初始化**************/
//使能GPIOB
RCC->MP_AHB4ENSETR = (0x1 << 1);
RCC->MP_APB1ENSETR = (0x1 << 2);
/*****GPIO章节初始化*****/
GPIOB->AFRL &= (~(0xf << 24));
GPIOB->AFRL |= (0x2 << 24);
//设置PB6引脚为输出模式
//GPIOB_MODER[13:12] = 0b01
GPIOB->MODER &= (~(0x3 << 12));
GPIOB->MODER |= (0x2 << 12);
/***********TMI4寄存器**************/
//TIM4_PSC寄存器
TIM4->PSC &= ~(0xffff);
TIM4->PSC |= 0xd0; //208
//TIM4_ARR寄存器 自动重载寄存器
TIM4->ARR &= ~(0xffff);
TIM4->ARR |= (0x3E8); //1000
//TIM4_CCMR1寄存器
//设置pwm1模式TIM4_CCMR1 16 [6:4] = 0110
TIM4->CCMR1 &= (~(0x1 << 16)); //16位置0
TIM4->CCMR1 &= (~(0x7 << 4)); //6~4位清零
TIM4->CCMR1 |= (0x6 << 4); //置为110
//设置预加载使能TIM4_CCMR1[3] = 1
TIM4->CCMR1 |= (0x1 << 3);
//设置为输出模式 TIM4_CCMR1[1:0] = 00
TIM4->CCMR1 &= (~(0x3 << 0));
//TIM4_CCER寄存器
//设置为输出模式
// TIM4->CCER |= (0x1 << 3);
//设置起始位高电平
TIM4->CCER &= (~(0x1 << 1));
//配置输出使能
TIM4->CCER |= (0x1 << 0);
//TIME4_CCR1
TIM4->CCR1 &= (~(0xffff));
TIM4->CCR1 |= (0x12c);
//TIM4_CR1寄存器
//自动承载计数器预加载使能
TIM4->CR1 |= (0x1 << 7);
//设置边沿对齐模式
TIM4->CR1 &= (~(0x3) << 5);
//设置递减计数器
TIM4->CR1 |= (0x1 << 4);
//设置计数器使能
TIM4->CR1 |= (0x1 << 0);
}
void fen_init()
{
//RCC PE9使能(GPIOE)
RCC->MP_AHB4ENSETR |= (0x1 << 4);
//TIM1使能 [0] = 1
RCC->MP_APB2ENSETR |= (0x1 << 0);
/*********GPIO章节初始化**************/
//设置引脚复用模式 GPIOE[19:18] = 01
GPIOE->MODER &= (~(0x3 << 18));
GPIOE->MODER |= (0x2 << 18);
//设置为AF1:0001 ,AFRH[7:4]
GPIOE->AFRH &= (~(0xf << 4));
GPIOE->AFRH |= (0x1 << 4);
/***********TMI1寄存器***************/
//1.设置分频器 系统提供时钟源 209MHz 209
TIM1->PSC &= ~(0xffff);
TIM1->PSC |= 0xd0; //208
//2.设置PWM方波最终周期1000Hz 对自动重载计数器进行赋值 1000
TIM1->ARR &= ~(0xffff);
TIM1->ARR |= (0x3E8); //1000
//3.设置PWM方波占空比 对比较/捕获寄存器进行赋值 700
TIM1->CCR1 &= (~(0xffff));
TIM1->CCR1 |= (0x2bc);
//4.设置TIM1_CH1通道为PWM1模式
//设置pwm1模式TIM4_CCMR1 16 [6:4] = 0110
TIM1->CCMR1 &= (~(0x1 << 16)); //16位置0
TIM1->CCMR1 &= (~(0x7 << 4)); //6~4位清零
TIM1->CCMR1 |= (0x6 << 4); //置为110
//5.设置TIM1_CH1通道预加载使能
TIM1->CCMR1 |= (0x1 << 3);
//6.设置TIM1_CH1通道为输出模式
TIM1->CCMR1 &= (~(0x3 << 0));
//7.设置TIM1_CH1通道输出模式极性高电平
TIM1->CCER &= (~(0x1 << 1));
//8.设置TIM1_CH1通道比较捕获寄存器输出使能
TIM1->CCER |= (0x1 << 0);
//9.设置TIM1_CH1通道自动重载计数器预加载使能
TIM1->CR1 |= (0x1 << 7);
//10.设置TIM1_CH1通道采用边沿对其方式
TIM1->CR1 &= (~(0x3) << 5);
//11.设置TIM1_CH1通道采用递减计数方式
TIM1->CR1 |= (0x1 << 4);
//12.设置TIM1_CH1通道计数器使能
TIM1->CR1 |= (0x1 << 0);
//13.TIM1_BDTR
TIM1->BDTR |= (0x1 << 15);
}
void mada_init()
{
//RCC PF6使能(GPIOE)
RCC->MP_AHB4ENSETR |= (0x1 << 5);
//TIM16使能 [0] = 1
RCC->MP_APB2ENSETR |= (0x1 << 3);
/*********GPIO章节初始化**************/
//设置引脚复用模式 GPIOE[13:12] = 01
GPIOF->MODER &= (~(0x3 << 12));
GPIOF->MODER |= (0x2 << 12);
//设置为AF1:0001 ,AFRH[27:24]
GPIOF->AFRL &= (~(0xf << 24));
GPIOF->AFRL |= (0x1 << 24);
/***********TMI1寄存器***************/
//1.设置分频器 系统提供时钟源 209MHz 209
TIM16->PSC &= ~(0xffff);
TIM16->PSC |= 0xd0; //208
//2.设置PWM方波最终周期1000Hz 对自动重载计数器进行赋值 1000
TIM16->ARR &= ~(0xffff);
TIM16->ARR |= (0x3E8); //1000
//3.设置PWM方波占空比 对比较/捕获寄存器进行赋值 300
TIM16->CCR1 &= (~(0xffff));
TIM16->CCR1 |= (0x2bc);
//4.设置TIM1_CH1通道为PWM1模式
//设置pwm1模式TIM4_CCMR1 16 [6:4] = 0110
TIM16->CCMR1 &= (~(0x1 << 16)); //16位置0
TIM16->CCMR1 &= (~(0x7 << 4)); //6~4位清零
TIM16->CCMR1 |= (0x6 << 4); //置为110
//5.设置TIM1_CH1通道预加载使能
TIM16->CCMR1 |= (0x1 << 3);
//6.设置TIM1_CH1通道为输出模式
TIM16->CCMR1 &= (~(0x3 << 0));
//7.设置TIM1_CH1通道输出模式极性高电平
TIM16->CCER &= (~(0x1 << 1));
//8.设置TIM1_CH1通道比较捕获寄存器输出使能
TIM16->CCER |= (0x1 << 0);
//9.设置TIM1_CH1通道自动重载计数器预加载使能
TIM16->CR1 |= (0x1 << 7);
//10.设置TIM1_CH1通道采用边沿对其方式
TIM16->CR1 &= (~(0x3) << 5);
//11.设置TIM1_CH1通道采用递减计数方式
TIM16->CR1 |= (0x1 << 4);
//12.设置TIM1_CH1通道计数器使能
TIM16->CR1 |= (0x1 << 0);
//13.TIM1_BDTR
TIM16->BDTR |= (0x1 << 15);
}
|