赞
踩
本设计以STM32MP157A单片机为核心控制器,加上其他的模块一起组成基于单片机的音乐盒的整个系统,通过不同频率的PWM使蜂鸣器播放音乐,通过按键中断实现歌曲切换,音量调节,定时器中断实现播放速度调节,LED灯也会随着音乐而闪烁。
硬件:STM32MP157A
软件:STM32CUBEIDE
音乐盒的功能:
1、能稳定的播放出音乐,满足使用者对音乐盒的需求。
2、具有开始和暂停的功能,按下暂停键音乐会停止播放,再按下开始,音乐会接着播放。
3、可以通过按下切换键播放下一首歌曲。
4、可以通过按下变速键,实现歌曲由1倍数-1.2倍数-1.5倍数-2倍数-0.8倍数-0.6倍数-1倍数的切换。
5、可以通过按下音量键使音量逐渐变大,到达阈值之后音量变为0实现静音,再按又会逐渐增大。
6、led会随着歌曲的音调而变化。
通常情况可以采用HAL_Delay()来实现一个音的持续时间,我们将其换成定时器,便于控制。再就是PWM控制蜂鸣器,我们需要设置对应的高中低音。
定时器:使用TIM2配置出一个0.1s的中断,我们将一个半拍按0.5秒算,这样我们只需要改变 对tim2中断的计数来改变播放速度。
PWM蜂鸣器:我们先了解一个公式 || ( (PSC+1)/CLK ) * ( ARR+1 ) = 1 / f || f(频率)
clk:系统时钟(64MHZ)(STM32MP157A)我们在程序中会更改ARR来改变频率,所以我们需要事先确定一个合适的PSC。 频率:一秒执行多少次。
我们取 1/f 中 取中音1频率 1/523.3 = 0.00191094974202178482705904834703
很长一串小数,可能还没算完,那我们可以取小数点后五位数据。我们以 0.00001为基础也就是让
(PSC+1)/CLK ) = 0.00001 已知clk = 64*10^6 得出PSC + 1 = 640
那么ARR是用于干什么的呢。1/523.3 就约等于 0.00001 *( ARR+1 ) 那么 ARR+1就等于191。
总结一下:我们通过计算得出一个基数,PSC配置为 640 - 1 ,明显ARR在最初时没有实际效果,因为音频不同相应的ARR也不同(这里简易 ARR = 999,不建议设置太大)
音乐盒 架构图
因为有许多中断,所以将在stm32mp1xx_it.c 和 main.c 之间交换信息。
stm32mp1xx_it.c 基础变量
- int time_100ms_cnt = 0; //0.1s计数器
- int Beat_speed = 5; //节拍速度,代表半个节拍需要多少个0.1s
- int Beat_speed_n = 0; //实际执行的节拍数
-
- int Beat_num = 2; //这个一个音需要多少个 半拍
- int flag = 0; //当其等于 1 时,表示一个音结束
- int EN = 0; //使能信号,用于开启整个音乐盒
- int list = 0; //音乐列表
- int list_max = 0; //音乐总数
- int Low_volume = 5; //音量大小
- #define Low_volume_cnt 3 //音量大小增加数
main.c基础变量
- extern int time_100ms_cnt ; //0.1s计数器
- extern int Beat_speed ; //节拍速度,代表半个节拍需要多少个0.1s
- extern int Beat_speed_n ; //实际执行的节拍数
-
- extern int Beat_num ; //这个一个音需要多少个 半拍
- extern int flag ; //当其等于 1 时,表示一个音结束
- extern int EN ; //使能信号,用于开启整个音乐盒
- extern int list ; //音乐列表
- extern int list_max ; //音乐总数
- extern int Low_volume ; //音量大小
-
-
- //将LED设置成全灭
- void LED_RESET(){
- HAL_GPIO_WritePin(GPIOF, GPIO_PIN_1, GPIO_PIN_RESET);
- HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET);
- HAL_GPIO_WritePin(GPIOI, GPIO_PIN_11|GPIO_PIN_10, GPIO_PIN_RESET);
- }
-
- void LED(int i){
- if(i >= 1) HAL_GPIO_WritePin(GPIOF, GPIO_PIN_1, GPIO_PIN_SET);
- if(i >= 2) HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET);
- if(i >= 3) HAL_GPIO_WritePin(GPIOI, GPIO_PIN_11,GPIO_PIN_SET);
- if(i >= 4) HAL_GPIO_WritePin(GPIOI, GPIO_PIN_10, GPIO_PIN_SET);
- }
- //随音节输入,改变LED状�??
- void LED_BEEP(int i){
- LED_RESET();
- switch(i){
- case 1:{
- LED(1);
- break;
- }
- case 2:{
- LED(1);
- break;
- }
-
- case 3:{
- LED(2);
- break;
- }
- case 4:{
- LED(2);
- break;
- }
-
- case 5:{
- LED(3);
- break;
- }
- case 6:{
- LED(3);
- break;
- }
-
- case 7:{
- LED(4);
- break;
- }
- default:{
- LED_RESET();
- break;
- }
- }
- }

-
- int tone[3][8];
- //初始化高中低音频率
- void tone_init(){
- tone[1][0] = 0; //不执行音乐
- tone[1][1] = 191;
- tone[1][2] = 170;
- tone[1][3] = 151;
- tone[1][4] = 143;
- tone[1][5] = 127;
- tone[1][6] = 113;
- tone[1][7] = 101;
- // 低音 (Low)
- for (int i = 0; i < 8; i++) {
- tone[0][i] = tone[1][i] * 2; // 只是低音 近似的值
- }
-
- // 高音 (High)
- for (int i = 0; i < 8; i++) {
- tone[2][i] = tone[1][i] / 2; // 只是高音 近似的值
- }
- }

