stm32f103电子琴课设报告终极版1.docx
《stm32f103电子琴课设报告终极版1.docx》由会员分享,可在线阅读,更多相关《stm32f103电子琴课设报告终极版1.docx(16页珍藏版)》请在冰豆网上搜索。
stm32f103电子琴课设报告终极版1
stm32f103电子琴课设报告-终极版
(1)
TheDesignoftheKeyboard
Abstract:
Thisdesignistheprofessionaldirectionofbiomedicalengineeringdesign.UsingSingleChipMicrocomputertoachieveasimpleKeyboard.Itsmainfunctionis:
Whileauserpressthedifferentkeys,itwillmakedifferentsoundsfromthebuzzeranddisplaydifferentnumberswhichcorrespondedtothesounds.Usingstm32f103--C8T6ascontrolchip.Ithas16-bittimers.Someofthemwithupto4IC/OC/PWMorpulsecounter.MakinguseoftheTimerstogeneratedrivingsignal.Byreadingthestateoftheexternalkeytochangethefrequencyofoutput.DifferentfrequencyofthePWMwillcontrolbuzzermakesdifferentsounds.
Keywords:
STM32f103;signal;Timer
一、设计目的:
通过本次综合设计,旨在运用已经学过的知识,根据题目的要求进行软硬件系统的设计和调试,对在《单片机的原理及应用》课程中涉及的芯片结构、控制原理、硬件和编程等方面有一定的感性认识和实践操作能力。
从而加深对本课程知识点的理解,对于设计能力,调试能力,以及分析处理问题的能力得到了一定的提高。
其目的是让学生得到一次进行独立设计的工程实践锻炼,不仅培养严谨的科学态度和扎实的实践技能、良好的工程意识,并在设计中学会如何发现、分析和解决工程实践问题的技能和方法,将所学知识综合应用于工程实践中,为后续的毕业设计做好准备。
二、控制要求:
利用stm32系列单片机设计简易电子琴。
功能要求:
(1)按下不同按键,发出不同1、2、3、4、5、6、7七个音符;
(2)用LED或LCD显示当前按键
三设计原理:
单片机可以驱动蜂鸣器或其他扬声器发出声音,可以控制其发出不同的声调,从而连接起来构成一个曲子。
一般来说,单片机不像其他专业乐器能奏出各种音色的声音,单片机的音乐基本上都是单色频率。
1)音调:
在音乐中把C上方的A音定为标准音高,其频率为f=440Hz,其余音均与之比较。
音符do与音符i之间正好相差一个倍频程,即相差一个八度音。
在一个八度音中,有12个半音。
只要知道了这12个音符的音高,就可以根据音符之间的倍频程关系得到其他音符基本的音调频率。
知道了一个音符的频率之后,编可以让单片机发出相应的频率的振荡信号,从而产生相应的音符声音,常采用的方法是通过单片机的定时器进行定时中断,在中断服务子程序中,将单片机上外界扬声器的I/O口来回置高电平或低电平,从而让扬声器发出声音。
为了让单片机发出不同频率的音符的声音,只需将定时器预置不同的定时值来实现。
以标准音高A为例,标准音高的A的频率f=440Hz,其对应周期为T=1/f=2272μs,单片机上定时器的中断触发时间为t=T/2=1136μs,如果单片机外接12MHz的晶振,则F0=12MHz,则标准音高A在单片机定时器工作方式1下定时器高低计数器的初值为:
TH=FBH,TL=90H.
2)节拍:
如果规定一拍的时长为400ms,那么以四分音符为节拍时,四分音符的时长为400ms,八分音符的时长为200ms,十六分音符的时长为100ms.从而在单片机上可以采用循环延时的方法来实现控制一个音符唱多长时间。
首先要编写一个精确的基本时长的延时程序,如果以八分音符的时长为基本延时时间,那么对于一个音符,如果它是四分音符,只需调用四次延时程序,如果它是二分音符,则需要调用八次延时程序。
以此类推。
3)演奏音乐的方法:
Step1:
将乐谱中的每个音符的音调及节拍变换成相应的音调参数和节拍数;
Step2:
将这些参数做成数据表格,存放在存储器中;
Step3:
通过按键调用程序去取出一个音符的相关参数,播放该音符;
Step4:
播放完该音符后,等待下一次按键调用程序去取出下一次音符的
相关参数,再播放音符;
Step5:
对于演奏音乐,一般将休止符的音调参数设置为FFH,节拍参数设
置为00H.
蜂鸣器驱动电路
此次设计选用有源蜂鸣器。
有源蜂鸣器的发声原理是电流通过电磁线圈,使电磁线圈产生磁场来驱动振动膜发音,因此需要一定的电流才能驱动它。
单片机的I/O引脚的输出电流比较小输出的TTL电平基本上驱动不了蜂鸣器,因此需要增加一个电流放大的电路,如图4-4所示,选用NPN的三极管来达到电流放大的作用。
图1-1蜂鸣器驱动电路
按键电路:
按键都采用了上拉电阻,当按键处于不被按下的状态时,连接到单片机的一端的输入信号为高电平,当按键按下时,输入为低电平,如图4-6所示。
图1-2按键电路
四设计任务和主要内容:
主要内容:
利用实验资源实现简易电子琴的简单功能:
(1)利用蜂鸣器发出不通的声音
(2)使用lcd显示器来显示音阶输入的相关信息
(3)当按下键盘相对按键,蜂鸣器会发出相对音阶的单音,共有两个8度音阶
(4)至少可以输入16个单音,可以一起演奏出来
(5)演奏时可以按键中断
(6)按下音乐播放键可以自动播放预先存在内存中的曲子
主要技术指标和要求:
(1)充分应用已给出的开发板硬件的资源进行设计
(2)通过改变占空比产生不同频率的信号
(3)实现按键发出的相对音阶的单音
(4)可以按照已经编好的乐谱演奏出相应的音乐
五单片机控制系统原理:
本次课程设计采用atmel公司stm32f103VE单片机,stm32f103VE是低电压,高性能的cmos8位单片机,片内含8KB的程序存储器和12B的随机存取数据存储器,其主要功能特性为:
兼容MCS51指令系统·32个双向I/O口·3个16位可编程定时/计数器中断·2个串行中断·2个外部中断源·2个读写中断口线·3级加密位·低功耗空闲和耗电模式·软件设置睡眠和唤醒功能等.
单片机必须在时钟的驱动下才能工作,在单片机内部有一个时钟振荡电路,只需要外接一个振荡源就能产生一定的时钟信号送到单片机内部的各个单元,决定单片机的工作速度。
单片机的定时控制功能是用时钟电路和振荡器完成的,而根据硬件电路的不同,连接方式分为内部时钟方式和外部时钟方式。
本次设计中采用内部时钟方式。
在按键中常产生‘毛刺’现象,要消除“毛刺”现象,最常用的方法是即时重复扫描法,延时法的原理是:
‘毛刺’脉冲一般持续时间短,约为几毫秒,而我们按键的时间一般远远大于这个时间,所以当单片机检测到有按键动静后,再延时一段时间(十毫秒到二十毫秒)后再进行判断此电平是否保持原来的状态,如果是,则说明是有效的按键按下,否则为无效按键。
矩阵键盘是单片中外部设备中所使用的排列类似于矩阵的键盘组。
在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。
将行线所接的单片机的I/O口作为输出端,而列线所接的I/O口则作为输入。
行扫描法:
1、判断键盘中有无键按下将全部行线Y0-Y3置低电平,然后检测列线的状态。
只要有一列的电平为低,则表示键盘中有键被按下,而且闭合的键位于低电平线与4根行线相交叉的4个按键之中。
若所有列线均为高电平,则键盘中无键按下。
2、判断闭合键所在的位置在确认有键按下后,即可进入确定具体闭合键的过程。
其方法是:
依次将行线置为低电平,即在置某根行线为低电平时,其它线为高电平。
在确定某根行线位置为低电平后,再逐行检测各列线的电平状态。
若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。
六主程序:
主程序的流程图:
开始
按键是否按下N
Y
去抖动,延时10ms
N
按键是否按下
Y
扫描按键位置
做一次按键处理,播放
相应的音符或音乐
七、结束语:
通过本次课程设计,我不仅学会了对KEIL的应用,还加深了对STM32单片机的了解,同时也进一步增强了自己的动手能力。
通过本次设计,我不仅加深了对单片机理论的理解,将理论很好地应用到实际当中去,而且我还学会了如何去培养我们的创新精神,从而不断地战胜自己,超越自己。
创新可以是在原有的基础上进行改进,使之功能不断完善,成为真己的东西。
这个设计过程中,通过在原有的按键中断的基础上进行了改进,使之具备了电子琴的基本功能。
设计结果能够符合题意,成功完成了此次实习要求,我不只在乎这一结果,更加在乎的,是这个过程。
这个过程中,自己更加注重了一些基础的理知识的学习,很好的把平时课堂上的知识运用到了实际的操作中。
同时,软硬件的结合调试也让自己明白了理论上的很多东西也是需要实际实验的验证的。
本综合设计是让得到一次进行独立设计的工程实践锻炼,不仅培养严谨的科学态度和扎实的实践技能、良好的工程意识,并在设计中学会如何发现、分析和解决工程实践问题的技能和方法,为后续的毕业设计做好准备。
同时在这里也感谢在整个设计中帮助过我的老师和同学们。
八、参考文献
[1]冯建华,赵亮.单片机应用系统设计与产品开发[M].北京:
人民邮电出版社2004
[2]谭浩强.C语言程序设计[M].北京:
清华大学出版社1999
[3]《单片机与嵌入式:
STM32库开发实战指南》[M]北京:
机械工业出版社2013
附件:
Main.c
#include"stm32f10x.h"
#include"KEY.h"
#include"Beep.h"
#include"PWM_OutPut.h"
//intmain(void)
//{
//uint8_tK;
//
//SysTick_Init();
//KeyBoard_Init();
//TIM4_GPIO_Config();
////Beep_GPIO_Config();
////TIM4_PWM_Init();
////Beep_do();
//while
(1)
//{
////TIM4->CCR3=523;
////Delay_us(400);
////TIM4->CCR3=578;
////Delay_us(400);
////TIM4->CCR3=659;
////Delay_us(400);
////TIM4->CCR3=698;
////Delay_us(400);
////TIM4->CCR3=784;
////Delay_us(400);
////TIM4->CCR3=880;
////Delay_us(400);
////TIM4->CCR3=988;
////Delay_us(400);
//
//K=Read_KeyValue();
//switch(K)
//{
//case1:
//TIM4->CCR3=256;
//TIM4_Mode_Config(280);
////TIM_Cmd(TIM4,ENABLE);
//break;
//case2:
//TIM4->CCR3=288;
//TIM4_Mode_Config(10);
//TIM_Cmd(TIM4,ENABLE);
//Delay_us(10);
//TIM_Cmd(TIM4,DISABLE);
//break;
//case3:
//TIM4->CCR3=320;
////TIM_Cmd(TIM4,ENABLE);
//break;
//case4:
//TIM4->CCR3=341;
////TIM_Cmd(TIM4,ENABLE);
//break;
//case5:
//TIM4->CCR3=384;
////TIM_Cmd(TIM4,ENABLE);
//break;
//case6:
//TIM4->CCR3=426;
////TIM_Cmd(TIM4,ENABLE);
//break;
//case7:
//TIM4->CCR3=480;
////TIM_Cmd(TIM4,ENABLE);
//break;
//case8:
//TIM4->CCR3=512;
////TIM_Cmd(TIM4,ENABLE);
//break;
//}
////if(K==0)
////{
////TIM4->CCR3=0;
////}
//}
////addyourcodehere
//}
intmain(void)
{
TIM_SetAutoreload(TIM2,1);
TIM4_GPIO_Config();
NVIC_Configuration();
TIM4_Mode_Config();
KeyBoard_Init();
while
(1)
{
////TIM_SetAutoreload(TIM2,7);
//if(keyvalue()==0)
//{TIM_SetAutoreload(TIM2,0);}
//if(keyvalue()==1)
//{TIM_SetAutoreload(TIM2,120);}
//elseif(keyvalue()==2)
//{TIM_SetAutoreload(TIM2,110);}
//elseif(keyvalue()==3)
//{TIM_SetAutoreload(TIM2,100);}
//elseif(keyvalue()==4)
//{TIM_SetAutoreload(TIM2,90);}
//elseif(keyvalue()==5)
//{TIM_SetAutoreload(TIM2,80);}
//elseif(keyvalue()==6)
//{TIM_SetAutoreload(TIM2,70);}
//elseif(keyvalue()==7)
//{TIM_SetAutoreload(TIM2,60);}
switch(Read_KeyValue())
{
case(0):
TIM_SetAutoreload(TIM4,0);
break;
case
(1):
TIM_SetAutoreload(TIM4,3800);
break;
case
(2):
TIM_SetAutoreload(TIM4,3450);
break;
case(3):
TIM_SetAutoreload(TIM4,3100);
break;
case(4):
TIM_SetAutoreload(TIM4,2750);
break;
case(5):
TIM_SetAutoreload(TIM4,2400);
break;
case(6):
TIM_SetAutoreload(TIM4,2050);
break;
case(7):
TIM_SetAutoreload(TIM4,1700);
break;
case(8):
TIM_SetAutoreload(TIM4,1350);
break;
case(9):
TIM_SetAutoreload(TIM4,1250);
break;
case(10):
TIM_SetAutoreload(TIM4,1150);
break;
case(11):
TIM_SetAutoreload(TIM4,1050);
break;
case(12):
TIM_SetAutoreload(TIM4,950);
break;
case(13):
TIM_SetAutoreload(TIM4,850);
break;
case(14):
TIM_SetAutoreload(TIM4,750);
break;
case(15):
TIM_SetAutoreload(TIM4,650);
break;
case(16):
TIM_SetAutoreload(TIM4,550);
break;
}
}
}
SysTick.c
#include"SysTick.h"
static__IOu32TimingDelay;
voidSysTick_Init(void)
{
if(SysTick_Config(SystemCoreClock/1000))
{
while
(1);
}
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;
}
voidDelay_us(__IOu32nTime)
{
TimingDelay=nTime;
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;
while(TimingDelay!
=0);
}
voidTimingDelay_Decrement(void)
{
if(TimingDelay!
=0x00)
{
TimingDelay--;
}
}
PWM.c
#include"PWM_OutPut.h"
//staticvoidTIM4_GPIO_Config(void)
voidTIM4_GPIO_Config(void)
{
GPIO_InitTypeDefGPIO_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_8);
}
voidNVIC_Configuration(void)
{
NVIC_InitTypeDefNVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//staticuint16_tTIM4_Mode_Config(uint16_ta)
voidTIM4_Mode_Config(void)
{
TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure;
TIM_OCInitTypeDefTIM_OCInitStructure;
TIM_TimeBaseStructure.TIM_Period=1;
TIM_TimeBaseStructure.TIM_Prescaler=36-1;
TIM_TimeBaseStructure.TIM_ClockDivision=0;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;/
TIM_TimeBaseInit(TIM4,&TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse=0;
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;
TIM_OC3Init(TIM4,&TIM_OCInitStructure);TIM_OC3PreloadConfig(TIM4,TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM4,ENABLE);
TIM_Cmd(TIM4,ENABLE);
//Delay_us(10);
//TIM_Cmd(TIM4,DISABLE);
}
//voidTIM4_PWM_Init(void)
//{
//TIM4_GPIO_Config();
//TIM4_Mode_Config();
//}