10.2国庆作业(PWM实验)

文章目录

  • 作业内容
  • 思路分析
    • 1. 电路分析
    • 2. RCC章节分析
    • 3. GPIO章节分析
    • 4. TIM4章节分析(以蜂鸣器为例)
  • 代码实现
    • pwm.h
    • pwm.c
    • main.c

作业内容

完成PWM实验:实现蜂鸣器发出响声、马达震动和风扇转动

思路分析

1. 电路分析

10.2国庆作业(PWM实验)_第1张图片
10.2国庆作业(PWM实验)_第2张图片
蜂鸣器:TIM4_CH1---->PB6 gpio toggle gpiob6
风扇:TIM1_CH1---->PE9 gpio toggle gpioe9
马达:TIM16_CH1---->PF6 gpio toggle gpiof6

2. RCC章节分析

  1. 设置GPIOB控制器使能:RCC_MP_AHB4ENSETR[1] = 1
  2. 设置TIM4控制器使能:RCC_MP_APB1ENSETR[2] = 1

3. GPIO章节分析

  1. 设置PB6引脚为复用功能:GPIOB_MODER[13:12] = 10
  2. 设置PB6引脚复用功能为TIM4_CH1:GPIOB_AFRL[27:24] = 0010

4. TIM4章节分析(以蜂鸣器为例)

  1. TIM4_CR1[7] = 1 ------>自动重载计数器预加载使能
    TIM4_CR1[6:5] = 00 ------>设置边沿对齐模式
    TIM4_CR1[4] = 1 ------>设置递减计数器
    TIM4_CR1[0] = 1 ------>设置计数器使能
  2. TIM4_CCMR1[16][6:4] = 0110------>设置为PWM1模式
    TIM4_CCMR1[3] = 1 ------>设置预加载使能
    TIM4_CCMR1[1:0] = 00 ------>设置为输出模式
  3. TIM4_CCER[3] = 0------>设置TIM4_CH1通道为输出模式
    TIM4_CCER[1] = 0------>设置TIM4_CH1起始状态高电平
    TIM4_CCER[0] = 1------>设置TIM4_CH1输出使能
  4. TIM4_PSC------>设置预分频寄存器的值
  5. TIM4_ARR------>设置PWM方波最终周期
  6. TIM4_CCR1------>设置PWM方波的占空比

代码实现

pwm.h

#ifndef __PWM_H__
#define __PWM_H__
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_tim.h"

void buzzer_init(void);

void motor_init(void);

void fan_init(void);
#endif

pwm.c

#include "pwm.h"

void buzzer_init(void)
{
	//设置GPIOB,TIM4的时钟使能
	RCC->MP_AHB4ENSETR |= (0x1 << 1);
	RCC->MP_APB1ENSETR |= (0x1 << 2);

	//设置PB6引脚为复用功能
	GPIOB->MODER &= (~(0x3 << 12));
	GPIOB->MODER |= (0x2 << 12);
	//设置PB6引脚为TIM4_CH1功能
	GPIOB->AFRL &= (~(0xf << 24));
	GPIOB->AFRL |= (0x2 << 24);

	//设置TIM4_CH1通道的预装载寄存器的缓冲区的使能
	//TIM4_CR1[7] = 0x1
	TIM4->CR1 |= (0x1 << 7);

	//设置定时器的计数方式,边沿对齐
	//TIM4_CR1[6:5] = 0x0
	TIM4->CR1 &= (~(0x3 << 5));

	//设置定时器计数的方向,采用递减计数/递增计数 
	//TIM4_CR1[4] = 0x1 | 0x0
	TIM4->CR1 |= (0x1 << 4);

	//使能TIM4_CH1计数器 
	//TIM4_CR1[0] = 0x1
	TIM4->CR1 |= (0x1 << 0);

	//设置TIM4_CH1通道为PWM1模式  
	//TIM4_CCMR1[16]  TIM4_CCMR1[6:4]
	//pwm模式1  = 0b0110
	TIM4->CCMR1 &= (~(0x1 << 16));
	TIM4->CCMR1 &= (~(0x7 << 4));
	TIM4->CCMR1 |= (0x6 << 4);

	//设置TIM4_CH1通道使能TIMx_CCR1预加载使能寄存器
	//TIM4_CCMR1[3] = 0x1
	TIM4->CCMR1 |= (0x1 << 3);
	TIM4->CCMR1 &= (~(0x3 << 0));

	//设置TIM4_CH1通道输出PWM方波的极性,
	//TIM_CCER[3] = 0b0 TIM4_CCER[1] = 0x1 or 0x0
	TIM4->CCER &= (~(0x1 << 3));
	TIM4->CCER &= (~(0x1 << 1));

	//设置TIM4_CH1通道的输出使能位,输出PWM方波 
	//TIM4_CCER[0] = 0x1
	TIM4->CCER |= (0x1 << 0);

	//设置预分频寄存器,TIM4_PSC[15:0]  CK_PSC = 209MHz
	//提供给TIM4的时钟源的频率是209MHz
	TIM4->PSC = 209 - 1;

	//设置PWM方波的最终的周期  TIM4_ARR[16:0]
	//得到一个1000-2000Hz的方波
	TIM4->ARR = 1000;

	//设置PWM方波的占空比   TIM4_CCR1[16:0]
	TIM4->CCR1 = 700;
}

