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

利用单片机的TIM模块播放春日影

利用TIM模块演奏音乐

大致思路

  • 利用一个定时器输出PWM波控制蜂鸣器音调,另一个定时器模块控制播放的节奏

准备部分

设计电路

准备材料

  • 导线若干,稳压二极管,无源蜂鸣器

设计电路图

  • 将蜂鸣器按照极性接分别接在信号源和接地端
  • 同时在蜂鸣器侧反向并联一个稳压二极管,防止反向电流损坏GPIO管脚

如图所示
img

初始化硬件

配置时钟

  • 使能RCC,改为高速外部晶振
    img
  • 配置时钟树
    img

配置TIM模块

  • 利用TIM3控制节奏,使能TIM3的中断
    img
  • 为方便后续控制节奏,将TIM3的预分频改为\(16800 - 1\),向上计数
    img
  • 利用TIM4输出PWM波控制音调
  • 将预分频器调为\(84 - 1\),允许“自动重载预装载值”,向上计数
    img

搭建电路

  • 已知TIM4的1通道为PB6
    img
  • 在原理图中找到PB6的位置
    img
  • 再在开发板上找到该管脚的实际位置
    img
  • 根据先前的电路图在面包板上进行连接
    img

代码部分

思路

流程图

  • 主函数
    img
  • 中断
    img

存储乐谱

这里选用《春日影》前8小节img

  • 使用环状链表的方式存储乐谱,
  • 值域为音符的时值和音调
  • 指针域为下一节点的索引值

如图所示
img

计算数据

时值

  • 已知TIM3的预分频值为\(16800 - 1\),计数器向上计数一次需要\(\frac{1}{\frac{84 \times 10^6}{16800}} = 0.0002\)
  • 所以设全音符的重装载值为\(10000\)

音调

  • 已知TIM4的预分频值为\(84 - 1\),所以计数器频率为\(\frac{84 \times 10^6}{84} = 1 \times 10^6\)Hz
  • 根据十二平均律,将音符的音名对应的重装载值在main.h中进行宏定义
/* USER CODE BEGIN Private defines */
#define C3 7633
#define D3 6802
#define E3 6060
#define F3 5713
#define G3 5101
#define A3 4544
#define B3 4048
#define C4 3816
#define D4 3400
#define E4 3029
#define F4 2864
#define G4 2550
#define A4 2272
#define B4 2023
#define C5 1911
#define D5 1703
#define E5 1516
#define F5 1432
#define G5 1275
#define A5 1135
#define B5 1011
#define C6 850
#define E6 757
#define F6 715
#define G6 637
#define A6 567
#define B6 505
/* USER CODE END Private defines */

设计链表

  • 新建头文件music_node.h,对结构体进行定义
#ifndef MUSIC_NODE_H
#define MUSIC_NODE_H
typedef struct{int len;//存储时值的重装载值int tone;//存储音调int next_node;//存储指针域,即下一节点索引值
}music;
#endif

初始化音乐播放

  • stm32f4xx_it.c中定义如下变量
/* USER CODE BEGIN PV */
music my_music[34];//存储乐谱的环状链表
int my_index;//链表索引值
extern TIM_HandleTypeDef htim4;//外部声明TIM4的句柄
/* USER CODE END PV */
  • stm32f4xx_it.h内声明初始化音乐播放的函数
/* USER CODE BEGIN EFP */
void music_init(void);
/* USER CODE END EFP */
  • stm32f4xx_it.c中定义该函数