- #define MAX_unit_num 200 //�??大乐谱数�??
- //创建结构体保存乐�??
- struct music_unit{
- char name[50]; //乐谱名称
- int unit[MAX_unit_num]; //发什么音
- int unit_HL[MAX_unit_num]; //发高音或者其�??
- int time[MAX_unit_num]; //发音时间
- //int time_4[MAX_unit_num]; //判断是否�??1/4�??
- int num; //记录有多少个
- }music[25];
-
- //创建乐谱 返回有多少首音乐
- int music_init(){
- int cnt = 0;
- //第一首音�?? 生日快乐
- strcpy(music[0].name, "生日快乐"); // 使用strcpy复制字符�?? 给音乐命�??
- int music0_unit[29] = {0,0, 5,5,6,5,1,7, 5,5,6,5,2,1,
- 5,5,6,3,1,7, 6,4,4,3,1,2,1,
- 0,0}; //基础乐谱
- int music0_time[29] = {1,1, 1,1,2,2,2,3, 1,1,2,2,2,3,
- 2,2,2,2,2,2, 2,2,2,2,2,2,3,
- 1,1}; //乐谱节拍
- music[0].num = 29; //乐谱总数
- int music0_unit_HL[29] = {1,1,
- 0,0,0,0,1,0, 0,0,0,0,1,1,
- 0,0,1,1,1,0, 0,1,1,1,1,1,1,
- 1,1}; //乐谱全为中音
-
- //第二首音�?? �??闪一闪亮晶晶
- cnt++;
- strcpy(music[1].name, "�??闪一闪亮晶晶"); // 使用strcpy复制字符�?? 给音乐命�??
- int music1_unit[44] = {0,
- 1,1,5,5,6,6,5, 4,4,3,3,2,2,1,
- 5,5,4,4,3,3,2, 5,5,4,4,3,3,2,
- 1,1,5,5,6,6,5, 4,4,3,3,2,2,1,
- 0}; //基础乐谱
- int music1_time[44] = {2,
- 2,2,2,2,2,2,3, 2,2,2,2,2,2,3,
- 2,2,2,2,2,2,3, 2,2,2,2,2,2,3,
- 2,2,2,2,2,2,3, 2,2,2,2,2,2,3,
- 2}; //乐谱节拍
- int music1_unit_HL[44] =
- {1,
- 1,1,1,1,1,1,1, 1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1, 1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1, 1,1,1,1,1,1,1,
- 1}; //乐谱全为中音
- music[1].num = 44; //乐谱总数
-
-
-
- //第三首音�?? 两只老虎
- cnt++;
- strcpy(music[2].name, "两只老虎"); // 使用strcpy复制字符�?? 给音乐命�??
- int music2_unit[38] = {0,
- 1,2,3,1, 1,2,3,1, 3,4,5,5, 3,4,5,5,
- 5,6,5,4, 3,1,5,6, 5,4,3,1, 1,5,1,1,
- 1,5,1,1, 0}; //基础乐谱
- int music2_time[38] = {2,
- 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
- 0,0,0,0, 1,1,0,0, 0,0,1,1, 1,1,1,2,
- 1,1,1,2, 2}; //乐谱节拍
- int music2_unit_HL[38] =
- {1,
- 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
- 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,1,1,
- 1,0,1,1, 1}; //乐谱�?? 中音
- music[2].num = 38; //乐谱总数
-
-
- //第四首音�?? 青花瓷片�??
- cnt++;
- strcpy(music[3].name, "青花瓷片选"); // 使用strcpy复制字符�?? 给音乐命�??
- int music3_unit[100] = {0,0,0,0, 0,5,5,3, 2,3,6,2, 3,5,3,2, 2,5,5,3,
- 2,3,5,2, 3,5,2,1, 1,1,2,3, 5,6,5,4, 5,3,3,2,
- 2,2,1,2, 1,1,2,1, 2,3,5,3, 3,3,5,5, 3,2,3,6,
- 2,3,5,3, 2,2,5,5, 3,2,3,5, 2,3,5,2, 1,1,1,2,
- 3,5,6,5, 4,5,3,3, 2,2,5,3, 2,2,2,1, 1,0,0,0}; //基础乐谱
-
- int music3_time[100] = {0,0,0,0, 0,0,0,0, 0,0,1,0, 0,0,0,2, 0,0,0,0,
- 0,0,1,0, 0,0,0,2, 0,0,0,0, 0,0,0,0, 0,0,0,0,
- 2,0,0,0, 0,0,0,0, 0,1,0,0, 2,0,0,0, 0,0,0,1,
- 0,0,0,0, 2,0,0,0, 0,0,0,1, 0,0,0,0, 2,0,0,0,
- 0,0,0,0, 0,0,0,0, 0,2,0,1, 0,0,0,1, 2,1,1,1}; //乐谱节拍
-
- for(int i =0;i<100;i++)
- music3_time[i] = music3_time[i]+1;
-
- int music3_unit_HL[100] =
- { 1,1,1,1, 1,1,1,1, 1,1,0,1, 1,1,1,1, 1,1,1,1,
- 1,1,0,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
- 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,0,
- 1,1,1,1, 1,1,1,1, 1,1,1,0, 1,1,1,1, 1,1,1,1,
- 1,1,1,1, 1,1,1,1, 1,1,0,1, 1,1,1,1, 1,1,1,1}; //乐谱�?? 中音
- music[3].num = 100; //乐谱总数
-
-
-
-
- for (int i = 0; i < MAX_unit_num; i++) {
- //将乐谱保存进结构�??
- if(i<music[0].num){//确保数据正确
- music[0].unit[i] =music0_unit[i];
- music[0].unit_HL[i] =music0_unit_HL[i];
- music[0].time[i] =music0_time[i];
- }
-
-
- //将乐谱保存进结构�??
- if(i<music[1].num){//确保数据正确
- music[1].unit[i] =music1_unit[i];
- music[1].unit_HL[i] =music1_unit_HL[i];
- music[1].time[i] =music1_time[i];
- }
-
- //将乐谱保存进结构�??
- if(i<music[2].num){//确保数据正确
- music[2].unit[i] =music2_unit[i];
- music[2].unit_HL[i] =music2_unit_HL[i];
- music[2].time[i] =music2_time[i];
- }
-
-
- //将乐谱保存进结构�??
- if(i<music[3].num){//确保数据正确
- music[3].unit[i] =music3_unit[i];
- music[3].unit_HL[i] =music3_unit_HL[i];
- music[3].time[i] =music3_time[i];
- }
- }
-
-
- return cnt;
- }