void motor_init(void)
{
	//设置GPIOF,TIM16的时钟使能
	RCC->MP_AHB4ENSETR |= (0x1 << 5);
	RCC->MP_APB2ENSETR |= (0x1 << 3);

	//设置PF6引脚为复用功能
	GPIOF->MODER &= (~(0x3 << 12));
	GPIOF->MODER |= (0x2 << 12);
	//设置PF6引脚为TIM16_CH1功能
	GPIOF->AFRL &= (~(0xf << 24));
	GPIOF->AFRL |= (0x1 << 24);

	//设置TIM16_CH1通道的预装载寄存器的缓冲区的使能
	//TIM16_CR1[7] = 0x1
	TIM16->CR1 |= (0x1 << 7);

	//设置定时器的计数方式,边沿对齐
	//TIM16_CR1[6:5] = 0x0
	//TIM16->CR1 &= (~(0x3 << 5));

	//设置定时器计数的方向,采用递减计数/递增计数 
	//TIM16_CR1[4] = 0x1 | 0x0
	//TIM16->CR1 |= (0x1 << 4);

	//使能TIM16_CH1计数器 
	//TIM16_CR1[0] = 0x1
	TIM16->CR1 |= (0x1 << 0);

	//设置TIM16_CH1通道为PWM1模式
	//TIM16_CCMR1[16]  TIM16_CCMR1[6:4]
	//pwm模式1  = 0b0110
	TIM16->CCMR1 &= (~(0x1 << 16));
	TIM16->CCMR1 &= (~(0x7 << 4));
	TIM16->CCMR1 |= (0x6 << 4);

	//设置TIM16_CH1通道使能TIMx_CCR1预加载使能寄存器
	//TIM16_CCMR1[3] = 0x1
	TIM16->CCMR1 |= (0x1 << 3);
	TIM16->CCMR1 &= (~(0x3 << 0));

	//设置TIM16_CH1通道输出PWM方波的极性,
	//TIM_CCER[3] = 0b0 TIM16_CCER[1] = 0x1 or 0x0
	//TIM16->CCER &= (~(0x1 << 3));
	TIM16->CCER &= (~(0x1 << 1));

	//设置TIM16_CH1通道的输出使能位,输出PWM方波 
	//TIM16_CCER[0] = 0x1
	TIM16->CCER |= (0x1 << 0);

	//设置预分频寄存器,TIM16_PSC[15:0]  CK_PSC = 209MHz
	//提供给TIM4的时钟源的频率是209MHz
	TIM16->PSC = 209 - 1;

	//设置PWM方波的最终的周期  TIM16_ARR[16:0]
	//得到一个1000-2000Hz的方波
	TIM16->ARR = 1000;

	//设置PWM方波的占空比   TIM16_CCR1[16:0]
	TIM16->CCR1 = 700;
	TIM16->BDTR |= (0x1 << 15);
}

void fan_init(void)
{
	//设置GPIOE,TIM1的时钟使能
	RCC->MP_AHB4ENSETR |= (0x1 << 4);
	RCC->MP_APB2ENSETR |= (0x1 << 0);

	//设置PE9引脚为复用功能
	GPIOE->MODER &= (~(0x3 << 18));
	GPIOE->MODER |= (0x2 << 18);
	//设置PE9引脚为TIM1_CH1功能
	GPIOE->AFRH &= (~(0xf << 4));
	GPIOE->AFRH |= (0x1 << 4);

	//设置TIM1_CH1通道的预装载寄存器的缓冲区的使能
	//TIM1_CR1[7] = 0x1
	TIM1->CR1 |= (0x1 << 7);

	//设置定时器的计数方式,边沿对齐
	//TIM1_CR1[6:5] = 0x0
	TIM1->CR1 &= (~(0x3 << 5));

	//设置定时器计数的方向,采用递减计数
	//TIM1_CR1[4] = 0x1
	TIM1->CR1 |= (0x1 << 4);

	//使能TIM1_CH1计数器
	//TIM1_CR1[0] = 0x1
	TIM1->CR1 |= (0x1 << 0);

	//设置TIM1_CH1通道为PWM1模式  
	//TIM1_CCMR1[16]  TIM1_CCMR1[6:4]
	//pwm模式1  = 0b0110
	TIM1->CCMR1 &= (~(0x1 << 16));
	TIM1->CCMR1 &= (~(0x7 << 4));
	TIM1->CCMR1 |= (0x6 << 4);

	//设置TIM1_CH1通道使能TIMx_CCR1预加载使能寄存器
	//TIM1_CCMR1[3] = 0x1
	TIM1->CCMR1 |= (0x1 << 3);
	TIM1->CCMR1 &= (~(0x3 << 0));

	//设置TIM1_CH1通道输出PWM方波的极性,
	//TIM1_CCER[3] = 0b0 TIM1_CCER[1] = 0x1 or 0x0
	TIM1->CCER &= (~(0x1 << 1));

	//设置TIM1_CH1通道的输出使能位,输出PWM方波 
	//TIM1_CCER[0] = 0x1
	TIM1->CCER |= (0x1 << 0);

	//设置预分频寄存器,TIM1_PSC[15:0]  CK_PSC = 209MHz
	//提供给TIM1的时钟源的频率是209MHz
	TIM1->PSC = 209 - 1;

	//设置PWM方波的最终的周期  TIM1_ARR[16:0]
	//得到一个1000-2000Hz的方波
	TIM1->ARR = 1000;

	//设置PWM方波的占空比   TIM1_CCR1[16:0]
	TIM1->CCR1 = 700;
	TIM1->BDTR |= (0x1 << 15);
}

main.c

#include "pwm.h"
extern void printf(const char *fmt, ...);

int main(void)
{
	buzzer_init();
	motor_init();
	fan_init();
	while(1);
	return 0;
}

你可能感兴趣的:(单片机,stm32,嵌入式硬件)