基于C8051F360语音存储回放系统源码.docx

上传人:b****5 文档编号:14638137 上传时间:2023-06-25 格式:DOCX 页数:25 大小:116.58KB
下载 相关 举报
基于C8051F360语音存储回放系统源码.docx_第1页
第1页 / 共25页
基于C8051F360语音存储回放系统源码.docx_第2页
第2页 / 共25页
基于C8051F360语音存储回放系统源码.docx_第3页
第3页 / 共25页
基于C8051F360语音存储回放系统源码.docx_第4页
第4页 / 共25页
基于C8051F360语音存储回放系统源码.docx_第5页
第5页 / 共25页
基于C8051F360语音存储回放系统源码.docx_第6页
第6页 / 共25页
基于C8051F360语音存储回放系统源码.docx_第7页
第7页 / 共25页
基于C8051F360语音存储回放系统源码.docx_第8页
第8页 / 共25页
基于C8051F360语音存储回放系统源码.docx_第9页
第9页 / 共25页
基于C8051F360语音存储回放系统源码.docx_第10页
第10页 / 共25页
基于C8051F360语音存储回放系统源码.docx_第11页
第11页 / 共25页
基于C8051F360语音存储回放系统源码.docx_第12页
第12页 / 共25页
基于C8051F360语音存储回放系统源码.docx_第13页
第13页 / 共25页
基于C8051F360语音存储回放系统源码.docx_第14页
第14页 / 共25页
基于C8051F360语音存储回放系统源码.docx_第15页
第15页 / 共25页
基于C8051F360语音存储回放系统源码.docx_第16页
第16页 / 共25页
基于C8051F360语音存储回放系统源码.docx_第17页
第17页 / 共25页
基于C8051F360语音存储回放系统源码.docx_第18页
第18页 / 共25页
基于C8051F360语音存储回放系统源码.docx_第19页
第19页 / 共25页
基于C8051F360语音存储回放系统源码.docx_第20页
第20页 / 共25页
亲,该文档总共25页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

基于C8051F360语音存储回放系统源码.docx

《基于C8051F360语音存储回放系统源码.docx》由会员分享,可在线阅读,更多相关《基于C8051F360语音存储回放系统源码.docx(25页珍藏版)》请在冰点文库上搜索。

基于C8051F360语音存储回放系统源码.docx

基于C8051F360语音存储回放系统源码

语音存储回放——系统软件设计

 

班级:

电科0801姓名:

学号:

语音存储回放系统软件的基本功能是通过按键控制系统实现录音与放音。

录音(语音的存储)时,采集语音信号并将采集的数据存入M25P16中;放音(语音的回放)时,从M25P16中读取数据送DAC。

一、设计题目

设计并制作一个数字化语音存储与回放系统,设计要求:

1前置放大器增益可调,功率放大器输出功率≥0.5W。

2带通滤波器:

通带为300Hz~3.4kHz。

3ADC:

采样频率fs=8kHz,字长8位。

4语音录放时间≥60s。

5DAC:

变换频率fc=8kHz,字长8位。

6回放语音质量良好。

7采用语音压缩算法,增加录放时间。

 

在建立系统软件的框架时,应考虑以下几个问题。

⑴人机接口的功能设计

语音存储与回放系统的人机接口功能比较简单,按照功能要求要求只需要3个功能键:

“擦除”键、“录音”键、“放音”键。

“擦除”键有效时,单片机调用擦除子程序将M25P16中数据整片擦除,以便进行录音操作。

“录音”键有效时,单片机以8kHz的频率采集语音信号,并将数据写入M25P16中。

当“放音”键有效时,单片机通过读数据子程序从M25P16中取出数据送入DAC输出语音信号。

语音存储与回放系统在工作时需要提示一些简单的信息,入显示三种工作状态:

录音状态、放音状态、擦出状态,另外,需要显示录音和放音的时间。

根据设计方案,语音存储与回放系统的单片机子系统采用并行总线单片机最小系统,人机接口采用LCD模块和矩阵式键盘。