-
-
- //播放音乐 N首音乐 音量 X 0 - 10
- void play_music(int n, int x){
- static int ni = 0; //用于判断 是否换了音乐
- static int cnt = 0; //记录播放到哪一个 音节
- if(ni != n ){//如果音乐换了
- ni = n;
- cnt = 0;
- __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,0);//设置音量
- HAL_Delay(1000);//
- }
-
- //
- int value = tone[music[n].unit_HL[cnt]][music[n].unit[cnt]]; //获取频率
- if(flag == 1){ //接受到一个音节结束
- flag = 0; //复位
- Beat_num = music[n].time[cnt]; //这个音需要多少个半拍
- LED_BEEP(music[n].unit[cnt]); //LED随音节变动
-
- if(music[n].time[cnt] == 0){// 后面添加的 1/4 拍
- Beat_speed_n = Beat_speed /2;
- }
- else{//如果没有1/4拍
- Beat_speed_n = Beat_speed;
- }
-
- __HAL_TIM_SET_AUTORELOAD(&htim4,value); //自动加载频率
-
- cnt ++; //可进行下一次音节
- if(cnt >= music[n].num){ //如果一首音乐播放完毕
- cnt = 0;//重新播放
- //__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,0);//设置音量
- //HAL_Delay(500);//
- }
- }
- //__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,x * (value/100));//设置音量
- __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,(value/10)*x);//设置音量
- }

-
- void EXTI0_IRQHandler(void)
- {
- /* USER CODE BEGIN EXTI0_IRQn 0 */
- if(HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_0) == 0)//确保数据稳定
- {
- //每次按下解决 音量�?? Low_volume_cnt
- Low_volume = Low_volume + Low_volume_cnt;
- if(Low_volume >= 10)
- Low_volume = 0;
- }
- /* USER CODE END EXTI0_IRQn 0 */
- HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
- /* USER CODE BEGIN EXTI0_IRQn 1 */
-
- /* USER CODE END EXTI0_IRQn 1 */
- }
-
- /**
- * @brief This function handles EXTI line1 interrupt.
- */
- void EXTI1_IRQHandler(void)
- {
- /* USER CODE BEGIN EXTI1_IRQn 0 */
- if(HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_1) == 0)//确保数据稳定
- {
- //控制音乐播放的�?�度
- static int i = 0;
- i++;
- //倍数计算公式 1 + (1 - (新的节拍速度 / 原来的节拍�?�度))
- switch(i){
- case 0:{
- Beat_speed = 5; //0.5s半个节拍,正常+�?�度
- break;
- }
- case 1:{
- Beat_speed = 4; //1.2倍数
- break;
- }
- case 2:{
- Beat_speed = 3; //约等�?? 1.5倍数
- break;
- }
- case 3:{
- Beat_speed = 1; //约等�?? 2 倍数
- break;
- }
- case 4:{
- Beat_speed = 6; //约等�?? 0.8 倍数
- break;
- }
- case 5:{
- Beat_speed = 7; //约等�?? 0.6 倍数
- break;
- }
-
- default:{
- Beat_speed = 5; //0.5s半个节拍,正常�?�度
- i=0;
- break;
- }
- }
- }
- /* USER CODE END EXTI1_IRQn 0 */
- HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
- /* USER CODE BEGIN EXTI1_IRQn 1 */
-
- /* USER CODE END EXTI1_IRQn 1 */
- }
-
- /**
- * @brief This function handles EXTI line2 interrupt.
- */
- void EXTI2_IRQHandler(void)
- {
- /* USER CODE BEGIN EXTI2_IRQn 0 */
- //按下�??次音乐进入下�??�??
- if(HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_2) == 0)//确保数据稳定
- {
- list++;
- if(list > list_max){
- list = 0;
- }
- }
- /* USER CODE END EXTI2_IRQn 0 */
- HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);
- /* USER CODE BEGIN EXTI2_IRQn 1 */
-
- /* USER CODE END EXTI2_IRQn 1 */
- }
-
- /**
- * @brief This function handles TIM2 global interrupt.
- */
- void TIM2_IRQHandler(void)
- {
- /* USER CODE BEGIN TIM2_IRQn 0 */
- if(EN == 1)
- time_100ms_cnt++;
- else
- time_100ms_cnt = time_100ms_cnt; //其余状�?�不计数
-
- if(time_100ms_cnt >= Beat_speed_n * Beat_num){ //这个音节结束
- time_100ms_cnt = 0;
- flag = 1; //发�?�音节结束信�??
- }
- /* USER CODE END TIM2_IRQn 0 */
- HAL_TIM_IRQHandler(&htim2);
- /* USER CODE BEGIN TIM2_IRQn 1 */
-
- /* USER CODE END TIM2_IRQn 1 */
- }
-
- /**
- * @brief This function handles EXTI line9 interrupt.
- */
- void EXTI9_IRQHandler(void)
- {
- /* USER CODE BEGIN EXTI9_IRQn 0 */
- if(HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_9) == 0)//确保数据稳定
- EN = !EN;
- /* USER CODE END EXTI9_IRQn 0 */
- HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9);
- /* USER CODE BEGIN EXTI9_IRQn 1 */
-
- /* USER CODE END EXTI9_IRQn 1 */
- }