/* USER CODE BEGIN 1 */
void music_init(void){my_index = 0;//初始化索引值/********对节点进行初始化*******/my_music[0].len = 2500 - 1;my_music[0].tone = E5;my_music[0].next_node = 1;my_music[1].len = 1250 - 1;my_music[1].tone = D5;my_music[1].next_node = 2;my_music[2].len = 2500 - 1;my_music[2].tone = C5;my_music[2].next_node = 3;my_music[3].len = 1250 - 1;my_music[3].tone = D5;my_music[3].next_node = 4;my_music[4].len = 1875 - 1;my_music[4].tone = E5;my_music[4].next_node = 5;my_music[5].len = 625 - 1;my_music[5].tone = F5;my_music[5].next_node = 6;my_music[6].len = 1250 - 1;my_music[6].tone = E5;my_music[6].next_node = 7;my_music[7].len = 3750 - 1;my_music[7].tone = D5;my_music[7].next_node = 8;my_music[8].len = 2500 - 1;my_music[8].tone = E5;my_music[8].next_node = 9;my_music[9].len = 1250 - 1;my_music[9].tone = D5;my_music[9].next_node = 10;my_music[10].len = 2500 - 1;my_music[10].tone = E5;my_music[10].next_node = 11;my_music[11].len = 1250 - 1;my_music[11].tone = D5;my_music[11].next_node = 12;my_music[12].len = 1875 - 1;my_music[12].tone = E5;my_music[12].next_node = 13;my_music[13].len = 625 - 1;my_music[13].tone = F5;my_music[13].next_node = 14;my_music[14].len = 1250 - 1;my_music[14].tone = E5;my_music[14].next_node = 15;my_music[15].len = 3750 - 1;my_music[15].tone = D5;my_music[15].next_node = 16;my_music[16].len = 2500 - 1;my_music[16].tone = E5;my_music[16].next_node = 17;my_music[17].len = 1250 - 1;my_music[17].tone = D5;my_music[17].next_node = 18;my_music[18].len = 2500 - 1;my_music[18].tone = C5;my_music[18].next_node = 19;my_music[19].len = 1250 - 1;my_music[19].tone = D5;my_music[19].next_node = 20;my_music[20].len = 1875 - 1;my_music[20].tone = E5;my_music[20].next_node = 21;my_music[21].len = 625 - 1;my_music[21].tone = F5;my_music[21].next_node = 22;my_music[22].len = 1250 - 1;my_music[22].tone = E5;my_music[22].next_node = 23;my_music[23].len = 3750 - 1;my_music[23].tone = D5;my_music[23].next_node = 24;my_music[24].len = 2500 - 1;my_music[24].tone = E5;my_music[24].next_node = 25;my_music[25].len = 1250 - 1;my_music[25].tone = D5;my_music[25].next_node = 26;my_music[26].len = 2500 - 1;my_music[26].tone = C5;my_music[26].next_node = 27;my_music[27].len = 1250 - 1;my_music[27].tone = D5;my_music[27].next_node = 28;my_music[28].len = 1875 - 1;my_music[28].tone = E5;my_music[28].next_node = 29;my_music[29].len = 625 - 1;my_music[29].tone = F5;my_music[29].next_node = 30;my_music[30].len = 1250 - 1;my_music[30].tone = E5;my_music[30].next_node = 31;my_music[31].len = 2500 - 1;my_music[31].tone = D5;my_music[31].next_node = 32;my_music[32].len = 312;my_music[32].tone = C4;my_music[32].next_node = 33;my_music[33].len = 312;my_music[33].tone = D4;my_music[33].next_node = 0;/**************************/HAL_TIM_Base_Start_IT(&htim3);//开启TIM3的中断功能HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1);//开启TIM4的PWM输出__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, my_music[0].len / 2);//将比较值设为时值对应重装载值的一半
}
/* USER CODE END 1 */

主程序部分

  • 在主函数内调用music_init()函数,完成音乐播放的初始化
  /* USER CODE BEGIN 2 */HAL_Delay(999);//开机一秒后再播放音乐music_init();/* USER CODE END 2 */

实验效果

  • 开机一秒后循环播放《春日影》前8个小节的音乐
http://www.jsqmd.com/news/42015/

相关文章:

  • warp-cli代理
  • 完整教程:Rust语言特性深度解析:所有权、生命周期与模式匹配之我见
  • 20231427田泽航第九周预习报告
  • do文件仿真 fpga
  • 20232412 2024-2025-1 《网络与系统攻防技术》实验五实验报告
  • 本地缓存Caffeien
  • 实用指南:C++---嵌套类型(Nested Types)封装与泛型的基石
  • [ sqlite ]
  • 视野修炼-技术周刊第127期 | Valdi
  • 完整教程:机器学习:基于大数据的基金数据分析可视化系统 股票数据 金融数据 股价 Django框架 大数据技术(源码) ✅
  • 科学计算复习
  • 【AIGC】语音识别ASR:火山引擎大模型技术实践 - 详解
  • 2025年11月石笼网厂家最新推荐,聚焦资质、案例、售后的五家企业深度解读!
  • 2025 年 11 月石笼网厂家最新推荐,技术实力与市场口碑深度解析!
  • 2025年11月温州律师事务所最新推荐,实力机构深度解析与择选指南!
  • python: 用pyppeteer以无头方式抓取页面
  • python共享内存的读写同步与加锁 —— multiprocessing.Value和multiprocessing.Array、加锁
  • 2025年11月温州律师事务所最新推荐,聚焦资质、案例、服务的五家机构深度解读!
  • UI设计公司审美积累|办公类软件界面设计巧思,效率与视觉的双重升级
  • 详细介绍:AVL树手撕,超详细图文详解
  • 网络安全
  • Zhengrui 11.16 总结
  • 实用指南:spark组件-spark core(批处理)
  • windows安装mingw
  • C# 高级类型 dynamic,list,泛型(学习笔记5)
  • filebeat + logstash接入OpenStack日志
  • 构建AI智能体:六十九、Bootstrap采样在大模型评估中的应用:从置信区间到模型稳定性 - 指南
  • pip安装或查看工具包时显示WARNING: Ignoring invalid distribution -XX的解决办法
  • 11 月 13 日
  • 详细介绍:用Flux.1-Krea[dev]打造动漫风格插画的提示词灵感与创作技巧