OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5917|回复: 11

通过战舰开发板演奏音乐实验分享

[复制链接]

1

主题

29

帖子

0

精华

初级会员

Rank: 2

积分
53
金钱
53
注册时间
2014-8-18
在线时间
0 小时
发表于 2014-8-24 15:11:04 | 显示全部楼层 |阅读模式
自19日收到开发板已快一周。以前一直以为STM32莫测高深,通过看配套的视频、配套的学习资料,发现要入门也不难。在学习了GPIO、TIM的应用后,突发奇想,如果弄首音乐在开发板上演奏,是什么情况?
说干就干!
GPIO用于控制LED的闪亮,开发板的喇叭(蜂鸣器)接在PB8,复用功能是TIM4_CH3,如果让TIM4_CH3工作于输出比较匹配翻转模式,当写入一定参数时,岂不能输出固定频率的方波,如果将音符对应的频率做成数据,顺序输出相应频率驱动喇叭,音乐不能成了。按照以上思路,写好程序,烧入开发板,运行程序,果然开发板发出了对应的音乐。不过开发板上装的是有源蜂鸣器,发出声音有点嘶哑,为此,将蜂鸣器更换为无源的,音乐动听多了。
以下是音乐文件,上面有《卡秋莎》、《铃儿响叮铛》,当在music.h文件的开头宏定义了MUSIC1时,演奏《卡秋莎》,否则演奏《铃儿响叮铛》。

/************************************
*     定义音乐文件二维数组{x,y}   *
*  x:对应音符音阶,0表示何止符   *
*  y:对应音符节拍,0表示音乐结束  *
************************************/
#include "sys.h"

#define MUSIC1 1

#ifdef MUSIC1      //如果定义了MUSIC1音乐为《卡秋莎》
u16 music_data[][2]=
{
 {440,600},{494,200},{523,600},{443,200},{523,400},{494,200},
 {440,200},{494,400},{330,400},{494,600},{523,200},{578,600},
 {494,200},{578,400},{523,200},{494,200},{440,800},{659,400},
 {880,400},{784,400},{880,200},{784,200},{698,400},{659,200},
 {578,200},{659,400},{440,400},{  0,200},{698,400},{578,200},
 {659,600},{523,200},{494,200},{330,200},{523,200},{494,200},
 {440,800},{659,400},{880,400},{784,400},{880,200},{784,200},
 {698,400},{659,200},{578,200},{659,400},{440,400},{  0,200},
 {698,400},{578,200},{659,600},{523,200},{494,200},{330,200},
 {523,200},{494,200},{440,800},{  0,  0}
};
#else          //否则音乐为《铃儿响叮铛》
u16 music_data[][2]=
{
 {392,200},{659,200},{587,200},{523,200},{392,400},{  0,200},
 {392,100},{392,100},
 {392,200},{659,200},{587,200},{523,200},{440,400},{  0,400},
 {440,200},{698,200},{659,200},{587,200},{494,400},{  0,400},
 {784,200},{784,200},{698,200},{587,200},{659,800},
 {392,200},{659,200},{587,200},{523,200},{392,400},{  0,200},
 {392,100},{392,100},
 {392,200},{659,200},{587,200},{523,200},{440,400},{  0,200},
 {440,200},
 {440,200},{698,200},{659,200},{587,200},{784,200},{784,200},
 {784,200},{784,200},
 {880,200},{784,200},{698,200},{587,200},{523,600},{  0,200},
 {659,200},{659,200},{659,400},{659,200},{659,200},{659,400},
 {659,200},{784,200},{523,300},{587,100},{659,600},{  0,200},
 {698,200},{698,200},{698,300},{698,100},{698,200},{659,200},
 {659,200},{659,100},{659,100},{659,200},{587,200},{587,200},
 {554,200},{587,400},{784,400},
 {659,200},{659,200},{659,400},{659,200},{659,200},{659,400},
 {659,200},{784,200},{523,300},{587,100},{659,600},{  0,200},
 {698,200},{698,200},{698,300},{698,100},{698,200},{659,200},
 {659,200},{659,100},{659,100},{784,200},{784,200},{698,300},
 {587,100},{523,600},{  0,200},
 {  0,  0}
};
#endif
TIM初始化函数如下:
void TIM4_Init(u16 arr,u16 psc)

 GPIO_InitTypeDef GPIO_InitStructure;      //设一个IO变量
 TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure; //设一个定时器变量
 TIM_OCInitTypeDef  TIM_OCInitStructure;
 

 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //使能TIM2
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //使能PWM输出端口
 
  //配置PWM输出端口:TIM4 CH3 PWM  GPIOB.8
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //TIM2_CH4
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_Init(GPIOB, &GPIO_InitStructure);  //置入

TIM_TimeBaseStructure.TIM_Period = arr; //计数上限
 TIM_TimeBaseStructure.TIM_Prescaler =psc; //分频系数
 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //时钟分割:TDTS = Tck_tim
 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM2向上计数
 TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //配置数据
 
 //???TIM4 Channel3 PWM?? 
 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; //TIM_OCMode_PWM2; //???????:TIM????????2
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //??????
 TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //????:TIM???????
 TIM_OC3Init(TIM4, &TIM_OCInitStructure);  //??T??????????TIM2 OC4

 TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Enable);  //??TIM3?CCR2????????
 
// TIM_Cmd(TIM4, ENABLE);  //??TIM2
}
主函数(演奏音乐在这里完成)如下:

#include "stm32f10x_tim.h"
#include "timer.h"
#include "sys.h"
#include "delay.h"
#include "led.h"
#include "music.h"