- /* USER CODE BEGIN Header */
- /**
- ******************************************************************************
- * @file : main.c
- * @brief : Main program body
- ******************************************************************************
- * @attention
- *
- * <h2><center>© Copyright (c) 2024 STMicroelectronics.
- * All rights reserved.</center></h2>
- *
- * This software component is licensed by ST under BSD 3-Clause license,
- * the "License"; You may not use this file except in compliance with the
- * License. You may obtain a copy of the License at:
- * opensource.org/licenses/BSD-3-Clause
- *
- ******************************************************************************
- */
- /* USER CODE END Header */
- /* Includes ------------------------------------------------------------------*/
- #include "main.h"
-
- /* Private includes ----------------------------------------------------------*/
- /* USER CODE BEGIN Includes */
-
- /* USER CODE END Includes */
-
- /* Private typedef -----------------------------------------------------------*/
- /* USER CODE BEGIN PTD */
-
- #include <string.h> // 引入strcpy函数�?�?的头文件
- /* USER CODE END PTD */
-
- /* Private define ------------------------------------------------------------*/
- /* USER CODE BEGIN PD */
- /* USER CODE END PD */
-
- /* Private macro -------------------------------------------------------------*/
- /* USER CODE BEGIN PM */
-
- /* USER CODE END PM */
-
- /* Private variables ---------------------------------------------------------*/
- TIM_HandleTypeDef htim2;
- TIM_HandleTypeDef htim4;
-
- /* USER CODE BEGIN PV */
-
- /* USER CODE END PV */
-
- /* Private function prototypes -----------------------------------------------*/
- void SystemClock_Config(void);
- static void MX_GPIO_Init(void);
- static void MX_TIM4_Init(void);
- static void MX_TIM2_Init(void);
- /* USER CODE BEGIN PFP */
-
- /* USER CODE END PFP */
-
- /* Private user code ---------------------------------------------------------*/
- /* USER CODE BEGIN 0 */
-
- //将LED设置成全�??
- void LED_RESET(){
- HAL_GPIO_WritePin(GPIOF, GPIO_PIN_1, GPIO_PIN_RESET);
- HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET);
- HAL_GPIO_WritePin(GPIOI, GPIO_PIN_11|GPIO_PIN_10, GPIO_PIN_RESET);
- }
-
- void LED(int i){
- if(i >= 1) HAL_GPIO_WritePin(GPIOF, GPIO_PIN_1, GPIO_PIN_SET);
- if(i >= 2) HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_SET);
- if(i >= 3) HAL_GPIO_WritePin(GPIOI, GPIO_PIN_11,GPIO_PIN_SET);
- if(i >= 4) HAL_GPIO_WritePin(GPIOI, GPIO_PIN_10, GPIO_PIN_SET);
- }
- //随音节输入,改变LED状�??
- void LED_BEEP(int i){
- LED_RESET();
- switch(i){
- case 1:{
- LED(1);
- break;
- }
- case 2:{
- LED(1);
- break;
- }
-
- case 3:{
- LED(2);
- break;
- }
- case 4:{
- LED(2);
- break;
- }
-
- case 5:{
- LED(3);
- break;
- }
- case 6:{
- LED(3);
- break;
- }
-
- case 7:{
- LED(4);
- break;
- }
- default:{
- LED_RESET();
- break;
- }
- }
- }
-
-
- extern int time_100ms_cnt; //0.1s计数�??
- extern int Beat_speed; //节拍速度,代表半个节拍需要多少个0.1s
- extern int Beat_speed_n; //实际执行的节�??
-
- extern int Beat_num; //这个�?? �??要多少个 半拍
- extern int flag; //当其等于 1 时,表示�??个音结束
- extern int EN; //使能信号,用于开启整个音�??
- extern int list ; //音乐列表
- extern int list_max ; //音乐总数
- extern int Low_volume; //音量大小
-
- int tone[3][8];
- //初始化高中低�??
- void tone_init(){
- tone[1][0] = 0; //不执�??
- tone[1][1] = 191;
- tone[1][2] = 170;
- tone[1][3] = 151;
- tone[1][4] = 143;
- tone[1][5] = 127;
- tone[1][6] = 113;
- tone[1][7] = 101;
- // 低音 (Low)
- for (int i = 0; i < 8; i++) {
- tone[0][i] = tone[1][i] * 2; // 只是�??个近似的值,实际值可能不�??
- }
-
- // 高音 (High)
- for (int i = 0; i < 8; i++) {
- tone[2][i] = tone[1][i] / 2; // 只是�??个近似的值,实际值可能不�??
- }
- }
-
-
- #define MAX_unit_num 200 //�??大乐谱数�??
- //创建结构体保存乐�??
- struct music_unit{
- char name[50]; //乐谱名称
- int unit[MAX_unit_num]; //发什么音
- int unit_HL[MAX_unit_num]; //发高音或者其�??
- int time[MAX_unit_num]; //发音时间
- //int time_4[MAX_unit_num]; //判断是否�??1/4�??
- int num; //记录有多少个
- }music[25];
-
- //创建乐谱 返回有多少首音乐
- int music_init(){
- int cnt = 0;
- //第一首音�?? 生日快乐
- strcpy(music[0].name, "生日快乐"); // 使用strcpy复制字符�?? 给音乐命�??
- int music0_unit[29] = {0,0, 5,5,6,5,1,7, 5,5,6,5,2,1,
- 5,5,6,3,1,7, 6,4,4,3,1,2,1,
- 0,0}; //基础乐谱
- int music0_time[29] = {1,1, 1,1,2,2,2,3, 1,1,2,2,2,3,
- 2,2,2,2,2,2, 2,2,2,2,2,2,3,
- 1,1}; //乐谱节拍
- music[0].num = 29; //乐谱总数
- int music0_unit_HL[29] = {1,1,
- 0,0,0,0,1,0, 0,0,0,0,1,1,
- 0,0,1,1,1,0, 0,1,1,1,1,1,1,
- 1,1}; //乐谱全为中音
-
- //第二首音�?? �??闪一闪亮晶晶
- cnt++;
- strcpy(music[1].name, "�??闪一闪亮晶晶"); // 使用strcpy复制字符�?? 给音乐命�??
- int music1_unit[44] = {0,
- 1,1,5,5,6,6,5, 4,4,3,3,2,2,1,
- 5,5,4,4,3,3,2, 5,5,4,4,3,3,2,
- 1,1,5,5,6,6,5, 4,4,3,3,2,2,1,
- 0}; //基础乐谱
- int music1_time[44] = {2,
- 2,2,2,2,2,2,3, 2,2,2,2,2,2,3,
- 2,2,2,2,2,2,3, 2,2,2,2,2,2,3,
- 2,2,2,2,2,2,3, 2,2,2,2,2,2,3,
- 2}; //乐谱节拍
- int music1_unit_HL[44] =
- {1,
- 1,1,1,1,1,1,1, 1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1, 1,1,1,1,1,1,1,
- 1,1,1,1,1,1,1, 1,1,1,1,1,1,1,
- 1}; //乐谱全为中音
- music[1].num = 44; //乐谱总数
-
-
-
- //第三首音�?? 两只老虎
- cnt++;
- strcpy(music[2].name, "两只老虎"); // 使用strcpy复制字符�?? 给音乐命�??
- int music2_unit[38] = {0,
- 1,2,3,1, 1,2,3,1, 3,4,5,5, 3,4,5,5,
- 5,6,5,4, 3,1,5,6, 5,4,3,1, 1,5,1,1,
- 1,5,1,1, 0}; //基础乐谱
- int music2_time[38] = {2,
- 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
- 0,0,0,0, 1,1,0,0, 0,0,1,1, 1,1,1,2,
- 1,1,1,2, 2}; //乐谱节拍
- int music2_unit_HL[38] =
- {1,
- 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
- 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,1,1,
- 1,0,1,1, 1}; //乐谱�?? 中音
- music[2].num = 38; //乐谱总数
-
-
- //第四首音�?? 青花瓷片�??
- cnt++;
- strcpy(music[3].name, "青花瓷片选"); // 使用strcpy复制字符�?? 给音乐命�??
- int music3_unit[100] = {0,0,0,0, 0,5,5,3, 2,3,6,2, 3,5,3,2, 2,5,5,3,
- 2,3,5,2, 3,5,2,1, 1,1,2,3, 5,6,5,4, 5,3,3,2,
- 2,2,1,2, 1,1,2,1, 2,3,5,3, 3,3,5,5, 3,2,3,6,
- 2,3,5,3, 2,2,5,5, 3,2,3,5, 2,3,5,2, 1,1,1,2,
- 3,5,6,5, 4,5,3,3, 2,2,5,3, 2,2,2,1, 1,0,0,0}; //基础乐谱
-
- int music3_time[100] = {0,0,0,0, 0,0,0,0, 0,0,1,0, 0,0,0,2, 0,0,0,0,
- 0,0,1,0, 0,0,0,2, 0,0,0,0, 0,0,0,0, 0,0,0,0,
- 2,0,0,0, 0,0,0,0, 0,1,0,0, 2,0,0,0, 0,0,0,1,
- 0,0,0,0, 2,0,0,0, 0,0,0,1, 0,0,0,0, 2,0,0,0,
- 0,0,0,0, 0,0,0,0, 0,2,0,1, 0,0,0,1, 2,1,1,1}; //乐谱节拍
-
- for(int i =0;i<100;i++)
- music3_time[i] = music3_time[i]+1;
-
- int music3_unit_HL[100] =
- { 1,1,1,1, 1,1,1,1, 1,1,0,1, 1,1,1,1, 1,1,1,1,
- 1,1,0,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
- 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,0,
- 1,1,1,1, 1,1,1,1, 1,1,1,0, 1,1,1,1, 1,1,1,1,
- 1,1,1,1, 1,1,1,1, 1,1,0,1, 1,1,1,1, 1,1,1,1}; //乐谱�?? 中音
- music[3].num = 100; //乐谱总数
-
-
-
-
- for (int i = 0; i < MAX_unit_num; i++) {
- //将乐谱保存进结构�??
- if(i<music[0].num){//确保数据正确
- music[0].unit[i] =music0_unit[i];
- music[0].unit_HL[i] =music0_unit_HL[i];
- music[0].time[i] =music0_time[i];
- }
-
-
- //将乐谱保存进结构�??
- if(i<music[1].num){//确保数据正确
- music[1].unit[i] =music1_unit[i];
- music[1].unit_HL[i] =music1_unit_HL[i];
- music[1].time[i] =music1_time[i];
- }
-
- //将乐谱保存进结构�??
- if(i<music[2].num){//确保数据正确
- music[2].unit[i] =music2_unit[i];
- music[2].unit_HL[i] =music2_unit_HL[i];
- music[2].time[i] =music2_time[i];
- }
-
-
- //将乐谱保存进结构�??
- if(i<music[3].num){//确保数据正确
- music[3].unit[i] =music3_unit[i];
- music[3].unit_HL[i] =music3_unit_HL[i];
- music[3].time[i] =music3_time[i];
- }
- }
-
-
- return cnt;
- }
-
-
-
-
-
- //播放�?? N首音�?? 音量�?? X 0 - 100
- void play_music(int n, int x){
- static int ni = 0; //用于判断 是否换了音乐
- static int cnt = 0; //记录播放到哪�??�?? 音节
- if(ni != n ){//如果音乐换了
- ni = n;
- cnt = 0;
- __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,0);//设置音量
- HAL_Delay(1000);//
- }
-
- //
- int value = tone[music[n].unit_HL[cnt]][music[n].unit[cnt]]; //获取频率
- if(flag == 1){ //接受到一个音节结�??
- flag = 0; //复位
- Beat_num = music[n].time[cnt]; //这个音需要多少个半拍
- LED_BEEP(music[n].unit[cnt]); //LED随音节变动�?�变�??
-
- if(music[n].time[cnt] == 0){//如果�?? 1/4�??
- Beat_speed_n = Beat_speed /2;
- }
- else{//如果没有1/4�??
- Beat_speed_n = Beat_speed;
- }
-
- //if(value != 0)//如果有频率�?�执行,没有者只更新 时间�??
- __HAL_TIM_SET_AUTORELOAD(&htim4,value); //自动加载频率�??
-
- cnt ++; //可进行下�??次音�??
- if(cnt >= music[n].num){ //如果�??个音节播放完�??
- cnt = 0;//重新播放
- //__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,0);//设置音量
- //HAL_Delay(500);//
- }
- }
- //__HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,x * (value/100));//设置音量
- __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,(value/10)*x);//设置音量
- }
-
-
- /* USER CODE END 0 */
-
- /**
- * @brief The application entry point.
- * @retval int
- */
- int main(void)
- {
- /* USER CODE BEGIN 1 */
-
- /* USER CODE END 1 */
-
- /* MCU Configuration--------------------------------------------------------*/
-
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
- HAL_Init();
-
- /* USER CODE BEGIN Init */
-
- /* USER CODE END Init */
-
- if(IS_ENGINEERING_BOOT_MODE())
- {
- /* Configure the system clock */
- SystemClock_Config();
- }
-
- /* USER CODE BEGIN SysInit */
-
- /* USER CODE END SysInit */
-
- /* Initialize all configured peripherals */
- MX_GPIO_Init();
- MX_TIM4_Init();
- MX_TIM2_Init();
- /* USER CODE BEGIN 2 */
- tone_init(); //初始化音量频�??
- list_max = music_init();//更新乐谱
- HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_1); //�??启PWM
- HAL_TIM_Base_Start_IT(&htim2); //�??启定时器�??
- /* USER CODE END 2 */
-
- /* Infinite loop */
- /* USER CODE BEGIN WHILE */
- while (1)
- {
- /* USER CODE END WHILE */
-
- /* USER CODE BEGIN 3 */
-
- if(EN == 1)//�??启音�??
- play_music(list,Low_volume);
- else
- __HAL_TIM_SET_COMPARE(&htim4,TIM_CHANNEL_1,0);//设置音量
-
-
- //EN = 1;
- //play_music(0,5);
- }
- /* USER CODE END 3 */
- }
-
- /**
- * @brief System Clock Configuration
- * @retval None
- */
- void SystemClock_Config(void)
- {
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
- RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
-
- /** Initializes the RCC Oscillators according to the specified parameters
- * in the RCC_OscInitTypeDef structure.
- */
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI;
- RCC_OscInitStruct.HSIState = RCC_HSI_ON;
- RCC_OscInitStruct.HSICalibrationValue = 16;
- RCC_OscInitStruct.HSIDivValue = RCC_HSI_DIV1;
- RCC_OscInitStruct.LSIState = RCC_LSI_ON;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
- RCC_OscInitStruct.PLL2.PLLState = RCC_PLL_NONE;
- RCC_OscInitStruct.PLL3.PLLState = RCC_PLL_NONE;
- RCC_OscInitStruct.PLL4.PLLState = RCC_PLL_NONE;
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
- {
- Error_Handler();
- }
- /** RCC Clock Config
- */
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_ACLK
- |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
- |RCC_CLOCKTYPE_PCLK3|RCC_CLOCKTYPE_PCLK4
- |RCC_CLOCKTYPE_PCLK5;
- RCC_ClkInitStruct.AXISSInit.AXI_Clock = RCC_AXISSOURCE_HSI;
- RCC_ClkInitStruct.AXISSInit.AXI_Div = RCC_AXI_DIV1;
- RCC_ClkInitStruct.MCUInit.MCU_Clock = RCC_MCUSSOURCE_HSI;
- RCC_ClkInitStruct.MCUInit.MCU_Div = RCC_MCU_DIV1;
- RCC_ClkInitStruct.APB4_Div = RCC_APB4_DIV1;
- RCC_ClkInitStruct.APB5_Div = RCC_APB5_DIV1;
- RCC_ClkInitStruct.APB1_Div = RCC_APB1_DIV1;
- RCC_ClkInitStruct.APB2_Div = RCC_APB2_DIV1;
- RCC_ClkInitStruct.APB3_Div = RCC_APB3_DIV1;
-
- if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct) != HAL_OK)
- {
- Error_Handler();
- }
- }
-
- /**
- * @brief TIM2 Initialization Function
- * @param None
- * @retval None
- */
- static void MX_TIM2_Init(void)
- {
-
- /* USER CODE BEGIN TIM2_Init 0 */
-
- /* USER CODE END TIM2_Init 0 */
-
- TIM_ClockConfigTypeDef sClockSourceConfig = {0};
- TIM_MasterConfigTypeDef sMasterConfig = {0};
-
- /* USER CODE BEGIN TIM2_Init 1 */
-
- /* USER CODE END TIM2_Init 1 */
- htim2.Instance = TIM2;
- htim2.Init.Prescaler = 6400-1;
- htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
- htim2.Init.Period = 1000-1;
- htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
- htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
- if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
- {
- Error_Handler();
- }
- sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
- if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
- {
- Error_Handler();
- }
- sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
- sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
- if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
- {
- Error_Handler();
- }
- /* USER CODE BEGIN TIM2_Init 2 */
-
- /* USER CODE END TIM2_Init 2 */
-
- }
-
- /**
- * @brief TIM4 Initialization Function
- * @param None
- * @retval None
- */
- static void MX_TIM4_Init(void)
- {
-
- /* USER CODE BEGIN TIM4_Init 0 */
-
- /* USER CODE END TIM4_Init 0 */
-
- TIM_ClockConfigTypeDef sClockSourceConfig = {0};
- TIM_MasterConfigTypeDef sMasterConfig = {0};
- TIM_OC_InitTypeDef sConfigOC = {0};
-
- /* USER CODE BEGIN TIM4_Init 1 */
-
- /* USER CODE END TIM4_Init 1 */
- htim4.Instance = TIM4;
- htim4.Init.Prescaler = 640-1;
- htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
- htim4.Init.Period = 100-1;
- htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
- htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
- if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
- {
- Error_Handler();
- }
- sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
- if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
- {
- Error_Handler();
- }
- if (HAL_TIM_PWM_Init(&htim4) != HAL_OK)
- {
- Error_Handler();
- }
- sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
- sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
- if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
- {
- Error_Handler();
- }
- sConfigOC.OCMode = TIM_OCMODE_PWM1;
- sConfigOC.Pulse = 0;
- sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
- sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
- if (HAL_TIM_PWM_ConfigChannel(&htim4, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
- {
- Error_Handler();
- }
- /* USER CODE BEGIN TIM4_Init 2 */
-
- /* USER CODE END TIM4_Init 2 */
- HAL_TIM_MspPostInit(&htim4);
-
- }
-
- /**
- * @brief GPIO Initialization Function
- * @param None
- * @retval None
- */
- static void MX_GPIO_Init(void)
- {
- GPIO_InitTypeDef GPIO_InitStruct = {0};
-
- /* GPIO Ports Clock Enable */
- __HAL_RCC_GPIOF_CLK_ENABLE();
- __HAL_RCC_GPIOC_CLK_ENABLE();
- __HAL_RCC_GPIOI_CLK_ENABLE();
- __HAL_RCC_GPIOG_CLK_ENABLE();
- __HAL_RCC_GPIOE_CLK_ENABLE();
- __HAL_RCC_GPIOB_CLK_ENABLE();
-
- /*Configure GPIO pin Output Level */
- HAL_GPIO_WritePin(GPIOF, GPIO_PIN_1|GPIO_PIN_6, GPIO_PIN_RESET);
-
- /*Configure GPIO pin Output Level */
- HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, GPIO_PIN_RESET);
-
- /*Configure GPIO pin Output Level */
- HAL_GPIO_WritePin(GPIOI, GPIO_PIN_11|GPIO_PIN_10, GPIO_PIN_RESET);
-
- /*Configure GPIO pins : PF1 PF6 */
- GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_6;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
- HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
-
- /*Configure GPIO pin : PC7 */
- GPIO_InitStruct.Pin = GPIO_PIN_7;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
- HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
-
- /*Configure GPIO pins : PI11 PI10 */
- GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_10;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
- HAL_GPIO_Init(GPIOI, &GPIO_InitStruct);
-
- /*Configure GPIO pins : PG2 PG0 PG1 */
- GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_0|GPIO_PIN_1;
- GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
- GPIO_InitStruct.Pull = GPIO_PULLUP;
- HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
-
- /*Configure GPIO pin : PE9 */
- GPIO_InitStruct.Pin = GPIO_PIN_9;
- GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
- GPIO_InitStruct.Pull = GPIO_PULLUP;
- HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
-
- /* EXTI interrupt init*/
- HAL_NVIC_SetPriority(EXTI0_IRQn, 2, 0);
- HAL_NVIC_EnableIRQ(EXTI0_IRQn);
-
- HAL_NVIC_SetPriority(EXTI1_IRQn, 2, 0);
- HAL_NVIC_EnableIRQ(EXTI1_IRQn);
-
- HAL_NVIC_SetPriority(EXTI2_IRQn, 2, 0);
- HAL_NVIC_EnableIRQ(EXTI2_IRQn);
-
- HAL_NVIC_SetPriority(EXTI9_IRQn, 1, 0);
- HAL_NVIC_EnableIRQ(EXTI9_IRQn);
-
- }
-
- /* USER CODE BEGIN 4 */
-
- /* USER CODE END 4 */
-
- /**
- * @brief This function is executed in case of error occurrence.
- * @retval None
- */
- void Error_Handler(void)
- {
- /* USER CODE BEGIN Error_Handler_Debug */
- /* User can add his own implementation to report the HAL error return state */
- __disable_irq();
- while (1)
- {
- }
- /* USER CODE END Error_Handler_Debug */
- }
-
- #ifdef USE_FULL_ASSERT
- /**
- * @brief Reports the name of the source file and the source line number
- * where the assert_param error has occurred.
- * @param file: pointer to the source file name
- * @param line: assert_param error line source number
- * @retval None
- */
- void assert_failed(uint8_t *file, uint32_t line)
- {
- /* USER CODE BEGIN 6 */
- /* User can add his own implementation to report the file name and line number,
- ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
- /* USER CODE END 6 */
- }
- #endif /* USE_FULL_ASSERT */
-
- /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

- /* USER CODE BEGIN Header */
- /**
- ******************************************************************************
- * @file stm32mp1xx_it.c
- * @brief Interrupt Service Routines.
- ******************************************************************************
- * @attention
- *
- * <h2><center>© Copyright (c) 2024 STMicroelectronics.
- * All rights reserved.</center></h2>
- *
- * This software component is licensed by ST under BSD 3-Clause license,
- * the "License"; You may not use this file except in compliance with the
- * License. You may obtain a copy of the License at:
- * opensource.org/licenses/BSD-3-Clause
- *
- ******************************************************************************
- */
- /* USER CODE END Header */
-
- /* Includes ------------------------------------------------------------------*/
- #include "main.h"
- #include "stm32mp1xx_it.h"
- /* Private includes ----------------------------------------------------------*/
- /* USER CODE BEGIN Includes */
- /* USER CODE END Includes */
-
- /* Private typedef -----------------------------------------------------------*/
- /* USER CODE BEGIN TD */
-
- /* USER CODE END TD */
-
- /* Private define ------------------------------------------------------------*/
- /* USER CODE BEGIN PD */
-
- /* USER CODE END PD */
-
- /* Private macro -------------------------------------------------------------*/
- /* USER CODE BEGIN PM */
-
- /* USER CODE END PM */
-
- /* Private variables ---------------------------------------------------------*/
- /* USER CODE BEGIN PV */
-
- /* USER CODE END PV */
-
- /* Private function prototypes -----------------------------------------------*/
- /* USER CODE BEGIN PFP */
-
- /* USER CODE END PFP */
-
- /* Private user code ---------------------------------------------------------*/
- /* USER CODE BEGIN 0 */
- int time_100ms_cnt = 0; //0.1s计数�??
- int Beat_speed = 5; //节拍速度,代表半个节拍需要多少个0.1s
- int Beat_speed_n = 0; //实际执行的节�??
-
- int Beat_num = 2; //这个�?? �??要多少就 半拍
- int flag = 0; //当其等于 1 时,表示�??个音结束
- int EN = 0; //使能信号,用于开启整个音�??
- int list = 0; //音乐列表
- int list_max = 0; //音乐总数
- int Low_volume = 5; //音量大小
- #define Low_volume_cnt 3 //音量大小�??10增加
-
- /* USER CODE END 0 */
-
- /* External variables --------------------------------------------------------*/
- extern TIM_HandleTypeDef htim2;
- /* USER CODE BEGIN EV */
-
- /* USER CODE END EV */
-
- /******************************************************************************/
- /* Cortex-M4 Processor Interruption and Exception Handlers */
- /******************************************************************************/
- /**
- * @brief This function handles Non maskable interrupt.
- */
- void NMI_Handler(void)
- {
- /* USER CODE BEGIN NonMaskableInt_IRQn 0 */
-
- /* USER CODE END NonMaskableInt_IRQn 0 */
- /* USER CODE BEGIN NonMaskableInt_IRQn 1 */
- while (1)
- {
- }
- /* USER CODE END NonMaskableInt_IRQn 1 */
- }
-
- /**
- * @brief This function handles Hard fault interrupt.
- */
- void HardFault_Handler(void)
- {
- /* USER CODE BEGIN HardFault_IRQn 0 */
-
- /* USER CODE END HardFault_IRQn 0 */
- while (1)
- {
- /* USER CODE BEGIN W1_HardFault_IRQn 0 */
- /* USER CODE END W1_HardFault_IRQn 0 */
- }
- }
-
- /**
- * @brief This function handles Memory management fault.
- */
- void MemManage_Handler(void)
- {
- /* USER CODE BEGIN MemoryManagement_IRQn 0 */
-
- /* USER CODE END MemoryManagement_IRQn 0 */
- while (1)
- {
- /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
- /* USER CODE END W1_MemoryManagement_IRQn 0 */
- }
- }
-
- /**
- * @brief This function handles Pre-fetch fault, memory access fault.
- */
- void BusFault_Handler(void)
- {
- /* USER CODE BEGIN BusFault_IRQn 0 */
-
- /* USER CODE END BusFault_IRQn 0 */
- while (1)
- {
- /* USER CODE BEGIN W1_BusFault_IRQn 0 */
- /* USER CODE END W1_BusFault_IRQn 0 */
- }
- }
-
- /**
- * @brief This function handles Undefined instruction or illegal state.
- */
- void UsageFault_Handler(void)
- {
- /* USER CODE BEGIN UsageFault_IRQn 0 */
-
- /* USER CODE END UsageFault_IRQn 0 */
- while (1)
- {
- /* USER CODE BEGIN W1_UsageFault_IRQn 0 */
- /* USER CODE END W1_UsageFault_IRQn 0 */
- }
- }
-
- /**
- * @brief This function handles System service call via SWI instruction.
- */
- void SVC_Handler(void)
- {
- /* USER CODE BEGIN SVCall_IRQn 0 */
-
- /* USER CODE END SVCall_IRQn 0 */
- /* USER CODE BEGIN SVCall_IRQn 1 */
-
- /* USER CODE END SVCall_IRQn 1 */
- }
-
- /**
- * @brief This function handles Debug monitor.
- */
- void DebugMon_Handler(void)
- {
- /* USER CODE BEGIN DebugMonitor_IRQn 0 */
-
- /* USER CODE END DebugMonitor_IRQn 0 */
- /* USER CODE BEGIN DebugMonitor_IRQn 1 */
-
- /* USER CODE END DebugMonitor_IRQn 1 */
- }
-
- /**
- * @brief This function handles Pendable request for system service.
- */
- void PendSV_Handler(void)
- {
- /* USER CODE BEGIN PendSV_IRQn 0 */
-
- /* USER CODE END PendSV_IRQn 0 */
- /* USER CODE BEGIN PendSV_IRQn 1 */
-
- /* USER CODE END PendSV_IRQn 1 */
- }
-
- /**
- * @brief This function handles System tick timer.
- */
- void SysTick_Handler(void)
- {
- /* USER CODE BEGIN SysTick_IRQn 0 */
-
- /* USER CODE END SysTick_IRQn 0 */
- HAL_IncTick();
- /* USER CODE BEGIN SysTick_IRQn 1 */
-
- /* USER CODE END SysTick_IRQn 1 */
- }
-
- /******************************************************************************/
- /* STM32MP1xx Peripheral Interrupt Handlers */
- /* Add here the Interrupt Handlers for the used peripherals. */
- /* For the available peripheral interrupt handler names, */
- /* please refer to the startup file (startup_stm32mp1xx.s). */
- /******************************************************************************/
-
- /**
- * @brief This function handles EXTI line0 interrupt.
- */
- void EXTI0_IRQHandler(void)
- {
- /* USER CODE BEGIN EXTI0_IRQn 0 */
- if(HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_0) == 0)//确保数据稳定
- {
- //每次按下解决 音量�?? Low_volume_cnt
- Low_volume = Low_volume + Low_volume_cnt;
- if(Low_volume >= 10)
- Low_volume = 0;
- }
- /* USER CODE END EXTI0_IRQn 0 */
- HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
- /* USER CODE BEGIN EXTI0_IRQn 1 */
-
- /* USER CODE END EXTI0_IRQn 1 */
- }
-
- /**
- * @brief This function handles EXTI line1 interrupt.
- */
- void EXTI1_IRQHandler(void)
- {
- /* USER CODE BEGIN EXTI1_IRQn 0 */
- if(HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_1) == 0)//确保数据稳定
- {
- //控制音乐播放的�?�度
- static int i = 0;
- i++;
- //倍数计算公式 1 + (1 - (新的节拍速度 / 原来的节拍�?�度))
- switch(i){
- case 0:{
- Beat_speed = 5; //0.5s半个节拍,正常+�?�度
- break;
- }
- case 1:{
- Beat_speed = 4; //1.2倍数
- break;
- }
- case 2:{
- Beat_speed = 3; //约等�?? 1.5倍数
- break;
- }
- case 3:{
- Beat_speed = 1; //约等�?? 2 倍数
- break;
- }
- case 4:{
- Beat_speed = 6; //约等�?? 0.8 倍数
- break;
- }
- case 5:{
- Beat_speed = 7; //约等�?? 0.6 倍数
- break;
- }
-
- default:{
- Beat_speed = 5; //0.5s半个节拍,正常�?�度
- i=0;
- break;
- }
- }
- }
- /* USER CODE END EXTI1_IRQn 0 */
- HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
- /* USER CODE BEGIN EXTI1_IRQn 1 */
-
- /* USER CODE END EXTI1_IRQn 1 */
- }
-
- /**
- * @brief This function handles EXTI line2 interrupt.
- */
- void EXTI2_IRQHandler(void)
- {
- /* USER CODE BEGIN EXTI2_IRQn 0 */
- //按下�??次音乐进入下�??�??
- if(HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_2) == 0)//确保数据稳定
- {
- list++;
- if(list > list_max){
- list = 0;
- }
- }
- /* USER CODE END EXTI2_IRQn 0 */
- HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_2);
- /* USER CODE BEGIN EXTI2_IRQn 1 */
-
- /* USER CODE END EXTI2_IRQn 1 */
- }
-
- /**
- * @brief This function handles TIM2 global interrupt.
- */
- void TIM2_IRQHandler(void)
- {
- /* USER CODE BEGIN TIM2_IRQn 0 */
- if(EN == 1)
- time_100ms_cnt++;
- else
- time_100ms_cnt = time_100ms_cnt; //其余状�?�不计数
-
- if(time_100ms_cnt >= Beat_speed_n * Beat_num){ //这个音节结束
- time_100ms_cnt = 0;
- flag = 1; //发�?�音节结束信�??
- }
- /* USER CODE END TIM2_IRQn 0 */
- HAL_TIM_IRQHandler(&htim2);
- /* USER CODE BEGIN TIM2_IRQn 1 */
-
- /* USER CODE END TIM2_IRQn 1 */
- }
-
- /**
- * @brief This function handles EXTI line9 interrupt.
- */
- void EXTI9_IRQHandler(void)
- {
- /* USER CODE BEGIN EXTI9_IRQn 0 */
- if(HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_9) == 0)//确保数据稳定
- EN = !EN;
- /* USER CODE END EXTI9_IRQn 0 */
- HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9);
- /* USER CODE BEGIN EXTI9_IRQn 1 */
-
- /* USER CODE END EXTI9_IRQn 1 */
- }
-
- /**
- * @brief This function handles RCC wake-up interrupt.
- */
- void RCC_WAKEUP_IRQHandler(void)
- {
- /* USER CODE BEGIN RCC_WAKEUP_IRQn 0 */
-
- /* USER CODE END RCC_WAKEUP_IRQn 0 */
- HAL_RCC_WAKEUP_IRQHandler();
- /* USER CODE BEGIN RCC_WAKEUP_IRQn 1 */
-
- /* USER CODE END RCC_WAKEUP_IRQn 1 */
- }
-
- /* USER CODE BEGIN 1 */
-
- /* USER CODE END 1 */
- /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

这是一个基于STM32MP157A单片机的音乐盒设计较为全面和详细。主要包括以下几个方面:
硬件设计:
软件设计:
中断处理:
整体架构:
总的来说,这个音乐盒的设计充分==利用了STM32MP157A单片机的各种外设资源,实现了一个功能丰富的音乐播放器。对于初学者来说,这个对于了解定时器和PWM有一定帮助。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。