msp430实验与程序.docx
《msp430实验与程序.docx》由会员分享,可在线阅读,更多相关《msp430实验与程序.docx(22页珍藏版)》请在冰豆网上搜索。
msp430实验与程序
[实验目的]
学会使用ADC12,DMA,TIMERB模块了解语音采集,以及PWM-DA工作原理。
[实验要求]
1、编程要求:
IAR4.11BC语言。
2、实现功能:
录/放音。
3、实验现象:
可进行17秒左右录/放音。
[实验原理]
该实验的基本原理是:
利用MIC将声音信号转换成模拟的电信号,通过功放将该信号放大,
利用ADC12进行采集、转换成数字量,并且通过DMA直接将转换数据送入FLASH中进行存
放。
在存放过程中通过LCD进行一定的信息提示,这就完成了整个录音过程。
放音过程中,则是通过提取存放在FLASH中的数据,通过计算得出PWM波占空比,利用
TIMERB输出PWM波,再通过1阶带通滤波器进行滤波,模拟出采集进来的模拟电信号,通
过语音输出功放TPA301进行放大送给耳机输出接口。
因此整个的过程的基本框图如图4-4:
图4-4语音基本框图
在该实验中最需要注意的是,采样频率的设置。
根据奈奎斯特采样定理,采样频率必须大于
被采样信号中最大频率分量频率的两倍,否则不能从信号采样中回复原始信号。
由于人耳听觉
范围通常为20Hz到20KHz,如果要将所有声音都做一个非常精确的记录以及播___________放,很显然MCU
的速度上无法支持。
但是做一个相对清晰语音记录的话,则采样频率仅仅需要11KHz(电话音
质)。
为了采样数据的存放的方便,也由于采样频率本身就被限制在了11KHz,因此ADC12在
进行转换的时候精度要求就不那么高了,通过设置我们将ADC12DC的转换精度改成8位。
则
每次进行采样的数据仅仅就是8位,一个字节而已。
在采样的时候进行处理将两次采样的数据
整合成一个字,存入FLAH中。
而MSP430F5438系列有256K的FLASHROM,扣去一些预留
空间,则有192K的空间来进行语音数据的存取。
则总共可记录语音时间:
T=192Kbyte/(11K/S*1byte)=17S
电信
号
电信
ADC号
FLAS
H
TIMEB
PWM波
电信
号
DMATB带通
1
第131页共179页
如果采样12位精度的AD转换,则时间会大大减少而音质并不会因此而有太大的提高。
因为1
次转换要占用两个字节,故可记录语音时间:
T=192Kbyte/(11K/S*2byte)=8.5S
利用PWM-DA输出,其实就是利用TIMERB进行一个占空比不断变化的PWM波的输出。
占空比的变化频率就是在采集模拟电信号的采样频率。
而输出模拟电压值Vout的计算公式如下
Vout=Vcc*dutycycle(占空比)
而利用TB的PWM产生模式产生的PWM波占空比的计算公式则是:
Dutycycle=CCR4/CCR0
换句话说输出电压值由CCR4与CCR0的比值决定,由于存放在FLASH中的数据均为8位
数据,因此只需要将CCR0即PWM波周期设置为256个TBCLK的倍数即可,考虑到MCU需
要响应按键中断以及进行数据的解析,故将PWM波周期设置为2倍的256个TBCLK。
因此在每
次将FLASH中的数值解析出来后,直接乘以2放入CCR4即可产生对应电压值所需占空比。
[程序流程]
主程序
1
第132页共179页
按键中断子程序
ADC12中断子程序
TB中断子程序
1
第133页共179页
[实验步骤]
1.由于在C语言默认情况下IAR编译器分配给指针变量两个字节的空间,因此只能访问
64K以内的地址,因此对于64K以外的存储空间是不能进行访问的,由于本程序要利用大于64K
外部空间存储录音数据因此需要进行如下设置,增加指针变量的分配空间:
A.在工程名上点击右键,选择Option出现界面如图4-2。
B.在出现Option界面datamodel中选择Large。
C.点击OK。
1
第134页共179页
图4-2扩展空间访问界面
2.根据LCD屏上显示的提示,进行操作即可进行相应的录音、放音、暂停等操作。
[范例路径]
资料光盘/SourceCode//综合程序/语音处理程序/code/LSD-TEST430F5438-01_V2.1_sound.c。
[范例程序]
*注意由于本程序调用上个实验LCD模块程序,因此这部分程序在这里没有写出。
/*************************************************************************
**
**文件名:
LSD-TEST430F5438-01_V2.1_sound.c
**工作环境:
IAR4.11B
**作者:
**生成日期:
**功能:
实现语音的录放
**相关文件:
**修改日志:
**************************************************************************/
1
第135页共179页
#include
#include"lcdoperate.h"
#definerecordmod1
#defineplaymod2
#definer_pausemod3
#definep_pausemod4
#definestopmod0
externuchardis[];
unsignedcharworkmod=0,restartflag=0;
longinta,samplenum,playnum1,i;
intsampleresult,playnum,data[2];
int*audiodata;
voidInit_Clk(void);
voidflashEraseBank(unsignedlongFarPtr);
voidrecord(void);
voidplay(void);
voidSeg_Erase(void);
voidwrite_Flash(intvalue,longaddress);
voidsysteminit()
{
WDTCTL=WDTPW+WDTHOLD;//停止看门狗
/****************************设置不用的IO口************************************/
PADIR=0xFFFF;
PAOUT=0;
PASEL=0;
PBDIR=0xFFFF;
PBOUT=0;
1
第136页共179页
PBSEL=0;
PCDIR=0xFFFF;
PCOUT=0;
PCSEL=0;
PDDIR=0xFFFF;
PDOUT=0;
PDSEL=0;
PEDIR=0xFFFF;
PEOUT=0;
PESEL=0;
P11DIR=0xFF;
P11OUT=0;
P11SEL=0;
PJDIR=0xFF;
PJOUT=0;
Init_Clk();//初始化系统时钟
}
voidmain(void)
{
systeminit();//系统初始化
P6OUT|=BIT6;
P6OUT&=~BIT6;
P9OUT|=_CS;
P8OUT|=_RST;
P9OUT|=A0;
P9OUT|=SCLK;
P9OUT|=SID;
initLCDM();//LCD初始化
ClearRAM();
/******************************按键IO口设置************************************/
1
第137页共179页
P2REN|=BIT6+BIT7;
P2OUT|=BIT6+BIT7;
P2DIR&=~(BIT6+BIT7);
P2IES|=BIT6+BIT7;
P2IE|=BIT6+BIT7;
P2IFG&=~(BIT6+BIT7);
/******************************工作状态显示************************************/
do
{
_DINT();
switch(workmod)
{
casestopmod:
{
/****************************STOPMOD***************************/
ClearRAM();
ucharshuru1[]={"利尔达公司"};
zimo(shuru1);
PrintGB(26,0,dis);//利尔达公司
ucharshuru2[]={"录音"};
zimo(shuru2);
PrintGB(4,54,dis);//录音
ucharshuru3[]={"播放"};
zimo(shuru3);
PrintGB(93,54,dis);//播放
/**************************************************************/
}
break;
caserecordmod:
{
/****************************RECORDMOD*************************/
ClearRAM();
ucharshuru4[]={"录音中"};
1
第138页共179页
zimo(shuru4);
PrintGB(40,0,dis);//录音中
ucharshuru5[]={"暂停"};
zimo(shuru5);
PrintGB(4,54,dis);//暂停
ucharshuru6[]={"结束"};
zimo(shuru6);
PrintGB(93,54,dis);//结束
if(restartflag==0)
record();
/**************************************************************/
}
break;
caser_pausemod:
{
/****************************R_PAUSEMOD************************/
ClearRAM();
ucharshuru7[]={"暂停中"};
zimo(shuru7);
PrintGB(40,0,dis);//暂停中
ucharshuru2[]={"录音"};
zimo(shuru2);
PrintGB(4,54,dis);//录音
/**************************************************************/
}
break;
casep_pausemod:
{
/****************************P_PAUSEMOD************************/
ClearRAM();
ucharshuru7[]={"暂停中"};
zimo(shuru7);
PrintGB(40,0,dis);//暂停中
ucharshuru3[]={"播放___________"};
zimo(shuru3);
1
第139页共179页
PrintGB(4,54,dis);//播放
/**************************************************************/
}
break;
caseplaymod:
{
/******************************PLAYMOD*************************/
ClearRAM();
ucharshuru8[]={"播放中"};
zimo(shuru8);
PrintGB(40,0,dis);//播放中
ucharshuru5[]={"暂停"};
zimo(shuru5);
PrintGB(4,54,dis);//暂停
ucharshuru6[]={"结束"};
zimo(shuru6);
PrintGB(93,54,dis);//结束
if(restartflag==0)
play();
/**************************************************************/
}
break;
}
TBCCTL4&=~(CCIFG);
_BIS_SR(CPUOFF+GIE);
}
while
(1);
}
/******************************************************************************/
/**程序名:
IO口中断-按键子程**/
/**输入参数:
无**/
/**输出参数:
无**/
/**作用:
根据按键改变工作状态**/
/******************************************************************************/
1
第140页共179页
#pragmavector=PORT2_VECTOR
__interruptvoidKEY(void)
{
for(inti=5000;i>0;i--);//延时消抖
if((P2IN&0XC0)==0XC0)
{
if((P2IFG&BIT6)==BIT6)//左键
{
if(workmod==stopmod)//当前工作模式为停
止模式
{
workmod=recordmod;//进入录音模式
LPM0_EXIT;
}
elseif(workmod==recordmod)//当前工作模式为录
音模式
{
TBCTL&=~(MC0+MC1);
workmod=r_pausemod;//进入录音暂停模式
LPM0_EXIT;
}
elseif(workmod==r_pausemod)//当前工作模式为录
音暂停模式
{
workmod=recordmod;//进入录音模式
TBCTL|=MC__UP;
restartflag=1;//开始录音标志置一
LPM0_EXIT;
}
elseif(workmod==playmod)//当前工作模式为播
放模式
{
TBCTL&=~(MC0+MC1);
workmod=p_pausemod;//进入播放停止模式
1
第141页共179页
LPM0_EXIT;
}
elseif(workmod==p_pausemod)//当前工作模式为播
放暂停模式
{
TBCTL|=MC__UP;
workmod=playmod;//进入播放模式
restartflag=1;
LPM0_EXIT;
}
}
if((P2IFG&BIT7)==BIT7)//右键
{
if(workmod==stopmod)//当前工作状态为停
止模式
{
workmod=playmod;//进入播放模式
LPM0_EXIT;
}
elseif((workmod==playmod)||(workmod==p_pausemod))
//当前工作模式为播放/播放停止模式
{
TBCTL|=MC__UP;
playnum1=65536*3;//强制停止
}
elseif((workmod==recordmod)||(workmod==r_pausemod))
//当前工作模式为录音/播放录音模式
{
TBCTL|=MC__UP;
a=65536*3;//强制停止
}
}
P2IFG&=~(BIT6+BIT7);
}
while((P2IN&0XC0)!
=0XC0);
1
第142页共179页
_NOP();
while((P2IN&0XC0)!
=0XC0);
}
/******************************************************************************/
/**程序名:
初始化录音子程**/
/**输入参数:
无**/
/**输出参数:
无**/
/**作用:
初始化录音模块设置**/
/******************************************************************************/
voidrecord(void)
{
_DINT();//全局中断关闭
Init_Clk();//初始化时钟设置12M
/*******************************DMA设置***************************************/
DMACTL0=DMA0TSEL_0;//DMA0通道软件触发
DMA0CTL=DMADT_4+DMADSTINCR_3;//重复单次传输字传输
目的地址加一
DMA0SA=(long*)&sampleresult;//源地址&sampleresult
DMA0DA=(long*)0x10000;//初始目的地址0x10000
DMA0SZ=8;//初始传输数据数8
/*******************************ADC12设置*************************************/
P6SEL|=BIT5;//ADC12端口初始化
P6DIR|=BIT4;
P6REN|=BIT4;
P6DS|=BIT4;
P6OUT|=BIT4;
ADC12CTL2=ADC12RES_0;//8位ADC
ADC12CTL1=ADC12SSEL_3+ADC12CONSEQ_2+ADC12SHS_3+ADC12SHP+ADC12REF2_5V;
//ADC12CLK=SMCLK=12M重复单通道转换TB1触发
ADC12CTL0=ADC12ON+ADC12CSTARTADD_0+ADC12SHT02;//ADC12内核开启初始
化通道0
ADC12MCTL0=ADC12INCH_5+ADC12SREF_0;//ADC12采样通道5参
考电压VCCVSS
ADC12IE=BIT0;//通道0中断使能
ADC12CTL0|=ADC12ENC;//转换使能
1
第143页共179页
/*******************************TIMERB设置***********************************/
TBCTL|=TBSSEL__SMCLK;//TB时钟源SMCLK=12M
TBCCR0=1023;//采样频率
12M/1024=11.718K
TBCCR1=923;//100个CLK进行转换
以及DMA数据转移
TBCCTL1|=OUTMOD_7+CCIE;//TBCCR1PWM输出中断
使能
/*******************************FLASH空间擦除*********************************/
flashEraseBank(0x10000);
flashEraseBank(0x20000);
flashEraseBank(0x30000);
/*******************************DMAFLASH空间写入准备*************************/
FCTL3=FWKEY;
FCTL1=FWKEY+BLKWRT;
TBCTL|=MC__UP;//TB使能
DMA0CTL|=DMAEN;//DMA使能
//_EINT();
}
/******************************************************************************/
/**程序名:
初始化录音播放子程**/
/**输入参数:
无**/
/**输出参数:
无**/
/**作用:
初始化录音播放模块设置**/
/******************************************************************************/
voidplay(void)
{
_DINT();//全局中断关闭
Init_Clk();//时钟初始化12M
audiodata=(int*)0x10000;//语音数据存放初始
地址
P6DIR|=BIT6;//语音输出运放使能
P6OUT&=~BIT6;
P4DIR|=BIT4;//PWM输出端口初始化
1
第144页共179页
设置
P4SEL|=BIT4;
TBCTL=TBSSEL__SMCLK+TBIE+TBCLR;//TB时钟源SMCLK=12M
溢出中断使能
TBCCR0=511;//PWM频率
12M/(256*2)=23.437k
TBCCR4=256;//初始化占空比50%
TBCCTL4=OUTMOD_7+CLLD_1;//PWM输出溢出后改
变TBCCR4数值
playnum1=0;
TBCTL|=MC__UP;//PWM输出初始化
//_EINT();
}
/******************************************************************************/
/**程序名:
ADC12中断-采样子程**/
/**输入参数:
无**/
/**输出参数:
无**/
/**作用:
采样输入声音电压**/
/******************************************************************************/
#pragmavector=ADC12_VECTOR
__interruptvoidADC12(void)
{
if((++samplenum)%2==1)//奇数次采样结果
暂时存放
{
sampleresult=ADC12MEM0