ISD1700语音芯片SPI使用总结.docx
- 文档编号:23636397
- 上传时间:2023-05-19
- 格式:DOCX
- 页数:17
- 大小:20.67KB
ISD1700语音芯片SPI使用总结.docx
《ISD1700语音芯片SPI使用总结.docx》由会员分享,可在线阅读,更多相关《ISD1700语音芯片SPI使用总结.docx(17页珍藏版)》请在冰豆网上搜索。
ISD1700语音芯片SPI使用总结
ISD1700语音芯片SPI使用总结
(一)
ISD1700语音芯片SPI使用总结
一
该语音芯片的使用要仔细分析英文PDF的资料,电路可按中青世纪论坛上面所给的电路搭建,也可按英文PDF后面所画的电路图焊接。
本芯片使用不单纯是一个放音电路,还含有其他的控制。
因此程序首先要能完成指定地址的放音工作,其次还应能嵌入整个费额显示程序中,即语音程序不能与电路其他功能相影响。
费额显示中里面主要有八字板,点阵等其他的控制。
SPI放音操作设计参考了网络上的部分程序,各取所长设计了放音程序。
在最后附上了部分程序,仅供参考。
二
试验中采用的是ISD1760语音芯片,采样率为8K时,一共能播放60S的语音,最大地址为0x1EF,录音实际地址为0x10-0x1EF,从此最大地址可得出:
0x1EF-0x10=0x1DF=479
479+1=480;480*125MS=60S,也就是说8K采样率时每1个地址最小语音长度为125MS,因此如果知道单个语音的长度,暂时无编程器的时候,也可自己推断每个语音所占的地址长度。
三
SPI操作时要严格遵守PDF上所给的各项操作,这里不列出。
暂时仅给出试验中遇到的所有问题并如何解决的。
1,一开始本实验是自己用通用板自己照电路搭建的平台,此电路正确与否可把PLAY管腿和地短路,如果芯片有语音并且电路功放及外围电路正确的话,此时芯片就会把所有语音全都循环读一遍。
接下来把4个SPI口与单片机接通,尝试软件控制。
主循环中可设置一个连续播放的程序,上电就循环放音。
放音程序没错的话第一步便成功了!
这期间我遇到的问题主要有放不出音,读音混乱,有杂音。
如果放不出音,先检查电路,程序放出声音应该没出现什么问题。
2,本芯片设置的APC值为0xA0和0x04,具体对应功能参见中文PDF。
接下来遇到的问题就是准确放单个音和连续播放多个语音。
播放单个语音首先是地址的编译。
1730以下的地址可定义为BYTE,从1740开始就需要定义为WORD,其实也可定义为BYTE,就是发送地址的时候先发0x10和后两位即可。
本程序定义为WORD,做一个偏移发送即可。
接下来的问题就是连续播放的问题,这个问题直到最后才正确的解决。
一开始的程序中只是一直发送SETPLAY,可以连续读,就是读的乱,其实就是错误操作,后来尝试在后面添加一个2秒的延时,可以连续读出语音了,就是每个要停顿一下才能放出第二个语音,自认为就这样就可以了,导致了以后还得解决此问题!
因为此放音方式放弃了判断芯片状态寄存器,根本没有实现连续放音,实际是单个语音人为把它们连起来播放,听起来很不自然。
问题拖到最后又衍生了别的问题,由于此放音方式的声音输出信号是有高有低,当电平跳变时对功放产生影响,喇叭会出现“噗噗”声,术语可以称之为“过载”,如果人距离喇叭很近的话很容易听出来。
因此需修改程序,芯片内部有个缓冲器,如果连续发送相同的两个setplay命令,芯片会发完第一个音后接着连续发第二个音,并且两音之间的间隔时间几乎没有。
利用这个特点,可以在发完一个语音命令后一直发送读芯片状态命令,从返回来的数据判断RDY,PLAY,INT位,当第一条放音指令发送完,读音播放完,立即发送第二条setplay,并以此类推。
这样实现了连续放音,并且声音输出一直为高电平(除了开始和结束音),解决了噗噗声的问题。
但是要一直发送读芯片状态指令就会影响其他指令,如本实验是执行串口指令,点阵刷新,八字板的显示和亮度调整等,推荐在do{ISD_Rd_Status;}while();内添加以上命令,便可解决只读音不响应其他命令的问题。
串口可判断标志位;点阵可在连续刷新16行(16*16点阵)后执行下一判断芯片标志位程序;八字板的显示可以锁存,因此有改变显示时执行一次即可;八字板的亮度需要一直执行,但是当亮度为3以下时(即16MS内有3MS是点阵亮,13MS是不亮),放音时八字板会有闪烁现象,原因可能是执行除了亮度调整指令外其他指令占用了大约3MS的时间,暂时还没有好的解决办法。
四
正在放音的同时用串口发送调节音量也遇到了问题,一开始的解决办法是打断当前语音,延时超过最大语音长度的时间,再发送修改APC的指令。
这样做的原因是如果用本程序在发完当前音后突然发送修改APC的指令时候,芯片会从头到尾读所有音!
!
到最后仔细研究才发现这个程序中有个修改永久内部寄存器的指令,当正在进行读音操作发送修改内部永久寄存器时会导致以上现象,把此程序剥离后实现了边播放语音边调节音量。
发送时也要注意判断芯片状态,RDY为1后发送,RDY再次为1时继续发放音指令。
五
本芯片的录音采用拷贝机,拷贝机烧录语音时也需注意以下问题:
首先是在最后的语音后添加一空语音,以保证录音不会出现问题;其次是烧录语音时电脑除了运行烧录语音的程序,其它什么都不要开,什么QQ,杀毒软件等都要关闭,最好鼠标都不要动!
烧录语音前最好检查下声卡驱动,保证有驱动并且最新,最好将声卡声音输出设置(本机为AC97Audio)中喇叭组态设置为耳机,不要什么立体声等其他状态。
音量大小可以随意,本试验设置最大。
官方意见是三分之二的状态,总之,在噪音最小的情况下也要保证音量。
六
第一次芯片初始化修改APC时,最好在前面添加chk_mem这个指令,在1700的datasheet里的说明并不多。
大意是检查环状存储器存储地址是否首尾相连的意思。
因为网上有人反映不添加此指令APC修改不了。
七
拷贝机很贵,并不是必须买,本芯片烧录语音的拷贝机也不是自己的,囧!
烧录语音的试验还没做过,将来会做这方面的试验。
另外芯片也有次品,主要表现是在放音时有很大的“咔嚓”声,还有一个干脆就是烧不了音!
拿去退货!
试验样本100只ISD1760,次品率十五分之一。
ISD1700语音芯片SPI使用总结
(二)
八
另外做了些其他实验,如在发送字节命令时,去掉了所有延时指令,芯片也可正常工作。
试验中单片机为SST和STC的产品,工作晶振22.1184MHz和35MHz。
波特率为9600.
九
音质不满意,但硬件电路(外围干扰或功放电路等)又实在不能更改,可尝试修改音源。
本实验采用的语音,在ISD2560(并行操作,停产)播放语速很正常,而ISD1760(替换2560)播放发现稍微有些慢。
可使用COOLEDIT或者Adobe.Audition.v1.5.CN做些修改,本实验用后者软件做修改。
做了修改破音,断音,去噪,不改变音质的情况下缩短语音播放长度,修改效果不错,可以尝试。
想自己录音的可用WIN自带的录音机,再配用此软件可调出不错的语音。
也可软件合成语音,具体软件和语音库网上可以搞到。
十
目前人仍有潜在问题,发现当新板子焊有复位键时,按下复位键语音芯片会不工作,而再次按下复位键时语音芯片便可继续工作,也就是说复位键按下次数的奇数次都会产生这样的问题。
但是当电路没有复位电路时就不会出现此问题!
十一
本电路是音频是采用AUX输出,中青世纪的论坛上给的电路图是在此脚接一电容CM3。
本实验认为此处应接电阻。
接电容可能会影响音量,但在实际实验中未发现音量有变化。
十二
由于电路的原因,语音芯片的供电为3.3V,PDF说明2.4V-5.5V皆可。
在采样率8K时震荡电阻为80K电阻,实际中无80K电阻,推荐用240K与120K并联构成80K电阻!
本电阻用82K代替。
此电阻会影响放音的时间和音质。
ISD1700语音芯片SPI使用总结(三)
附:
MAIN.C
voidISD_Reset(void)
{
ISD_SendByte(CMD_1760_RESET);
ISD_SendByte(0x00);
sbnISD_SS=1;
//DelayX1ms(10);
}
voidISD_PU(void)
{
ISD_SendByte(CMD_1760_PU|0x10);
ISD_SendByte(0x00);
sbnISD_SS=1;
DelayX1ms(50);
}
voidISD_Rd_Status(void)
{
ISD_SendByte(CMD_1760_RD_STATUS);
ISD_SendByte(0x00);
ISD_SendByte(0x00);
sbnISD_SS=1;
//DelayX1ms(10);
SR0_L=ISD_SendByte(CMD_1760_RD_STATUS);
SR0_H=ISD_SendByte(0x00);
SR1=ISD_SendByte(0x00);
sbnISD_SS=1;
//DelayX1ms(10);
}
voidISD_ClrInt(void)
{
ISD_SendByte(CMD_1760_CLI_INT);
ISD_SendByte(0x00);
sbnISD_SS=1;
//DelayX1ms(10);
}
voidISD_CHK_MEM(void)
{
ISD_SendByte(CMD_1760_CHK_MEM);
ISD_SendByte(0x00);
sbnISD_SS=1;
//DelayX1ms(10);
}
voidISD_WR_APC2(BYTEVolume)
{
ISD_SendByte(CMD_1760_WR_APC2);
ISD_SendByte(Volume);//后3位为音量
ISD_SendByte(0x04);//0x04EOM=0,VALERT=1,0x0CEOM=1
sbnISD_SS=1;
DelayX1ms(10);
ISD_WR_NVCFG();//永久写入寄存器//此程序正在放音要调整音量时不要添加!
!
}
voidISD_WR_NVCFG(void)
{
ISD_SendByte(CMD_1760_WR_NVCFG);
ISD_SendByte(0x00);
sbnISD_SS=1;
DelayX1ms(10);
}
voidISD_RDAPC(void)
{
ISD_SendByte(CMD_1760_RD_APC);
ISD_SendByte(0x00);
ISD_SendByte(0x00);
ISD_SendByte(0x00);
sbnISD_SS=1;
DelayX1ms(10);
SR0_L=ISD_SendByte(CMD_1760_RD_APC);
SR0_H=ISD_SendByte(0x00);
APCL=ISD_SendByte(0x00);
APCH=ISD_SendByte(0x00);
sbnISD_SS=1;
DelayX1ms(10);
}
voidISD_PD(void)
{
ISD_SendByte(CMD_1760_PD);
ISD_SendByte(0x00);
sbnISD_SS=1;
//DelayX1ms(5);
}
BYTEISD_SendByte(BYTEBUF_ISD)
{
BYTEi;
BYTEdat=BUF_ISD;
sbISD_SCLK=1;
sbnISD_SS=0;
for(i=0;i<8;i++)
{
sbISD_SCLK=0;
_nop_();
_nop_();
if(dat&0x01)
{
sbISD_MOSI=1;
}
else
{
sbISD_MOSI=0;
}
dat>>=1;
if(sbISD_MISO==1)
{
dat|=0x80;
}
sbISD_SCLK=1;
_nop_();
_nop_();
}
sbISD_MOSI=0;
_nop_();
return(dat);
}
ISD1700语音芯片SPI使用总结(四)
BYTEISD_RDDevID(void)
{
ISD_SendByte(CMD_1760_RD_DEVID);
ISD_SendByte(0x00);
ISD_SendByte(0x00);
sbnISD_SS=1;
DelayX1ms(10);
SR0_L=ISD_SendByte(CMD_1760_RD_DEVID);
SR0_H=ISD_SendByte(0x00);
ID=ISD_SendByte(0x00);
sbnISD_SS=1;
DelayX1ms(10);
return(ID);
}
voidISD_Init(void)
{
ISD_Reset();
ISD_PU();//上电指令
DelayX1ms(50);
//SBUF=ISD_RDDevID();//读取芯片ID,----1760为0xA0
ISD_ClrInt();
ISD_CHK_MEM();//检查环状存储器存储地址是否首尾相连
//改变1700内部存储单元或是内部寄存器的指令前,
//都要加上这个指令。
ISD_WR_APC2(Volume);//写APC寄存器,后3位为音量,此设为最大,0xA7为最小F0
DelayX1ms(50);
//ISD_RDAPC();//读APC寄存器
//DelayX1ms(25);
}
voidISD_GetToneAdd(BYTEcNum,WORD*ipStartAdd,WORD*ipEndAdd)
{
*ipStartAdd=aSpeech_Addr[cNum*2];
*ipEndAdd=aSpeech_Addr[cNum*2+1];
}
voidISD_SetPLAY(BYTEcNum)
{
WORDAdd_ST,Add_ED;
BYTEAdd_ST_H,Add_ST_L,Add_ED_H,Add_ED_L;
//ISD_Init();//初始化
//ISD_PU();
//ISD_ClrInt();//清中断
ISD_GetToneAdd(cNum,&Add_ST,&Add_ED);//取出当前语音的首末地址
Add_ST_L=(BYTE)(Add_ST&0x00ff);
Add_ST_H=(BYTE)((Add_ST>>8)&0x00ff);
Add_ED_L=(BYTE)(Add_ED&0x00ff);
Add_ED_H=(BYTE)((Add_ED>>8)&0x00ff);
ISD_SendByte(CMD_1760_SET_PLAY);//发送放音指令
ISD_SendByte(0x00);
ISD_SendByte(Add_ST_L);//S7:
S0开始地址
ISD_SendByte(Add_ST_H);//S10:
S8
ISD_SendByte(Add_ED_L);//E7:
E0结束地址
ISD_SendByte(Add_ED_H);//E10:
E8
ISD_SendByte(0x00);
sbnISD_SS=1;
}
ISD1700语音芯片SPI使用总结(五)
管腿,变量等其他.H程序
sbitsbnISD_SS=P1^0;//ISD1760的slaveselect
sbitsbISD_SCLK=P1^1;//ISD1760的SPI接口时钟
sbitsbISD_MOSI=P1^2;//ISD1760的SPI接口数据输入端口
sbitsbISD_MISO=P1^3;//ISD1760的SPI接口的串行输出
sbitsbnINT_1760=P3^2;//ISD1760的INT管脚//未使用//外部中断可用此脚
sbitsbSRT_1760=P3^3;//ISD1760的RESET管脚//未使用
//-----ISD1760SPI命令-----
#defineCMD_1760_PU0x01//上电
#defineCMD_1760_STOP0x02
#defineCMD_1760_RESET0x03//复位
#defineCMD_1760_CLI_INT0x04//清中断
#defineCMD_1760_RD_STATUS0x05//读状态
#defineCMD_1760_RD_PLAY_PTR0x06
#defineCMD_1760_PD0x07//掉电
#defineCMD_1760_RD_REC_PTR0x08
#defineCMD_1760_RD_DEVID0x09//读取芯片ID
#defineCMD_1760_G_ERASE0x43
#defineCMD_1760_RD_APC0x44//读APC
#defineCMD_1760_WR_APC10x45
#defineCMD_1760_WR_APC20x65//SPI模式下写APC寄存器
#defineCMD_1760_WR_NVCFG0x46//永久写入寄存器
#defineCMD_1760_CHK_MEM0x49//检查环状存储器
#defineCMD_1760_SET_PLAY0x80//设置播放
#defineCMD_1760_SET_REC0x81
#defineCMD_1760_SET_ERASE0x82
unsignedcharbdataSR0_L;
sbitbINT_1760=SR0_L^4;
sbitbEOM=SR0_L^3;
sbitbPU_1760=SR0_L^2;
sbitbFULL=SR0_L^1;
sbitbCMD_ERR=SR0_L^0;
unsignedcharbdataSR0_H;
unsignedcharbdataSR1;
sbitbREC_1760=SR1^3;
sbitbPLAY_1760=SR1^2;
sbitbERASE_1760=SR1^1;
sbitbRDY=SR1^0;
unsignedcharID,APCL=0,APCH=0;
WORDcodeaSpeech_Addr[90]
={0x0010,0x0013,0x0014,0x0017,0x0018,0x001C,0x001D,0x0020,0x0021,0x0024,0x0025,0x0028,0x0029,0x002D,0x002E,0x0032,0x0033,0x0037,0x0038,0x003C,0x003D,0x0042,0x0043,0x0047,0x0048,0x004C,0x004D,0x0051,0x0052,0x0059,0x005A,0x0061,0x0062,0x0069,0x006A,0x0071,0x0072,0x0079,0x007A,0x0081,0x0082,0x008A,0x008B,0x0092,0x0093,0x009A,0x009B,0x00A0,0x00A1,0x00A7,0x00A8,0x00AE,0x00AF,0x00B8,0x00B9,0x00C2,0x00C3,0x00CB,0x00CC,0x00D1,0x00D2,0x00DA,0x00DB,0x00E0,0x00E1,0x00EA,0x00EB,0x00F5,0x00F6,0x00FE,0x00FF,0x0104,0x0105,0x0117,0x0118,0x0127,0x0128,0x0133,0x0134,0x0140,0x0141,0x0147,0x0148,0x0154,0x0155,0x0158,0x0159,0x016E,0x016F,0x0170};
voidDelayX1ms(WORDcount);
//ISD1760
BYTEISD_SendByte(BYTEBUF_ISD);
voidISD_Reset(void);
voidISD_PU(void);
voidISD_Rd_Status(void);
voidISD_ClrInt(void);
voidISD_CHK_MEM(void);
voidISD_WR_APC2(BYTEvoiceValue);
voidISD_WR_NVCFG(void);
voidISD_RDAPC(void);
voidISD_PD(void);
BYTEISD_RDDevID(void);
voidISD_Init(void);
voidISD_GetToneAdd(BYTEcNum,WORD*ipStartAdd,WORD*ipEndAdd);
//取出当前语音的首末地址
voidISD_SetPLAY(BYTEcNum);
************************************************************
ISD1700语音芯片SPI使用总结(六)
MAIN中的FOR循环,芯片初始化省略
if(bFlag_spk)//放音标志
{
for(i=0;i<21;i++)//一共21个放音元素
{
tmp=Speak_buf[i];//取当前放音位置
if(tmp<=0x3E)//在正常范围内
{
ISD_SetPLAY(tmp);//播放当前位置语音,地址内部对应
do
{
ISD_Rd_Status();//读芯片状态
if(bOpen_LED_Mark)
{
Renovate_LED();//八字板亮度调整
}
if(_testbit_(bReceive_Mark))//执行串口命令
Execute_LEDcmd2();
if((1==bOpen_LED_Mark)&&(1==bOpen_Mark2))//执行一次八子板显示命令
{
Disp_LED2();
Put_ON_LED();
bOpen_Mark2=0;
}
}while((0==bRDY)&&(0==bINT_1760)&&(1==bPLAY_1760));
//放音结束后跳出
ISD_ClrInt();
if(ISD_SETVolume_Mark)//调整音量标志
{
ISD_SendByte(CMD_1760_WR_APC2);
ISD_SendByte(Volume);//后3位为音量
ISD_SendByte(0x04);//0x04EOM=0,VALERT=1,0x0CEOM=1
sbnISD_SS=1;
DelayX1ms(10);
do
{
ISD_Rd_Status();
}while(0==bRDY);
ISD_ClrInt();
ISD_SETVolume_Mark=0;
}
}
else
{
i=21;
}
}
bFlag_spk=0;
}
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ISD1700 语音 芯片 SPI 使用 总结