ARM32开发——PWM蜂鸣器案例

🎬 秋野酱:《个人主页》
🔥 个人专栏:《Java专栏》《Python专栏》

⛺️心若有所向往,何惧道阻且长

文章目录

    • 需求
    • 原来的驱动
    • 移植操作
      • 替换初始化
    • 更新Play函数
    • 完整代码

需求

在这里插入图片描述
通过控制PB9来播放音乐,PB9对应的定时器通道:Timer1 CH1

原来的驱动

#ifndef __BUZZER_H__
#define __BUZZER_H__#include "config.h"// 初始化蜂鸣器
void Buzzer_init();// 按照指定频率播放
void Buzzer_play(u16 hz_val);// 按照指定的音调播放 1,2,3,4,..7
void Buzzer_beep(u8 hz_val_index);// 停止播放
void Buzzer_stop();#endif
#include "Buzzer.h"#include "GPIO.h"
#include "PWM.h"
//			   C	 D    E 	F	 G	 A	  B	   C`
//u16 hz[] = {523, 587, 659, 698, 784, 880, 988, 1047};//            C			D			E			 F			G			A			B		  C`
u16 hz[] = { 1047, 1175, 1319,  1397, 1568, 1760, 1976, 2093 };static void GPIO_config(void) {GPIO_InitTypeDef	GPIO_InitStructure;		//结构定义GPIO_InitStructure.Pin  = GPIO_Pin_0;		//指定要初始化的IO,GPIO_InitStructure.Mode = GPIO_OUT_PP;	//指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PPGPIO_Inilize(GPIO_P0, &GPIO_InitStructure);//初始化
}void Buzzer_init(){GPIO_config();
}void Buzzer_beep(u8 hz_val_index){ // 1,2,3,4 ... 7u16 hz_val = hz[hz_val_index - 1];Buzzer_play(hz_val);
}void Buzzer_play(u16 hz_val){u16 Period = MAIN_Fosc / hz_val;PWMx_InitDefine		PWMx_InitStructure;// 总配置// (MAIN_Fosc / 1000 - 1) 周期计数值PWMx_InitStructure.PWM_Period   		= Period - 1;	//周期时间,   0~65535PWMx_InitStructure.PWM_DeadTime 		= 0;								//死区发生器设置, 0~255PWMx_InitStructure.PWM_EnoSelect		= ENO5P;	//输出通道选择,	ENO1P,ENO1N,ENO2P,ENO2N,ENO3P,ENO3N,ENO4P,ENO4N / ENO5P,ENO6P,ENO7P,ENO8PPWMx_InitStructure.PWM_PS_SW    		= PWM5_SW_P00;//切换端口// 具体PWM端口配置// pwm5PWMx_InitStructure.PWM5_Mode    		= CCMRn_PWM_MODE1;	//模式,		CCMRn_FREEZE,CCMRn_MATCH_VALID,CCMRn_MATCH_INVALID,CCMRn_ROLLOVER,CCMRn_FORCE_INVALID,CCMRn_FORCE_VALID,CCMRn_PWM_MODE1,CCMRn_PWM_MODE2PWMx_InitStructure.PWM5_Duty    		= Period / 2;			//PWM4占空比时间, 0~Period	 声音的大小、响度// pwm5PWMx_InitStructure.PWM_CC5Enable   = ENABLE;				//开启PWM6P输入捕获/比较输出,  ENABLE,DISABLE// PWM启动配置PWMx_InitStructure.PWM_MainOutEnable= ENABLE;				//主输出使能, ENABLE,DISABLEPWMx_InitStructure.PWM_CEN_Enable   = ENABLE;				//使能计数器, ENABLE,DISABLEPWM_Configuration(PWMB, &PWMx_InitStructure);				//初始化PWM,  PWMA,PWMB
}void Buzzer_stop(){PWMx_InitDefine		PWMx_InitStructure;PWMx_InitStructure.PWM_MainOutEnable= DISABLE;				//主输出使能, ENABLE,DISABLEPWMx_InitStructure.PWM_CEN_Enable   = DISABLE;				//使能计数器, ENABLE,DISABLEPWM_Configuration(PWMB, &PWMx_InitStructure);				//初始化PWM,  PWMA,PWMB
}
#include "config.h"
#include "delay.h"
#include "GPIO.h"
#include "Buzzer.h"// 两只老虎 
// 音符
u8 code notes[] = {1, 2, 3, 1,					1, 2, 3, 1,					3, 4, 5,		3, 4, 5,5, 6, 5, 4, 3, 1, 	5, 6, 5, 4, 3, 1, 	1, 5, 1,		1, 5, 1,
};// 延时时长
u8 code durations[] = {4, 4, 4, 4,					4, 4, 4, 4,					4, 4, 8,		4, 4, 8,3, 1, 3, 1, 4, 4,		3, 1, 3, 1, 4, 4,		4, 4, 8,		4, 4, 8,
};int main() {u8 i = 0;u8 len = 0;u16 delay = 0;Buzzer_init();len = sizeof(notes) / sizeof(u8);while(1) {for(i = 0; i < len; i++){Buzzer_beep(notes[i]);delay = durations[i] * 100;// 声响延时delay_X_ms(delay);// stopBuzzer_stop();delay_ms(20);}// stopBuzzer_stop();delay_ms(250);delay_ms(250);delay_ms(250);delay_ms(250);}
}

移植操作

替换初始化


void timer_gpio_config(uint32_t gpio_rcu, uint32_t gpio_port, uint32_t gpio_pin, uint32_t gpio_af){rcu_periph_clock_enable(gpio_rcu);                                             /* 设置gpio模式 */															  gpio_mode_set(gpio_port, GPIO_MODE_AF, GPIO_PUPD_NONE, gpio_pin);              gpio_output_options_set(gpio_port, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, gpio_pin);  gpio_af_set(gpio_port, gpio_af, gpio_pin);                                     
}void timer_init_config(uint32_t timer_periph, uint16_t t_prescaler, uint32_t t_period) {/*初始化参数 */timer_parameter_struct initpara;/* initialize TIMER init parameter struct */timer_struct_para_init(&initpara);/* 根据需要配置值 分频系数 (可以实现更低的timer频率) */initpara.prescaler 	= t_prescaler - 1;/* 1个周期的计数(period Max: 65535) Freq >= 2564  */initpara.period		= t_period - 1;/* initialize TIMER counter */timer_init(timer_periph, &initpara);/* enable a TIMER */timer_enable(timer_periph);
}void timer_channel_config(uint32_t timer_periph, uint16_t channel) {/* TIMER 通道输出配置 */timer_oc_parameter_struct ocpara;/* initialize TIMER channel output parameter struct */timer_channel_output_struct_para_init(&ocpara);ocpara.outputstate  = (uint16_t)TIMER_CCX_ENABLE;/* 配置输出参数 configure TIMER channel output function */timer_channel_output_config(timer_periph, channel, &ocpara);/* 配置通道输出输出比较模式 configure TIMER channel output compare mode */timer_channel_output_mode_config(timer_periph, channel, TIMER_OC_MODE_PWM0);
}#define TIMER_RCU		RCU_TIMER1
#define TIMER_PERIPH 	TIMER1
#define TIMER_CHANNEL	TIMER_CH_1
#define PRESCALER  		10void Buzzer_init() {// PB9 Timer1_CH1 AF2// GPIO ----------------------------------------timer_gpio_config(RCU_GPIOB, GPIOB, GPIO_PIN_9, GPIO_AF_1);// TIMER----------------------------------------rcu_periph_clock_enable(TIMER_RCU);timer_deinit(TIMER_PERIPH);/* 升级频率*/rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);// 通道配置 -------------------------------------timer_channel_config(TIMER_PERIPH, TIMER_CHANNEL);
}

将原有的初始化逻辑修改为新的pwm更新

更新Play函数

//            C			D			E			 F			G			A			B		  C`
u16 hz[] = { 1047, 1175, 1319,  1397, 1568, 1760, 1976, 2093 };void Buzzer_beep(u8 hz_val_index) { // 1,2,3,4 ... 7u16 hz_val = hz[hz_val_index - 1];Buzzer_play(hz_val);
}void Buzzer_play(u16 hz_val) {// 根据系统主频和分频系数,计算周期uint16_t period = SystemCoreClock / (hz_val * PRESCALER);// 设置分频系数和周期计数值timer_init_config(TIMER_PERIPH, PRESCALER, period);// 设置输出脉冲值,范围是[0, 周期计数值)timer_channel_output_pulse_value_config(TIMER_PERIPH, TIMER_CHANNEL, (uint32_t)(period * 0.5f));
}void Buzzer_stop() {timer_disable(TIMER_PERIPH);
}

● 分频问题需要解决
● 分频根据hz值来设定

完整代码

#ifndef __BSP_BUZZER_H__
#define __BSP_BUZZER_H__#include "gd32f4xx.h"#ifndef u32
#define u32 uint32_t
#endif#ifndef u16
#define u16 uint16_t
#endif#ifndef u8
#define u8 uint8_t
#endif// 初始化蜂鸣器
void Buzzer_init();// 按照指定频率播放
void Buzzer_play(u16 hz_val);// 按照指定的音调播放 1,2,3,4,..7
void Buzzer_beep(u8 hz_val_index);// 停止播放
void Buzzer_stop();#endif
#include "bsp_buzzer.h"
//			   C	 D    E 	F	 G	 A	  B	   C`
//u16 hz[] = {523, 587, 659, 698, 784, 880, 988, 1047};//            C			D			E			 F			G			A			B		  C`
u16 hz[] = { 1047, 1175, 1319,  1397, 1568, 1760, 1976, 2093 };
// >= 2564
void timer_gpio_config(uint32_t gpio_rcu, uint32_t gpio_port, uint32_t gpio_pin, uint32_t gpio_af){rcu_periph_clock_enable(gpio_rcu);                                             /* 设置gpio模式 */															  gpio_mode_set(gpio_port, GPIO_MODE_AF, GPIO_PUPD_NONE, gpio_pin);              gpio_output_options_set(gpio_port, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, gpio_pin);  gpio_af_set(gpio_port, gpio_af, gpio_pin);                                     
}void timer_init_config(uint32_t timer_periph, uint16_t t_prescaler, uint32_t t_period) {/*初始化参数 */timer_parameter_struct initpara;/* initialize TIMER init parameter struct */timer_struct_para_init(&initpara);/* 根据需要配置值 分频系数 (可以实现更低的timer频率) */initpara.prescaler 	= t_prescaler - 1;/* 1个周期的计数(period Max: 65535) Freq >= 2564  */initpara.period		= t_period - 1;/* initialize TIMER counter */timer_init(timer_periph, &initpara);/* enable a TIMER */timer_enable(timer_periph);
}void timer_channel_config(uint32_t timer_periph, uint16_t channel) {/* TIMER 通道输出配置 */timer_oc_parameter_struct ocpara;/* initialize TIMER channel output parameter struct */timer_channel_output_struct_para_init(&ocpara);ocpara.outputstate  = (uint16_t)TIMER_CCX_ENABLE;/* 配置输出参数 configure TIMER channel output function */timer_channel_output_config(timer_periph, channel, &ocpara);/* 配置通道输出输出比较模式 configure TIMER channel output compare mode */timer_channel_output_mode_config(timer_periph, channel, TIMER_OC_MODE_PWM0);
}#define TIMER_RCU		  RCU_TIMER1
#define TIMER_PERIPH 	TIMER1
#define TIMER_CHANNEL	TIMER_CH_1
#define PRESCALER  		10void Buzzer_init() {// PB9 Timer1_CH1 AF2// GPIO ----------------------------------------timer_gpio_config(RCU_GPIOB, GPIOB, GPIO_PIN_9, GPIO_AF_1);// TIMER----------------------------------------rcu_periph_clock_enable(TIMER_RCU);timer_deinit(TIMER_PERIPH);/* 升级频率*/rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);// 通道配置 -------------------------------------timer_channel_config(TIMER_PERIPH, TIMER_CHANNEL);
}void Buzzer_beep(u8 hz_val_index) { // 1,2,3,4 ... 7u16 hz_val = hz[hz_val_index - 1];Buzzer_play(hz_val);
}void Buzzer_play(u16 hz_val) {// 根据系统主频和分频系数,计算周期uint16_t period = SystemCoreClock / (hz_val * PRESCALER);// 设置分频系数和周期计数值timer_init_config(TIMER_PERIPH, PRESCALER, period);// 设置输出脉冲值,范围是[0, 周期计数值)timer_channel_output_pulse_value_config(TIMER_PERIPH, TIMER_CHANNEL, (uint32_t)(period * 0.5f));
}void Buzzer_stop() {timer_disable(TIMER_PERIPH);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3269315.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Web3 职场新手指南:从技能到素养,求职者如何脱颖而出?

随着 2024 年步入下半年&#xff0c;Web3 行业正在经历一系列技术革新。通过改进的跨链交互机制和兼容性&#xff0c;逐步消除市场碎片化的问题。技术的进步为开发者和用户都打开了新的前景。然而&#xff0c;复杂的技术和快速变化的市场环境也让许多新人望而却步。求职者如何找…

【数据结构】双向带头循环链表(c语言)(附源码)

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;数据结构 目录 前言 1.双向带头循环链表的概念和结构定义 2.双向带头循环链表的实现 2.1 方法声明 2.2 方法实现 2.2.1 创建新节点 2.2.2 初始化 2.2.3 …

【基于yolo转onnx 量化测试】

1、 训练模型转onnx 和量化 from ultralytics import YOLOmodel_path "yolov10/runs/train8/weights/best.pt" model YOLO(model_path) # 载入官方模型 # 导出模型 model.export(formatonnx,halfTrue)2、量化&#xff0c;减少了三分之一的存储空间从100M到30M …

当镜像地址出错的时候下载selenium的处理办法

当镜像地址出错的时候下载selenium的处理办法 一、原因 显示出错&#xff1a; C:\Users\xiaodaidai>pip install selenium3.4.0 Looking in indexes: Simple Index WARNING: Retrying (Retry(total4, connectNone, readNone, redirectNone, statusNone)) after connection …

学语言,看这里,如何快速掌握JavaScript?

本篇文章是基于会点c语言和会点python基础的&#xff0c;去更容易上手javascript 学习笔记分享✨&#x1f308;&#x1f44f;&#x1f44f;&#x1f451;&#x1f451; javascript目录 1.安装node.js&#xff1a;2.配置环境变量——创建NODE_HOME :3.变量与常量4.原生数据类型5…

C++ —— STL简介

1. 什么是STL STL(standard template libaray-标准模板库)&#xff1a;是C标准库的重要组成部分&#xff0c;不仅是一个可复用的 组件库&#xff0c;而且是一个包罗数据结构与算法的软件框架 2.STL的版本 原始版本 Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本…

Java之父官宣退休

今年不用说大家都知道环境真的很差很差&#xff0c;裁员降薪已经是家常便饭&#xff0c;在这种严峻环境下&#xff0c;我们只能提升自己内功来抗风险&#xff0c;下面分享一本java之父推荐的优秀书籍。 刚过完自己 69 岁生日的两个月后&#xff0c;Java 之父 James Gosling&…

论文阅读:Deep_Generic_Dynamic_Object_Detection_Based_on_Dynamic_Grid_Maps

目录 概要 Motivation 整体框架流程 技术细节 小结 不足 论文地址&#xff1a;Deep Generic Dynamic Object Detection Based on Dynamic Grid Maps | IEEE Conference Publication | IEEE Xplore 概要 该文章提出了一种基于动态网格图&#xff08;Dynamic Grid Maps&a…

Golang高效合并(拼接)多个gzip压缩文件

有时我们可能会遇到需要把多个 gzip 文件合并成单个 gzip 文件的场景&#xff0c;最简单最容易的方式是把每个gzip文件都先解压&#xff0c;然后合并成一个文件后再次进行压缩&#xff0c;最终得到我们想要的结果&#xff0c;但这种先解压后压缩的方式显然效率不高&#xff0c;…

监控Windows文件夹下面的文件(C#和C++实现)

最近在做虚拟打印机时&#xff0c;需要实时监控打印文件的到达&#xff0c;并移动文件到另外的位置。一开始我使用了线程&#xff0c;在线程里去检测新文件的到达。实际上Windows提供了一个文件监控接口函数ReadDIrectoryChangesW。这个函数可以对所有文件操作进行监控。 ReadD…

1 深度学习网络DNN

代码来自B站up爆肝杰哥 测试版本 import torch import torchvisiondef print_hi(name):print(fHi, {name}) if __name__ __main__:print_hi(陀思妥耶夫斯基)print("HELLO pytorch {}".format(torch.__version__))print("torchvision.version:", torchvi…

2024后端开发面试题总结

一、前言 上一篇离职贴发布之后仿佛登上了热门&#xff0c;就连曾经阿里的师兄都看到了我的分享&#xff0c;这波流量真是受宠若惊&#xff01; 回到正题&#xff0c;文章火之后&#xff0c;一些同学急切想要让我分享一下面试内容&#xff0c;回忆了几个晚上顺便总结一下&#…

mybatis查询数据字段返回空值

1.描述 数据苦衷实际存储字段全不为空 查询后brand_name/company_name为空 2.原因分析 带下划线的字段&#xff0c;都会返回空值&#xff0c;应该是字段映射出了问题 3.解决方案 在配置文件中添加下划线自动映射为驼峰 <configuration><settings><sett…

【计算机网络】OSPF单区域实验

一&#xff1a;实验目的 1&#xff1a;掌握在路由器上配置OSPF单区域。 2&#xff1a;学习OSPF协议的原理&#xff0c;及其网络拓扑结构改变后的变化。 二&#xff1a;实验仪器设备及软件 硬件&#xff1a;RCMS交换机、网线、内网网卡接口、Windows 2019操作系统的计算机等。…

STM32+ESP8266-连接阿里云-物联网通用Android app(2)

前言 接着上一篇的文章创建好了设备&#xff0c;云产品转发&#xff0c;让STM32连接上阿里云&#xff0c;发布和订阅了相关主题。本篇文章来编写一个Android app来进行控制STM32和接收传感器数据显示在屏幕上。基于Android studio。 演示视频 实现一个简单的app来控制stm32开…

Django-3.3创建模型

创建模型&#xff08;models&#xff09;的时候&#xff0c; 1&#xff1a;我们需要这个模型是哪个文件下面的模型&#xff08;models&#xff09;&#xff0c;我们需要在配置文件中吧应用安装上&#xff08;安装应用&#xff1a;INSTALLED_APPS&#xff09; 2&#xff1a;找对…

【机器学习】不同操作系统下如何安装Jupyter Notebook和Anaconda

引言 Jupyter Notebook 是一个非常流行的开源Web应用程序&#xff0c;允许你创建和共享包含代码、方程、可视化和解释性文本的文档 文章目录 引言一、如何安装Jupyter Notebook1.1 对于Windows用户1.2 对于macOS用户1.3 对于Linux用户&#xff1a; 二、如何安装Anaconda2.1 对于…

《python程序语言设计》第6章13题 数列求和编写一个函数计算

正确代码 def sumNumber(integer_num):print(" i || m(i)")print("-"*30)a 0for i in range(1, integer_num 1):a i / (i 1)print("{:4d} || {:.4f}".format(i, a))sumNumber(20)结果如下

使用 leanback 库 GridView 管理AnroidTV的焦点

一、前情提要 我当前需要开发一个TV应用&#xff0c;但是之前处理过的焦点问题的很少&#xff0c;现在空下来了&#xff0c;对过往的工作做一个总结分享。在手机APP开发中常用的 RecycleView 在 TV 中开发时&#xff0c;无法解决大量的焦点问题&#xff0c;所以使用leanback进…

ElasticSearch核心之DSL查询语句实战

什么是DSL&#xff1f; Elasticsearch提供丰富且灵活的查询语言叫做DSL查询(Query DSL),它允许你构建更加复杂、强大的查询。 DSL(Domain Specific Language特定领域语言)以JSON请求体的形式出现。目前常用的框架查询方法什么的底层都是构建DSL语句实现的&#xff0c;所以你必…