根据键盘的工作原理,当键有效时,单片机通过执行INT0中断服务程序读取键值。

单片机根据读取的键值,执行相应的键处理程序。

这里需要考虑的是,键处理程序放在INT0中断服务程序中还是放在主程序中。

如果将键处理程序放在INT0中断服务程序中,则单片机在执行键处理程序时,无法响应同级别的中断,影响程序的效率和实时性。

因此,将键处理程序放在主程序中,INT0中断服务程序只需要读取键值并设置一个键有效标志。

主程序则不断循环检测键有效标志,如键有效标志置1,则根据键执行响应的键处理程序。

每次检测到键有效标志置1后,应立即将键有效标志清零,以免键处理程序重复执行。

⑵M25P16的读写方案设计

由于对M25P16写一字节数据和写一页(256字节)数据所需编程时间是相同的,约需0.64ms。

语音存储与回放系统的数据采样频率为8kHz,采样周期为u0.125ms。

如果每采集一字节数据就立即写入M25P16,显然M25P16在写操作时间上是不能满足要求的。

因此,在程序设计中,采集的语音数据先存放在C8051F360内部的XRAM中,待采满256字节数据,调用M25P16页编程子程序将数据写入M25P16。

由于采集256字节数据需要32ms的时间,可以满足M25P16对写操作时间的需求。

(3)A/D和D/A转化器的控制

为了精确控制采样频率,DAc由定时器2控制,在定时器2中断服务程序中向DAC送一字节数据,将数字化的语音信号转化成模拟信号。

ADC由定时器3溢出启动A/D转化(注意需要禁止定时器3溢出中断),A/D转化结束后产生中断,通过ADC中断服务程序读取采样值。

为了提高定时精确,定时器2和定时器3均采用16为自动重装工作方式。

(4)C8051F360单片机内部资源的使用

在语音存储回放系统中,需要使用C8051F360单片机的ADC、DAC、SPI0、XRAM、

定时器等资源。

由于C8051F360单片机具有丰富的片上外设,除了人机接口和大容量的存储器外,不需要扩展其他外部设备,大大简化了系统硬件电路的设计。

根据上述分析,语音存储与回放系统的软件框架由主程序、键盘中断服务程序、定时器2服务程序、ADC中断服务程序组成。

1.主程序流程图

主程序的流程图如图。

在主程序中首先执行C8051F360单片机和M25P16的初始化程序。

C8051F360单片机的初始化包括I/O口初始化、内部振荡器初始化、ADC初始化、DAC初始化、SPI0初始化、定时器初始化、中断系统初始化、M25P16的初始化主要目的是通过写状态字消除M25P16的写保护。

主程序实际上是一个循环程序,不断的检测有无按键输入。

有键输入时,根据键值做相应的处理。

主程序中设置了两个工作状态:

录音状态和放音状态,分别用两个标志位来表示。

在录音状态下,数据每采集满256个字节,就调用页编程子程序,将XRAM中的数据写入M25P16中。

在放音状态下,每转化完成256个字节的数据,就再从M25P16中读取下一页数据。

在录音和放音的过程中,还需要显示录音和放音的时间。

由于采样频率是固定的,M25P16的存储地址的变化是与录音与放音时间是相关的,因此,可以用M25P16的存储地址换算后可得录音和放音的时间。

2.键盘中断(INT0)服务程序流程图

当有键按下时,键盘接口电路产生INT0中断信号。

键盘中断服务程序的功能十分简单:

读取4位键值,置键有效标志位。

其流程图如图所示:

3.A/D中断服务程序流程图

A/D转化的启动通过定时器3的溢出实现。

当A/D转化结束以后,启动一次中断。

在A/D转化中断服务程序中首先判断是否处于录音状态,如果出于录音状态,将高8位数据(ADC0H)存入C8051F360单片机内部XRAM。

注意,ADC中断标志必须软件清零。

A/D中断服务程序流程图如图所示:

