当前位置: 首页 > news >正文

10.2国庆作业(PWM实验)

文章目录

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

作业内容

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

思路分析

1. 电路分析

在这里插入图片描述
在这里插入图片描述
蜂鸣器: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;
}

相关文章:

  • Java开发环境基础配置
  • 基于springboot和ftp实现的网盘文件系统
  • Maven创建聚合项目
  • ASP.NET MVC--视图
  • java基础巩固-宇宙第一AiYWM:为了维持生计,虽然咱没机会经历双11这种技术阅兵场,但是看看人家写的阅兵场日记,先xiao习xiao习一下嘛~整起
  • Mybatis配置详解 | 深入理解 『带上CSDN一起玩转国庆』
  • 断断续续学习算法的5年
  • Qt 精确定时器
  • mysql中int(11)与int(1)的区别与联系
  • 【Vue】Vue的v-for指令
  • 【Hadoop---09】MapReduce:MapReduce概述
  • 黑马旅游网-配置项目(一)
  • 【C语言】continue 关键字
  • java基于springboot+Vue+nodejs的高校网上二手闲置跳蚤市场 element
  • JAVA计算机毕业设计超市进销存管理系统Mybatis+系统+数据库+调试部署
  • php的引用
  • 2017届校招提前批面试回顾
  • 30天自制操作系统-2
  • Brief introduction of how to 'Call, Apply and Bind'
  • chrome扩展demo1-小时钟
  • Gradle 5.0 正式版发布
  • HTTP中的ETag在移动客户端的应用
  • js面向对象
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • Python利用正则抓取网页内容保存到本地
  • SOFAMosn配置模型
  • 半理解系列--Promise的进化史
  • 初识 beanstalkd
  • 搭建gitbook 和 访问权限认证
  • 记一次和乔布斯合作最难忘的经历
  • 利用阿里云 OSS 搭建私有 Docker 仓库
  • 区块链技术特点之去中心化特性
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 使用Gradle第一次构建Java程序
  • 通信类
  • 正则表达式小结
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • ​ssh-keyscan命令--Linux命令应用大词典729个命令解读
  • ​人工智能书单(数学基础篇)
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • (16)Reactor的测试——响应式Spring的道法术器
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (iPhone/iPad开发)在UIWebView中自定义菜单栏
  • (NSDate) 时间 (time )比较
  • (Python) SOAP Web Service (HTTP POST)
  • (分布式缓存)Redis分片集群
  • (转) Face-Resources
  • .naturalWidth 和naturalHeight属性,
  • .NET Core WebAPI中使用swagger版本控制,添加注释
  • .Net Core和.Net Standard直观理解
  • .NET DevOps 接入指南 | 1. GitLab 安装