void sound(u16 k)
{
 u16 x;
 x=music_data[k][0];   //读取音阶数据
 if(x!=0)
 {
  x=4000000/x;     //计算计数值
  TIM4->ARR = x;    //计数值写入重装载寄存器
   GPIOB->CRH&=0XFFFFFFF0;
   GPIOB->CRH|=0X0000000B; //PB.8复用推挽输出
  TIM_Cmd(TIM4, ENABLE); //开声音
 }
 else
 {
  TIM_Cmd(TIM4, DISABLE);  //关声音disenable
   GPIOB->CRH&=0XFFFFFFF0;
   GPIOB->CRH|=0X00000003;  //PB.8推挽输出
  Bout(8)=0;        ////停止时蜂鸣器管脚低电平
 }
}


int main(void)
{
 u8 i=0;
 TIM4_Init(2000,9);  //初始化定时器4,预分频9,计数频率8M

 LED_Init();
 delay_init();

  while (1)
  {
  while(music_data[1]!=0) //等待音乐结束
  {
   LED0 = 0;         //每切换一个音符,LED0闪一下
   sound(i);         //播放音符
   delay_ms(50);
   LED0 = 1;
   delay_ms(music_data[1]-50);//音符时长
   LED1 = !LED1;       //每切换一个音符,LED1反一种状态
   i++;           //下一个音符
   TIM_Cmd(TIM4, DISABLE);  //每两个音符间停止一小会
   GPIOB->CRH&=0XFFFFFFF0;
   GPIOB->CRH|=0X00000003;  //PB.8推挽输出
   GPIO_ResetBits(GPIOB,GPIO_Pin_8);//停止时蜂鸣器管脚低电平
   delay_ms(20);
  }
  TIM_Cmd(TIM4, DISABLE);   //音乐结束,停止播放
  delay_ms(1500);//延时后继续
  delay_ms(1500);
  i=0;       //从头开始
 }
}

完整的工程文件如下:
(此工程仅为初学练习,由于不懂之处还很多,程序采用了库函数、寄存器共用方式。让各位高手见笑!请多指点!)

战舰开发板奏音乐实验.rar

1.62 MB, 下载次数: 847

活到老,学到老!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165524
金钱
165524
注册时间
2010-12-1
在线时间
2116 小时
发表于 2014-8-25 14:20:30 | 显示全部楼层
不错,谢谢分享。。。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 1 反对 0

使用道具 举报

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
发表于 2014-8-24 22:04:53 | 显示全部楼层
谢谢分享。。。。。
开往春天的手扶拖拉机
回复 支持 反对

使用道具 举报

170

主题

917

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1824
金钱
1824
注册时间
2013-4-13
在线时间
63 小时
发表于 2014-8-24 22:44:37 | 显示全部楼层
有想法,值得学习!谢谢!
手艺人要内外兼修。
回复 支持 反对

使用道具 举报

120

主题

7878

帖子

13

精华

资深版主

Rank: 8Rank: 8

积分
12012
金钱
12012
注册时间
2013-9-10
在线时间
427 小时
发表于 2014-8-25 12:43:08 | 显示全部楼层
谢谢分享!!!!!
现在,程序把烂铜烂铁变得智能化了,人呢,一旦离开了这烂铜烂铁就不知道干啥了
回复 支持 反对

使用道具 举报

23

主题

62

帖子

0

精华

初级会员

Rank: 2

积分
148
金钱
148
注册时间
2014-7-28
在线时间
4 小时
发表于 2014-8-28 21:21:13 | 显示全部楼层
太帅气了  准备下载看一看,如果代码不懂,可否回来请教一番!
回复 支持 反对

使用道具 举报

23

主题

62

帖子

0

精华

初级会员

Rank: 2

积分
148
金钱
148
注册时间
2014-7-28
在线时间
4 小时
发表于 2014-8-28 21:37:17 | 显示全部楼层
库函数的看不懂啊 ,能不能搞一个寄存器的啊
回复 支持 反对

使用道具 举报

1

主题

29

帖子

0

精华

初级会员

Rank: 2

积分
53
金钱
53
注册时间
2014-8-18
在线时间
0 小时
 楼主| 发表于 2014-9-3 13:32:58 | 显示全部楼层
回复【7楼】Mr_Head:
---------------------------------
空了试试,看能否弄一个全寄存器的版本
活到老,学到老!
回复 支持 反对

使用道具 举报

5

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
68
金钱
68
注册时间
2014-10-30
在线时间
1 小时
发表于 2014-12-23 20:08:12 | 显示全部楼层
楼主你好,刚我试了将TIM_OCInitStructure.TIM_OCMode =TIM_OCMode_Toggle改为TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;但是改了以后发现此时的输出波形频率不再变化了,能不能麻烦你或者哪位大神给解释一下,谢谢!
回复 支持 反对

使用道具 举报

1

主题

29

帖子

0

精华

初级会员

Rank: 2

积分
53
金钱
53
注册时间
2014-8-18
在线时间
0 小时
 楼主| 发表于 2014-12-27 10:46:59 | 显示全部楼层
回复【9楼】空翼0:
---------------------------------
PWM方式只是占空比变化,频率不变化。要想发出不同声音,得用匹配翻转模式,输出不同频率的波形。
活到老,学到老!
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
5
金钱
5
注册时间
2020-5-12
在线时间
0 小时
发表于 2020-5-15 01:59:41 | 显示全部楼层
下载不了了嗷
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
5
金钱
5
注册时间
2020-5-12
在线时间
0 小时
发表于 2020-5-15 02:00:38 | 显示全部楼层
都是14年的帖子了欸,都下载不了了唉
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-1 02:34

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表