4.定时器T2终端服务流程图

定时器T2每中断一次,单片机向DAC写一字节的语音数据。

根据8kHz的采样频率,可以计算T2定时常数为FF83H(0.125ms)。

由于定时时间很短,定时器采用16位自动加载工作方式,既提高了定时精度,又简化了程序设计。

T2中断服务程序流程图如图

在DAC中断服务程序流程图和定时器T2中断服务程序流程图中,需要单片机对XRAM的读写操作。

单片机对XRAM的读写有16位MOVX指令和8位MOVX指令。

由于在程序中只需要对256字节的XRAM操作,因此,采用8位MOVX指令可大大简化程序设计。

附件:

程序

#include"C8051F360.h"

#defineuncharunsignedchar

#defineRCOMADDR0XC00A

#defineWCOMADDR0XC008

#defineWDATADDR0XC009

#defineRDATADDR0XC00B

#defineKEY_READ0XC00C

uncharkeycode,keysign,sh_time,time_sign;

unsignedlongADDR=0x0000;

xdatauncharData_byte[256];

uncharcodefiguer[]=

{'0','1','2','3','4','5','6','7','8','9',':

'};

/////////////////////////端口初始化

voidport_io_init(void)

{

SFRPAGE=0x0f;

P0MDIN=0xe7;////P0.3--P0.4设置为模拟输入

P0MDOUT=0x83;////P0.0,P0.7,P0.1推拉式输出

P0SKIP=0xf9;////P0.0,P0.3--P0.7被交叉开关跳过

P1MDIN=0xff;

P1MDOUT=0xff;

P1SKIP=0xff;

P2MDIN=0xfe;///P2.0模拟输入,漏极开路输出

P2MDOUT=0xfe;

P2SKIP=0xe1;///P2.1--P2.4不被交叉开关跳过

P3MDIN=0xff;

P3MDOUT=0xff;

P3SKIP=0xfe;

P4MDOUT=0xff;

XBR0=0x03;///UART连接到端口引脚,使能SPI总线

XBR1=0xc0;

SFRPAGE=0x00;

return;

}

/////////////////////////内部振荡器初始化

voidosc_init(void)

{

SFRPAGE=0x0f;

OSCICL=OSCICL+4;

OSCICN=0xc2;

OSCXCN=0x00;

CLKSEL=0x00;

SFRPAGE=0x00;

return;

}

/////////////////////////外部数据存储器初始化

voidxram_init(void)

{

SFRPAGE=0x0f;

EMI0CF=0x07;

SFRPAGE=0x00;

return;

}

/////////////////////////外部中断初始化

voidint01_init(void)

{

IT01CF=0x65;

IT0=1;

IT1=1;

EX0=1;

EX1=0;

return;

}

/////////////////////////定时器初始化

voidtimer_init(void)

{

TMOD=0X11;

CKCON=0X00;

TH0=(65536-10000)/256;///T0定时10Ms

TL0=(65536-10000)%256;

//TL1=0X0C;

//TH1=0XFE;

TMR2CN=0X04;

TMR2RLL=0X83;///T3,T3定时0.125ms

TMR2RLH=0XFF;

TMR3CN=0X0C;

TMR3RLL=0X83;

TMR3RLH=0XFF;

//TR0=1;

//TR1=1;

return;

}

/////////////////////////中断系统初始化

voidinterrupt_init(void)

{

EX0=1;///允许INT0中断

PX0=1;///INT0高优先级

ET0=1;

//ET1=1;

ES0=1;

//IE0=0;

EA=1;

return;

}

/////////////////////////PCA初始化

voidpca_init(void)

{

PCA0CN=0X40;

return;

}

/////////////////////////异步串口通信接口初始化

voiduar_init(void)

{

SCON0=0X00;

return;

}

/////////////////////////延时子程序

voiddelay(unsignedintt)

{unsignedinti,j;

for(i=0;i

for(j=0;j<100;j++)

return;

}

/////////////////////////检查BF标志位子程序

voidCheck_Lcd()

{

unchartemp=0x00;

uncharxdata*addr;

while

(1)

{

addr=RCOMADDR;

temp=*addr;

temp&=0x80;

if(temp==0x00)break;

}

return;

}

/////////////////////////LCD写指令子程序

voidWrite_Com(uncharn)

{

uncharxdata*addr;

Check_Lcd();

addr=WCOMADDR;

*addr=n;

return;

}

/////////////////////////LCD写数据子程序

voidWrite_Data(uncharm)

{

uncharxdata*addr;

Check_Lcd();

addr=WDATADDR;

*addr=m;

return;

}

/////////////////////////LCD初始化

voidLCD_Init()

{

Write_Com(0x30);

Write_Com(0x01);

Write_Com(0x0c);

return;

}

////////////////////////显示汉字子程序

voidDisp_Han(uncharcode*a,uncharm,unchark)

{

unchardat,i,j,length;

length=k/2;

Write_Com(m);

for(i=0;i

{

j=2*i;

dat=a[j];

Write_Data(dat);

dat=a[j+1];

Write_Data(dat);

}

return;

}

//SPI初始化

voidSPI_Init()

{

SPI0CFG=0x70;

SPI0CN=0x0d;

SPI0CKR=0x02;

}

///2、M25P16读写

voidCheck_SPIF()

{

while(SPIF!

=1);//等待完成数据发送

SPIF=0;

}

//读取状态字,查看是否擦写完成

voidCheck_Busy()

{

unsignedcharmem_status=0x01;

NSSMD0=0;

SPI0DAT=0x05;//送读状态寄存器命令

Check_SPIF();

while(mem_status==0x01)

{

SPI0DAT=0xff;//查看

Check_SPIF();

mem_status=SPI0DAT&0x01;//检查spi0完成数据发

}

NSSMD0=1;//禁止M25P16;

}

voidFlash_Init()

{

NSSMD0=0;//选通M25P16

SPI0DAT=0x06;//送写允许命令

Check_SPIF();

NSSMD0=1;

NSSMD0=0;

SPI0DAT=0x01;//送写状态字命令

Check_SPIF();

SPI0DAT=0x00;//送状态字,将BP2——BP0置0

Check_SPIF();

NSSMD0=1;

Check_Busy();

}

voidErase_All()

{

NSSMD0=0;//选通M25P16

SPI0DAT=0x06;//送写允许命令

Check_SPIF();

NSSMD0=1;

NSSMD0=0;

SPI0DAT=0xc7;//送整片擦除命令

Check_SPIF();

NSSMD0=1;

Check_Busy();

}

voidPage_Program(unsignedlongADDR)

{

unsignedinti;

unsignedchartemp[3];

NSSMD0=0;//选通M25P16

SPI0DAT=0x06;//送写允许命令

Check_SPIF();

NSSMD0=1;

NSSMD0=0;

SPI0DAT=0x02;//送页编程命令

Check_SPIF();

for(i=0;i<3;i++)

{

temp[i]=ADDR>>(8*(2-i));

SPI0DAT=temp[i];

Check_SPIF();

}

for(i=0;i<256;i++)

{

SPI0DAT=Data_byte[i];

Check_SPIF();

}

NSSMD0=1;

}

voidRead_Flash(unsignedlongADDR)

{

unsignedinti;

unsignedchartemp[3];

NSSMD0=0;//选通M25P16

SPI0DAT=0x06;//送写允许命令

Check_SPIF();

NSSMD0=1;

NSSMD0=0;

SPI0DAT=0x03;//送读数据命令

Check_SPIF();

for(i=0;i<3;i++)

{

temp[i]=ADDR>>(8*(2-i));

SPI0DAT=temp[i];

Check_SPIF();

}

for(i=0;i<256;i++)

{

SPI0DAT=0xff;

Check_SPIF();

Data_byte[i]=SPI0DAT;

}

NSSMD0=1;

}

////AD初始化

voidAD_Program()

{

SFRPAGE=0X0F;

REF0CN=0x08;

AMX0P=0x08;

AMX0N=0x1F;

///ADC0CF=0x14;

ADC0CF=0x2c;

ADC0CN=0x85;

SFRPAGE=0X00;

}

/////DA初始化

voidDA_Program()

{

SFRPAGE=0X0F;

IDA0CN=0xA2;

SFRPAGE=0X00;

}

///////////////////////总初始化

voiddevice_init(void)

{

port_io_init();

osc_init();

xram_init();

int01_init();

timer_init();

interrupt_init();

pca_init();

uar_init();

SPI_Init();

///Flash_Init();

AD_Program();///AD初始化

DA_Program();///DA初始化

return;

}

//////////时间显示

voidSH_time(unsignedintn)

{

uncharfiguer1;

unsignedinta,b,c,d,e;

Write_Com(0x03);

///Write_Com(0x01);

Write_Com(0x0c);

Write_Com(0x8A);

a=n;

b=a/60;

c=a%60;

d=c/10;

e=c%10;

figuer1=figuer[0];

Write_Data(figuer1);

figuer1=figuer[b];

Write_Data(figuer1);

figuer1=figuer[10];

Write_Data(figuer1);

figuer1=figuer[d];

Write_Data(figuer1);

figuer1=figuer[e];

Write_Data(figuer1);

delay(10);

return;

}

///////////////////////主函数

voidmain()

{

unsignedintn;

uncharcodehanzi1[]="语音存储回放";

uncharcodehanzi2[]="按K0开始录音";

uncharcodehanzi3[]="按K1开始放音";

uncharcodehanzi4[]="按K2擦除";

uncharcodehanzi7[]="正在录音";

uncharcodehanzi8[]="正在放音";

uncharcodehanzi9[]="正在擦除";

PCA0MD=0X00;///////////////////关看门狗

device_init();

while

(1)

{

LCD_Init();

Disp_Han(hanzi1,0x81,0x0c);

Disp_Han(hanzi2,0x91,0x0c);

Disp_Han(hanzi3,0x89,0x0c);

Disp_Han(hanzi4,0x99,0x08);

while(keysign==0);

if(keysign==1)

{

sh_time=0;

n=300;

keysign=0;

switch(keycode)

{

case0x00:

{

LCD_Init();

Disp_Han(hanzi7,0x92,0x08);

ADDR=0;

sh_time=1;

EIE1=0X80;///开定时器3中断

break;

}

case0x01:

{

LCD_Init();

Disp_Han(hanzi8,0x92,0x08);

ADDR=0;

Read_Flash(ADDR);

ADDR+=0x00ff;

sh_time=1;

ET2=1;///开定时器2中断

break;

}

case0x02:

{

LCD_Init();

Disp_Han(hanzi9,0x92,0x08);

Erase_All();

break;

}

default:

break;

}

while(sh_time==1)

{

TR0=1;

SH_time(n);

if(n<=0)

{

sh_time=0;

TR0=0;

ET2=0;

EIE1=0X00;

time_sign=1;

}

while(time_sign!

=1);

n--;

time_sign=0;

}

}

}

}

voidReadKey()interrupt0

{

uncharxdata*addr;

IE0=0;

TR0=0;

ET2=0;

EIE1=0X00;

addr=KEY_READ;

P1=*addr;

P1&=0x0f;

keycode=P1;

keysign=1;

time_sign=1;

sh_time=0;

}

voidADC0_ISR(void)interrupt14

{

staticunchari=0;

TMR3CN=0X06;

while(AD0BUSY==1);

AD0INT=0;

Data_byte[i]=ADC0H;

if(i>=255)

{

i=0;

Page_Program(ADDR);

ADDR+=0x00ff;

if(ADDR>0xffffff)

{

ADDR=0;

EIE1=0X00;

sh_time=0;

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > IT计算机 > 电脑基础知识

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2