通信工程专业课程设计基于SEP3203的电子琴模型.docx
- 文档编号:6861020
- 上传时间:2023-01-11
- 格式:DOCX
- 页数:21
- 大小:274.19KB
通信工程专业课程设计基于SEP3203的电子琴模型.docx
《通信工程专业课程设计基于SEP3203的电子琴模型.docx》由会员分享,可在线阅读,更多相关《通信工程专业课程设计基于SEP3203的电子琴模型.docx(21页珍藏版)》请在冰豆网上搜索。
通信工程专业课程设计基于SEP3203的电子琴模型
目录
1、需求分析3
1.1基本功能3
1.2附加功能3
2、总体设计3
2.1基本功能使用的模块3
2.2加入附加功能之后的模块组成3
3、可行性分析4
4、详细设计与分工日志5
4.1输入:
5
4.1.*相关代码5
4.2发声器件7
4.2.1PWM波输出原理7
4.2.2控制寄存器(PWMC):
7
4.2.3采样寄存器(PWMS):
7
4.2.4周期寄存器(PWMP):
8
4.2.5计数器寄存器(PWMCNT):
8
4.2.6相关代码:
8
4.3LED显示10
4.3.1动态显示原理10
4.3.2定时器输出11
4.3.3相关寄存器11
4.3.4相关代码:
11
分工日志:
14
5、测试14
5.1曾经出现的问题与解决:
14
6、结论14
1、需求分析
1.1基本功能
想法来源:
例如电子琴之类的键盘乐器。
早期电子琴的原理是:
检测键盘上的按键是否按下,若按下,则相应的蜂鸣器发出声音。
这样,每个电子琴需要的蜂鸣器就很多。
但是,这样做很浪费资源。
所以,可以采用另一种方法,只用一个发声设备,每个按钮按下,对应加入一个相应的分量,将最终的波形输出来。
实际功能描述:
按不同的按键,发出不同的声音。
按下按钮之后,发出中断请求信号,CPU响应中断时,先检测按下的是哪一个按钮,然后控制发出相应PWM波,输出到蜂鸣器上,发出相应的声音。
最后,CPU继续循环执行主程序,等候下一个中断请求的到来。
1.2附加功能
想法来源:
调试过程中,需要查看按键的状态,需要查看是否正确检测到了按键,是否能够给出正确的键码,所以增加了这一功能。
功能描述:
利用LED数码管,显示按下的按键。
2、总体设计
2.1基本功能使用的模块
第一部分包括两个主要软件模块和两个外围的硬件模块:
2.2加入附加功能之后的模块组成
加入第二部分后的框图如下:
增加了一个新的程序模块和硬件模块。
程序运行的流程如下:
第二部分是对第一部分的完善和改进,但是在程序执行的流程中,仅仅在处理键码信息步骤,增加了“根据键码控制点亮数码管”这一部分。
3、可行性分析
该系统包含了输入、处理、输出三个部分。
其中,输入即为按键,使用矩阵键盘完成,实际的电子琴键盘含有更多的按键,但由于这仅仅是模型,所以,不需要使用那么多的按键。
处理部分是基于SEP3203的程序,通过输入的按键信息,修改寄存器的相应位,使得最终能够输出相应的PWM波,控制蜂鸣器响。
此外,还可以根据输入的按键信息,将输入的按键值显示在LED七段数码管上。
输出即为蜂鸣器和LED数码管,硬件电路已经在实验箱上连接好。
4、详细设计与分工日志
4.1输入:
4.1.1器件原理
采用矩阵键盘,矩阵键盘有两种驱动方式:
一种是行扫描法,另一种是高低电平翻转法。
这里采用了行扫描法。
包括两个步骤:
判断键盘中有无键按下:
将全部行线Y0-Y3置低电平,然后检测列线的状态。
只要有一列的电平为低,则表示键盘中有键被按下,而且闭合的键位于低电平线与4根行线相交叉的4个按键之中。
若所有列线均为高电平,则键盘中无键按下。
判断闭合键所在的位置:
在确认有键按下后,即可进入确定具体闭合键的过程。
其方法是:
依次将行线置为低电平,即在置某根行线为低电平时,其它线为高电平。
在确定某根行线位置为低电平后,再逐行检测各列线的电平状态。
若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。
4.1.2相关代码
键盘中断的调用:
voidkeyhandler(void)//键盘中断处理函数
{
mask_irq(INT_EXT15);//屏蔽键盘中断
//找到哪个键被按下,并打印
findkey();
unmask_irq(INT_EXT15);//打开键盘中断
//这里的键盘中断处理的不仅仅是打印键值,
//还包括了重置PWM波发出的寄存器.
}
寻找被按下的按键:
voidfindkey(void)
{
U32KEYTIME=0x100000;
U32KEYTIME2=0x10000;
U32dly=0;
U16intstatus;
U8col,row;
//清除garfield中断源
*(RP)PORTH_INTRCLR|=0x8;
//记录下中断状态值,用于判断行地址
intstatus=rucb(0x62);
wucb(0x60,0);//屏蔽UCB中断
if(!
(intstatus&KEY_ROW_MASK)){
wucb(0x60,KEY_ROW_MASK);
return;
}
wucb(0x62,KEY_ROW_MASK);
row=intstatus&KEY_ROW_MASK;
{
inti;
for(i=0;i if((row&(1< row=i; break; } } { //找到对应得列 U16line=KEY_COL_MSB; U16tmp; col=KEY_COL_NUM; while(col--){ //利用按键拉低相应得中断线 tmp=rucb(0x5a); tmp=((tmp|KEY_COL_MASK)&(~line)|KEY_ROW_MASK); wucb(0x5a,tmp); if((rucb(0x5a)&intstatus)==0) break; line>>=1; } } key_code=key_code_map[row][col];//利用行列取得键码 b=b_code_map[row][col]; l=l_code_map[row][col]; pwm(); led(); if(key_code){//排除无效按键 wucb(0x5a,0);//所有的列线置0 while(((rucb(0x5a))&intstatus)==0){ //按键还未抬起 inti; if(dly++==0){ for(i=0;i //在等待较长时间后,打印键值 DBG_Printf("key=%c\n",key_code); }else{ for(i=0;i DBG_Printf("key=%c\n",key_code); } //下一次的判断周期 wucb(0x5a,0x0); } } //再次ucb行清除中断状态,因为判断 wucb(0x62,KEY_ROW_MASK); wucb(0x60,KEY_ROW_MASK); } 4.2发声器件 4.2.1PWM波输出原理 发声器件即为蜂鸣器,通过控制输出的PWM波的波形来控制发出的声音。 PWM波包括两个参数: 频率和占空比。 控制频率,可以控制发出声音的频率;控制占空比,可以控制声音的响度。 在所用开发板GE01中,PWM模块中包含了2个PWM通道,彼此相互独立。 相关寄存器: 地址 寄存器名称 宽度 描述 复位值 0x1000c000 PWMC(TCTL) 32 PWM_1控制寄存器 0000_4000 0x1000c004 PWMS(TPRER) 32 PWM_1采样寄存器 0000_0000 0x1000c008 PWMP(TCMP) 32 PWM_1周期寄存器 0000_FFFE 0x1000c00c PWMCNT(TCR) 32 PWM_1计数器寄存器 0000_0000 4.2.2控制寄存器(PWMC): 高16位为保留位 bit15——中断请求状态(0=FIFO满、1=FIFO不满) bit14——中断请求使能(0=不使能(缺省)、1=PWM中断使能) bit13——FIFO有效状态(0=FIFO满、1=FIFO不满) bit12——PWM使能(0=PWM不使能、1=PWM使能) bit11-10——选择playback模式下采样被重放的次数(00=没重复,01=播放两次、10=重复3次(播放4次)、11=重复7次(播放8次)) bit9-0(PRESCALER)——用来提供分频因子的(prescaler+1),对系统时钟进行分频。 缺省值是0。 1=2分频、2=4分频… 4.2.3采样寄存器(PWMS): 高16位为保留位 Bit15-0——PWMS采样值PWM采样寄存器是FIFO的输入。 此值和一个自由计数的计数器比较。 当大于计数器值时PWM输出为高,反之输出为低。 4.2.4周期寄存器(PWMP): 高16位为保留位 bit15-0——Period值/定时值在tone模式时,其用于设置计数器的复位值。 计数器计数到此值就复位一次,PWM输出也相应翻转一次。 4.2.5计数器寄存器(PWMCNT): 高16位为保留位 bit15-0——当前的计数值它保存着自由计数的计数器的当前值。 依据上述寄存器各位的功能,通过合适的赋值便可以实现本实验所要求的基本功能。 4.2.6相关代码: 主函数: intmain(void) { if(E_OK! =ModulePwm()) DBG_Printf("errorinpwmlab\n"); DBG_Printf("successinpwmlab\n"); while (1); return1; } STATUS模块初始化 STATUSModulePwm(void) { /*systeminitialized*/ system_init(); /*固定周期发音实验*/ #ifdefFIX_LAB sample=0X5555DDDD; if(E_OK! =set_fix()) returnE_CTX; #endif /*设置周期发音实验*/ #ifdefUNFIX_LAB if(E_OK! =set_unfix(0Xf0)) returnE_CTX; #endif run_pwm(); returnE_OK; } STATUSset_fix(void) { #ifdefGE01MB *(RP)(PWM2_P)=0X0000FFFE; #else *(RP)(PWM1_P)=0X0000FFFE; #endif returnE_OK; } STATUSset_unfix(U8prescaler) { #ifdefGE01MB *(RP)(PWM2_C)=0X00001c00|(U32)prescaler; #else *(RP)(PWM1_C)=0X00001c00|(U32)prescaler; #endif returnE_OK; } voidrun_pwm(void) { #ifdefFIX_LAB #ifdefGE01MB *(RP)(PWM2_C)|=0X00001CFF; while (1) { *(RP)(PWM2_S)=0X0000FFFF&sample; *(RP)(PWM2_S)=sample>>16; } #else *(RP)(PWM1_C)|=0X00001CFF; while (1) { *(RP)(PWM1_S)=0X0000FFFF&sample; *(RP)(PWM1_S)=sample>>16; } #endif #endif #ifdefUNFIX_LAB #ifdefGE01MB *(RP)(PWM2_P)=0X00008ffe; #else *(RP)(PWM1_P)=0X00008ffe; #endif #endif return; } 4.3LED显示 4.3.1动态显示原理 图十二动态显示LED的连接 由图,六个数码管每个都有一个选择信号,当置“1”时,该数码管的相关段亮。 对于此动态显示电路,有六个数码管,使用的频率由定时器产生,为500Hz,即周期为2ms。 此外,将每个数码管相同的段连在一起到段数据线上。 在第一个2ms,第一个数码管允许点亮,同时,需要点亮的段置“1”,在这2ms内,只有第一个数码管亮。 在第二个2ms,第二个数码管允许点亮,同时,需要点亮的段置“1”,在这2ms内,只有第二个数码管亮……如此,每个2ms只有一个数码管亮,所以,不会相互影响,导致显示不清。 而且,由于每个数码管刷新的周期非常小,本实验中为12ms,小于人眼的分辨时间。 所以,看起来,好像同时亮了。 4.3.2定时器输出 如图,定时器用到的IO端口位置如下: TIMER是片内集成的32bit定时器,该模块共包括4个通道,每个通道包括一个32位计数器,以及一个加载计数寄存器。 计数器的重新加载、计数使能以及中断的产生受到控制寄存器的各个控制位的控制。 定时器的工作原理是: 首先要设定定时器的初值,然后启动定时器。 一旦启动,定时器就从初值开始累计增加或减小(在实验所用的芯片中是递减)。 每增加或减小一个数需要特定的时间,这个特定的时间是累加指令的机器周期,是由处理器的晶振的频率(本实验中晶振的频率是75MHz)决定的。 计数值从初值计至0时,TIMER模块发出中断,然后计数器跳至用户配置的值,重复递增或递减过程。 在中断寄存器允许的情况下处理器响应中断,通过中断服务程序执行特定的任务。 TIMER中的一个通道的功能结构如下图: TIMER有两种工作模式: 正常工作模式 TIMER在正常工作模式时,当通道使能后计数器锁存加载计数寄存器的值,然后在系统时钟的驱动下递减计数。 当计数到零时,产生一个计数到零的标志用于设置相应的中断标志位,若中断未被屏蔽则产生中断;同时,计数器重新锁存加载计数寄存器的值开始一个新的计数周期。 自由工作模式 TIMER在自由工作模式时,当通道使能后计数器锁存加载计数寄存器的值,然后在系统时钟的驱动下递减计数。 当计数到零时,产生一个计数到零的标志用于设置相应的中断标志位,若中断未被屏蔽则产生中断;同时,计数器加载数据32’HFFFFFFFF开始一个新的计数周期。 TIMER中四个通道的中断都可以通过各自的控制寄存器屏蔽。 任意一个通道计数完毕都会产生一个中断。 TIMER的中断输出是四个中断源的线或。 查询中断源有两种方法: (一)查询各个通道的中断屏蔽状态寄存器是否被置1; (二)查询TIMER中断屏蔽状态寄存器,看各个通道相应位是否被置1。 清除中断的方法也有两种: (一)读各个通道的中断状态清除寄存器,相应通道的中断会被清除; (二)读TIMER中断状态清除寄存器,所有通道的中断都会被清除。 查询到中断源后,如果不重新配置加载计数寄存器,计数器会按照原来的配置继续计数,直到计数完毕再发出中断。 如果要重新配置,清完中断后应该先将计数器关闭(disable),然后配置新的计数值,再将计数器打开(enable)。 4.3.3相关寄存器 地址 名称 读/写 宽度 描述 复位值 0x10003000 T1LCR R/W 32 通道1加载计数寄存器 32’b0 0x10003004 T1CCR R 32 通道1当前计数值寄存器 32’b0 0x10003008 T1CR W/R 32 通道1控制寄存器 32’b0 0x1000300C T1ISCR R 32 通道1中断状态清除寄存器 32’b0 0x10003010 T1IMSR R 32 通道1中断屏蔽状态寄存器 32’b0 0x10003014 T2LCR R/W 32 通道2加载计数寄存器 32’b0 0x10003018 T2CCR R 32 通道2当前计数值寄存器 32’b0 0x1000301C T2CR W/R 32 通道2控制寄存器 32’b0 0x10003020 T2ISCR R 32 通道2中断状态清除寄存器 32’b0 0x10003024 T2IMSR R 32 通道2中断屏蔽状态寄存器 32’b0 0x10003028 T3LCR R/W 32 通道3加载计数寄存器 32’b0 0x1000302C T3CCR R 32 通道3当前计数值寄存器 32’b0 0x10003030 T3CR W/R 32 通道3控制寄存器 32’b0 0x10003034 T3ISCR R 32 通道3中断状态清除寄存器 32’b0 0x10003038 T3IMSR R 32 通道3中断屏蔽状态寄存器 32’b0 0x1000303C T4LCR R/W 32 通道4加载计数寄存器 32’b0 0x10003040 T4CCR R 32 通道4当前计数值寄存器 32’b0 0x10003044 T4CR W/R 32 通道4控制寄存器 32’b0 0x10003048 T4ISCR R 32 通道4中断状态清除寄存器 32’b0 0x1000304C T4IMSR R 32 通道4中断屏蔽状态寄存器 32’b0 0x100030A0 TIMSR R 32 TIMER中断屏蔽状态寄存器 32’b0 0x100030A4 TISCR R 32 TIMER中断状态清除寄存器 32’b0 0x100030A8 TISR R 32 TIMER中断状态寄存器 32’b0 4.3.4相关代码: 调用LED显示: intled(void) { char*s1,*s2,*s3; s1="ThereisnoLEDonGE00\n"; s2="ErrorinLedlab! ! ! \n"; s3="SucceededinLedlab! ! ! \n"; #ifdefGE00 DBG_Printf(s1); return; #else if(E_OK! =ModuleLed()) DBG_Printf("ErrorinLedlab! ! ! \n"); //PRINT(s2); else//PRINT(s3); DBG_Printf("SucceededinLedlab! ! ! \n"); #endif //while (1); //returnE_OK; } LED显示模块: STATUSModuleLed(void) { /*systeminitialized*/ system_init();//系统初始化 /*GPIOinitialized*/ GPIO_Init(); /*ledlabbody*/ if(key_code=='1') { LedDisPlay(display1);//显示用户设定的内容 } if(key_code=='2') { LedDisPlay(display2); } if(key_code=='3') { LedDisPlay(display3); } if(key_code=='4') { LedDisPlay(display4);//显示用户设定的内容 } if(key_code=='5') { LedDisPlay(display5); } if(key_code=='6') { LedDisPlay(display6); } if(key_code=='7') { LedDisPlay(display7);//显示用户设定的内容 } if(key_code=='8') { LedDisPlay(display8); } if(key_code=='9') { LedDisPlay(display9); } returnE_OK; } LED显示程序: voidLedDisPlay(U8data[]) { U8*SegData; //十六进制数字翻译成7段译码值 Hex2Seg(data,SegData); LedOut(SegData,10);//在led上显示 } 翻译码值 VoidHex2Seg(U8hexdata[],U8*p) { inti; for(i=0;i<9;i++) { //将要显示的数值,通过查找7段译码表翻译成码值 *p++=SEGMENT[hexdata[i]]; } } LED输出 voidLedOut(U8data[],U32times) { intSegment_i,Bit_i,i; U8Segment_Data; U8tempData; for(i=0;i { for(Bit_i=0;Bit_i<8;Bit_i++) //依次串行导入八个led的显示内容 { //获得一个led显示的码值 Segment_Data=*(data+Bit_i); //将7段译码值依次串行输入到GPIO口中 for(Segment_i=0;Segment_i<8;Segment_i++) { //得到一段发光管的译码值 tempData=(Segment_Data>>Segment_i)&0x1; //写入74HC595的输入端,同时拉低PD3 *(RP)PORTD_
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 通信工程 专业课程 设计 基于 SEP3203 电子琴 模型
![提示](https://static.bdocx.com/images/bang_tan.gif)