视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
ISD1700语音芯片SPI使用总结
2025-09-26 04:25:52 责编:小OO
文档
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,杀毒软件等都要关闭,最好鼠标都不要动!烧录语音前最好检查下声卡驱动,保证有驱动并且最新,最好将声卡声音输出设置(本机为AC97 Audio)中喇叭组态设置为耳机,不要什么立体声等其他状态。音量大小可以随意,本试验设置最大。官方意见是三分之二的状态,总之,在噪音最小的情况下也要保证音量。

       第一次芯片初始化修改APC时,最好在前面添加chk_mem这个指令,在1700的datasheet里的说明并不多。大意是检查环状存储器存储地址是否首尾相连的意思。因为网上有人反映不添加此指令APC修改不了。

拷贝机很贵,并不是必须买,本芯片烧录语音的拷贝机也不是自己的,囧!烧录语音的试验还没做过,将来会做这方面的试验。另外芯片也有次品,主要表现是在放音时有很大的“咔嚓”声,还有一个干脆就是烧不了音!拿去退货!试验样本100只ISD1760,次品率十五分之一。

ISD1700语音芯片SPI使用总结(二)

八 

另外做了些其他实验,如在发送字节命令时,去掉了所有延时指令,芯片也可正常工作。试验中单片机为SST和STC的产品,工作晶振22.1184MHz和35MHz。波特率为9600.

       音质不满意,但硬件电路(外围干扰或功放电路等)又实在不能更改,可尝试修改音源。本实验采用的语音,在ISD2560(并行操作,停产)播放语速很正常,而ISD1760(替换2560)播放发现稍微有些慢。可使用COOL EDIT或者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

 void ISD_Reset(void)

{

        ISD_SendByte(CMD_1760_RESET);

        ISD_SendByte(0x00);

        sbnISD_SS=1;

//         DelayX1ms(10);

}

void  ISD_PU(void)

{

        ISD_SendByte(CMD_1760_PU|0x10);

        ISD_SendByte(0x00);

        sbnISD_SS=1;

           DelayX1ms(50);

}

 void ISD_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);

}

void ISD_ClrInt(void)

{

        ISD_SendByte(CMD_1760_CLI_INT);

        ISD_SendByte(0x00);

        sbnISD_SS=1;

//        DelayX1ms(10);              

}

void ISD_CHK_MEM(void)

{

        ISD_SendByte(CMD_1760_CHK_MEM);

        ISD_SendByte(0x00);

        sbnISD_SS=1;

//        DelayX1ms(10);

}

 

 

void ISD_WR_APC2(BYTE Volume)

{

        ISD_SendByte(CMD_1760_WR_APC2);

        ISD_SendByte(Volume);         //后3位为音量

        ISD_SendByte(0x04);           //0x04 EOM=0,VALERT=1 ,0x 0C EOM=1

        sbnISD_SS=1;

        DelayX1ms(10);                      

        ISD_WR_NVCFG(); //永久写入寄存器 //此程序正在放音要调整音量时不要添加!!

}

void ISD_WR_NVCFG(void)

{

        ISD_SendByte(CMD_1760_WR_NVCFG);

        ISD_SendByte(0x00);

        sbnISD_SS=1;

        DelayX1ms(10);              

}

void ISD_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);               

}

void ISD_PD(void)

{

        ISD_SendByte(CMD_1760_PD);

        ISD_SendByte(0x00);

        sbnISD_SS=1;

//            DelayX1ms(5);

             

}

BYTE ISD_SendByte(BYTE BUF_ISD)

{

        BYTE i;

              BYTE dat=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使用总结(四)

BYTE ISD_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);

}

 

 

 

void   ISD_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);

}

 

 

void ISD_GetToneAdd(BYTE cNum, WORD * ipStartAdd, WORD * ipEndAdd)

{

        *ipStartAdd=aSpeech_Addr[cNum * 2];

        *ipEndAdd=aSpeech_Addr[cNum * 2 + 1];

}

 

 

void ISD_SetPLAY(BYTE cNum)

{

        WORD Add_ST, Add_ED;

        BYTE Add_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程序

 

sbit        sbnISD_SS              = P1^0; // ISD1760的slave select

sbit        sbISD_SCLK              = P1^1; // ISD1760的SPI接口时钟

sbit        sbISD_MOSI              = P1^2; // ISD1760的SPI接口数据输入端口

sbit        sbISD_MISO              = P1^3; // ISD1760的SPI接口的串行输出

 

sbit        sbnINT_1760             = P3^2;   // ISD1760的INT管脚//未使用//外部中断可用此脚

sbit        sbSRT_1760                 = P3^3;          // ISD1760的RESET管脚//未使用

// ----- ISD1760 SPI命令 -----

#define CMD_1760_PU                        0x01             //上电

#define CMD_1760_STOP                 0x02            

#define CMD_1760_RESET                0x03             //复位

#define CMD_1760_CLI_INT              0x04             //清中断

#define CMD_1760_RD_STATUS                  0x05             //读状态

#define CMD_1760_RD_PLAY_PTR        0x06

#define CMD_1760_PD                   0x07             //掉电

#define CMD_1760_RD_REC_PTR         0x08

#define CMD_1760_RD_DEVID           0x09             //读取芯片ID

#define CMD_1760_G_ERASE             0x43     

#define CMD_1760_RD_APC              0x44             //读APC

#define CMD_1760_WR_APC1            0x45

#define CMD_1760_WR_APC2            0x65             //SPI模式下写APC寄存器

#define CMD_1760_WR_NVCFG          0x46             //永久写入寄存器

#define CMD_1760_CHK_MEM                   0x49             //检查环状存储器

#define CMD_1760_SET_PLAY                    0x80             //设置播放

#define CMD_1760_SET_REC             0x81

#define CMD_1760_SET_ERASE           0x82

 

 

unsigned char bdata SR0_L;

sbit bINT_1760                            =SR0_L^4;

sbit bEOM                               =SR0_L^3;

sbit bPU_1760                             =SR0_L^2;

sbit bFULL                               =SR0_L^1;

sbit bCMD_ERR                          =SR0_L^0;

 

unsigned char bdata SR0_H;

unsigned char bdata SR1; 

sbit bREC_1760                           =SR1^3;

sbit bPLAY_1760                          =SR1^2;

sbit bERASE_1760                         =SR1^1;

sbit bRDY                                =SR1^0;

 

unsigned char ID,APCL=0,APCH=0;

 

WORD code aSpeech_Addr[90]

={0x0010,0x0013,0x0014,0x0017,0x0018,0x 001C,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};

 

void DelayX1ms(WORD count);

//ISD1760

BYTE ISD_SendByte(BYTE BUF_ISD);

 

void ISD_Reset(void);

void ISD_PU(void);

void ISD_Rd_Status(void);

void ISD_ClrInt(void);

void ISD_CHK_MEM(void);

void ISD_WR_APC2(BYTE voiceValue);

void ISD_WR_NVCFG(void);

void ISD_RDAPC(void);

void ISD_PD(void);

BYTE ISD_RDDevID(void);

void ISD_Init(void);

 

void ISD_GetToneAdd(BYTE cNum, WORD * ipStartAdd, WORD * ipEndAdd);

// 取出当前语音的首末地址

void ISD_SetPLAY(BYTE cNum);

************************************************************

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); //0x04 EOM=0,VALERT=1 ,0x 0C EOM=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;                    

              }

 

参考程序网址:

http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=917470&bbs_page_no=1&bbs_id=1006下载本文

显示全文
专题