<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 基于語音識別的微博簽到系統(tǒng)

          基于語音識別的微博簽到系統(tǒng)

          作者: 時間:2016-11-26 來源:網(wǎng)絡 收藏

          LD3320介紹

          1 通過快速而穩(wěn)定的優(yōu)化算法,完成非特定人語音識別,識別準確率95%。

          2 不需要外接任何輔助的Flash芯片,RAM芯片和AD芯片,就可以完成語音識別功能。

          3 每次識別最多可以設置50項候選識別句,每個識別句可以是單字,詞組或短句,長度為不超過10個漢字或者79個字節(jié)的拼音串。識別句內容還可以動態(tài)編輯修改。

          4 芯片內部已經(jīng)準備了16位A/D轉換器、16位D/A轉換器和功放電路,麥克風、立體聲耳機和單聲道喇叭可以很方便地和芯片管腳連接。

          5 支持并行和串行接口,串行方式可以簡化與其他模塊的連接。

          在本系統(tǒng)中采用的LD3320模塊如圖7,LD3320芯片外部已經(jīng)連接了麥克風,耳機接口,基本電路,只引出了我們需要的引腳。本系統(tǒng)采用串行方式,串行接口通過SPI協(xié)議和外部主CPU連接,首先要將MD接高電平,將SPIS接地,選定LD3320工作在串行模式,此時使用的管腳有:片選(SCS*)、SPI時鐘(SDCK)、SPI輸入(SDI)和SPI輸出(SDO),中斷引腳(INT),復位引腳(RST),時鐘引腳(CLK),通過SPI接口,配置LD3320的工作模式,讀取識別結果,圖8,圖9為SPI讀寫時序。當LD3320識別到有語音輸入,INT引腳將產(chǎn)生中斷,在中斷處理函數(shù)中,讀取識別結果,改變LD3320狀態(tài)。


          圖7LD3320語音模塊

          圖8SPI方式讀時序

          圖9 SPI方式寫時序

          在本系統(tǒng)中,OV2640輸出JPEG壓縮圖像格式。MCU與OV2640的通信采用串行與并行結合,OV2640帶有SCCB(Serial Camera Control Bus)雙線串行接口,MCU通過SCCB接口配置和讀取OV2640的信息;MCU通過并行總線的方式來接收OV2640的圖像數(shù)據(jù)。Y(2..9)為8位MSB(MostSignificant Bit,最高有效位模式)并行總線,SDIO、SCLK為SCCB接口,PCLK為像素時鐘輸出管腳(每個周期從并行總線上輸出一個像素),VSYNC為列同步輸出管腳(每幀圖像發(fā)生一次跳變),HERF為行參考輸出管腳(每個周期總線從并行總線上輸出一行圖像數(shù)據(jù))。系統(tǒng)的硬件電路連接簡圖如圖10。

          圖10系統(tǒng)硬件電路連接簡圖

          系統(tǒng)上電后,MCU配置OV2640的工作方式,初始化LD3320,然后檢查LD3320的狀態(tài),當LD3320的狀態(tài)是“找到識別結果”,開啟OV2640中斷,在OV2640準備好圖像后,VSYNC會被拉高一段時間,MCU通過PCLK上升沿中斷按字節(jié)接收圖像數(shù)據(jù),接收數(shù)據(jù)完成,關閉OV2640中斷。然后向新浪微博發(fā)送已經(jīng)寫進程序里的自己想說的話和接收到的圖片。接下來將對主要的程序塊做介紹。

          程序介紹

          在《為你的設備添加社交網(wǎng)絡功能》中,已經(jīng)詳細介紹了OV2640的初始化配置程序,本篇文章就不再贅述,圖像數(shù)據(jù)緩存程序與本文稍有不同,這里簡單介紹圖像數(shù)據(jù)緩存程序。本文對LD3320的寫入詞條列表,啟動語音識別,中斷處理程序,發(fā)送微博程序做主要介紹。

          圖像數(shù)據(jù)緩存程序(摘至stm32f10x_it.c):

          void EXTI0_IRQHandler(void)

          {

          u8 temp;

          EXTI_ClearITPendingBit(EXTI_Line0);//清除EXTI0線路掛起位

          if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_1)==0)return;//HREF管腳為低

          temp=(u8)((GPIOC->IDR)>>8 & 0x00ff);//讀取一個字節(jié)圖像數(shù)據(jù)

          switch(jpg_flag)

          {

          case 0:

          if(temp==0xff)//圖像數(shù)據(jù)以0xff 0xd8開頭

          {

          JPEGBuffer[0]=0xff;

          jpg_flag=1;

          }

          break;

          case 1:

          if(temp==0xd8)

          {

          JPEGBuffer[1]=0xd8;

          jpg_flag=2;

          JPEGCnt=2;

          }

          else if(temp!=0xff)

          jpg_flag=0;

          break;

          case 2:

          JPEGBuffer[JPEGCnt++] =temp;//存儲數(shù)據(jù)

          if(temp==0xff)jpg_flag=3;

          break;

          case 3:

          JPEGBuffer[JPEGCnt++]=temp;//圖像數(shù)據(jù)以0xff0xd9結尾

          if(temp==0xd9)

          {

          jpg_flag=4;

          }

          else if(temp!=0xff)

          jpg_flag=2;

          break;

          case 4:

          break;

          }

          }

          在中斷函數(shù)中通過以上程序即可正確讀取每一幀圖像的數(shù)據(jù)了。程序思想已經(jīng)在拍攝照片流程圖中體現(xiàn)。JPEGBuffer為一個全局的圖像緩存區(qū),在主函數(shù)中,檢測到緩存區(qū)數(shù)據(jù)準備完畢后,就可以將圖像發(fā)送給新浪微博了。

          LD3320添加詞條程序(摘至LD3320_main.c)

          uint8 LD_AsrAddFixed(void)

          {

          uint8 k, flag;

          uint8nAsrAddLength;

          #define DATE_A4

          #define DATE_B20

          uint8sRecog[DATE_A][DATE_B] = {

          "wenjuan",

          "guocui",

          "jierui",

          "chenge"

          };

          uint8pCode[DATE_A] = {

          CODE_wenjuan,

          CODE_guocui,

          CODE_jierui,

          CODE_chenge

          };

          flag = 1;

          for (k=0; k

          {

          if(LD_Check_ASRBusyFlag_b2() == 0)

          {

          flag= 0;

          break;

          }

          LD_WriteReg(0xc1, pCode[k] );

          LD_WriteReg(0xc3, 0 );

          LD_WriteReg(0x08, 0x04);

          LD3320_delay(1);

          LD_WriteReg(0x08, 0x00);

          LD3320_delay(1);

          for (nAsrAddLength=0; nAsrAddLength

          {

          if (sRecog[k][nAsrAddLength] == 0)

          break;

          LD_WriteReg(0x5, sRecog[k][nAsrAddLength]);

          }

          LD_WriteReg(0xb9, nAsrAddLength);

          LD_WriteReg(0xb2, 0xff);

          LD_WriteReg(0x37, 0x04);

          LD_WriteReg(0x37, 0x04);

          }

          return flag;

          }

          列表的規(guī)則是,每個識別條目對應一個特定的編號(1個字節(jié)),不同的識別條目的編號可以相同,而且不用連續(xù)。本芯片最多支持50個識別條目,每個識別條目是標準普通話的漢語拼音(小寫),每2個字(漢語拼音)之間用一個空格間隔。首先把識別條目的編號寫入0xc1寄存器,其次,將字符串中的字符按順序寫入寄存器0x05,然后將字符串長度寫入寄存器0xB9,向寄存器0xB2寫入0xFF,向寄存器0x37寫入0x04,通知DSP要添加一項識別句。

          LD3320啟動語音識別程序(摘至LD3320_main.c)

          uint8 LD_AsrRun(void)

          {

          1LD_WriteReg(0x35,MIC_VOL);//ADC增益設置

          2LD_WriteReg(0x1C,0x09);//ADC開關控制,寫09H為保留命令字。

          3LD_WriteReg(0xBD,0x20);//初始化控制寄存器,寫入20H,保留命令字。

          4LD_WriteReg(0x08, 0x01);//清除FIFO內容,第0位:寫入1→清除FIFO_DATA。

          LD3320_delay( 5);

          5LD_WriteReg(0x08,0x00);

          LD3320_delay( 5);

          6if(LD_Check_ASRBusyFlag_b2()== 0)//檢查b2寄存器是否為空閑

          {

          return 0;

          }

          LD_WriteReg(0xB2,0xff);

          7LD_WriteReg(0x37, 0x06); //語音識別控制命令下發(fā)寄存器,寫06H:通知DSP開始識別語音。

          LD_WriteReg(0x37,0x06);

          LD3320_delay( 5);

          8LD_WriteReg(0x1C, 0x0b); // ADC開關控制寫0BH麥克風輸入ADC通道可用

          LD_WriteReg(0x29, 0x10); //中斷允許(可讀寫)第4位:同步中斷允許,1表示允許;0表示不允許。

          LD_WriteReg(0xBD, 0x00);//初始化控制寄存器寫入00H;然后啟動;為ASR模塊;

          return 1;

          }

          第1行,ADC增益設置,或可以理解為麥克風(MIC)音量??梢栽O置為00H-7FH。建議設置值為40H-55H:值越大代表MIC音量越大,識別啟動越敏感,但可能帶來更多誤識別;值越小代表MIC音量越小,需要近距離說話才能啟動識別功能,好處是對遠處的干擾語音沒有反應。第6行檢查LD3320是否為空閑狀態(tài),如果為空閑狀態(tài),在第7行向0x37寄存器寫入0x06,通知DSP開始語音識別。第8行,向寄存器0x1c寫入0x0b,表示麥克風輸入ADC通道可用。

          LD3320中斷處理程序(摘至LDChip.c)

          voidProcessInt0(void)

          {

          uint8nAsrResCount=0;

          1ucRegVal = LD_ReadReg(0x2B);// 讀取中斷請求編號寄存器

          2LD_WriteReg(0x29,0);// 第2位:FIFO 中斷允許,1表示允許;0表示不允許。第4位:同步中斷允許,1表示允許;0表示不允許。

          3LD_WriteReg(0x02,0);// FIFO中斷允許第0位:允許FIFO_DATA中斷;第2位:允許FIFO_EXT中斷;

          4If((ucRegVal& 0x10)&&LD_ReadReg(0xb2)==0x21 &&LD_ReadReg(0xbf)==0x35)// 中斷請求編號寄存器0x2B第4位:讀取值為1表示語音識別有結果產(chǎn)生;MCU可清零。ASR過程中DSP忙閑狀態(tài)寄存器0xb2,讀取到0x21 表示閑,查詢到為閑狀態(tài)可以進行下一步ASR動作。ASR狀態(tài)報告寄存器0xbf 讀到數(shù)值為0x35,可以確定是一次語音識別流程正常結束.

          {

          5nAsrResCount= LD_ReadReg(0xba); //中斷輔助信息寄存器,其中的數(shù)值表示語音識別有幾個識別候選

          6if(nAsrResCount>0&&nAsrResCount<=4)

          {

          nAsrStatus=LD_ASR_FOUNDOK;

          }

          else

          {

          7nAsrStatus=LD_ASR_FOUNDZERO;

          }

          }

          else

          {

          8nAsrStatus=LD_ASR_FOUNDZERO;//執(zhí)行沒有識別

          }

          LD_WriteReg(0x2b,0);

          LD_WriteReg(0x1C,0);

          LD_WriteReg(0x29,0);

          LD_WriteReg(0x02,0);

          LD_WriteReg(0x2B,0);

          LD_WriteReg(0xBA,0);

          LD_WriteReg(0xBC,0);

          LD_WriteReg(0x08,1);

          LD_WriteReg(0x08,0);

          }

          中斷處理函數(shù)的第1行讀取中斷請求編號寄存器0x2B的值,第4位:讀取值為1表示語音識別有結果產(chǎn)生;MCU可清零。第2位:讀取值為1表示芯片內部FIFO中斷發(fā)生。MP3播放時會產(chǎn)生中斷標志請求外部MCU向FIFO_DATA中Reload數(shù)據(jù)。第3位:讀取值為1表示芯片內部已經(jīng)出現(xiàn)錯誤。值得注意的是:如果在中斷響應時讀到這位為1,需要對芯片進行重啟Reset,才可以繼續(xù)工作。第2,3行關閉LD3320的中斷。第4行,讀取中斷請求編號寄存器0x2B的值,當?shù)?位讀取值為1表示語音識別有結果產(chǎn)生,其次讀取語音識別過程中DSP忙閑狀態(tài)寄存器0xb2,讀取到0x21表示閑,然后讀取語音識別狀態(tài)報告寄存器0xbf的值,讀到數(shù)值為0x35,可以確定是一次語音識別流程正常結束,當這三個寄存器的數(shù)值不滿足以上要求的時候,返回“LD_ASR_FOUNDZERO”,表示未找到識別結果。當滿足以上要求時,第5行,讀取中斷輔助信息寄存器,其中的數(shù)值表示語音識別有幾個識別候選,當數(shù)值為1 – 4:表示有N個識別候選,數(shù)值為0或者大于4表示沒有識別候選,當有識別候選的時候,返回“LD_ASR_FOUNDOK”,表示找到語音識別結果。

          發(fā)送微博程序(摘至weibo.c)

          unsigned char post_weibo_upload(char* weibo, uint8* pic,uint32 picLen)

          {

          unsigned char ret=0;

          unsignedintlen=0;

          1 if(socket(SOCK_WEIBO,Sn_MR_TCP,any_local_port++,0)!=1)//to initialize a TCP socket

          {

          printf("Socket initialization failed.");

          return 0;

          }

          else

          {

          printf("Connect with Weibo server.");

          2ret=connect(SOCK_WEIBO,weibo_server_ip,80);//connect to the weibo server, default TCPport is 80

          if(ret!=1)

          {

          printf("Connect Weibo server failed.");

          return 0;

          }

          else

          {

          3while(getSn_SR(SOCK_WEIBO)!=SOCK_ESTABLISHED);//wait for the TCP connection established!

          printf("Connected with Weiboserver.");

          4sprintf(post_data,"--%sContent-Disposition:form-data; name="id"%s"

          "--%sContent-Disposition:form-data; name="pw"%s"

          "--%sContent-Disposition:form-data; name="cmd"upload"

          "--%sContent-Disposition:form-data; name="status"%s"

          "--%sContent-Disposition:form-data; name="file"; filename="pic.jpg"Content-Type:application/octet-stream",(char*)BOUNDARY,(char*)WEIBO_ID,(char*)BOUNDARY,(char*)WEIBO_PWD,(char*)BOUNDARY,(char*)BOUNDARY,weibo,(char*)BOUNDARY);//"--%s--"

          5sprintf(tmp_buf,"POST %sHTTP/1.1Host: %sUser-Agent: w5500Content-Type: multipart/form-data;boundary=%sConnection:closeContent-Length:%d%s",(char*)HTTP_PATH,(char*)WEIBO_SERVER,(char*)BOUNDARY,strlen(post_data)+picLen+strlen((char*)BOUNDARY)+8,post_data);

          6len=send(SOCK_WEIBO,(unsignedchar*)tmp_buf,strlen(tmp_buf)); //upload your weibo content

          uint16 file_len=picLen;

          uint16 send_len=0;

          while(file_len)

          {

          if(file_len>PACKET_LEN)

          {

          if(getSn_SR(SOCK_WEIBO)!=SOCK_ESTABLISHED)

          {

          return 0;

          }

          7send(SOCK_WEIBO, (uint8*)(pic+send_len), PACKET_LEN);// upload picture

          send_len+=PACKET_LEN;

          file_len-=PACKET_LEN;

          }

          else

          {

          8send(SOCK_WEIBO, (uint8*)(pic+send_len), file_len);// uploadpicture

          send_len+=file_len;

          file_len-=file_len;

          }

          }

          sprintf(tmp_buf,"--%s--",(char*)BOUNDARY);

          send(SOCK_WEIBO,(unsigned char*)tmp_buf,strlen(tmp_buf));

          while(1)

          {

          9len=getSn_RX_RSR(SOCK_WEIBO);

          if(len>0)

          {

          memset(tmp_buf,0x00,MAX_BUF_SIZE);

          10len=recv(SOCK_WEIBO,(unsigned char*)tmp_buf, len);//receive thereturn result from weibo server

          11char*p=strstr(tmp_buf,(char*)"")+4;//gethttp payload without http headerprintf("%s",p);

          disconnect(SOCK_WEIBO);//disconnect with weibo server

          close(SOCK_WEIBO);//close the socket

          return 1;//sucess! return 1

          }

          }

          }

          }

          }

          發(fā)送微博函數(shù)的第1行,初始化一個socket,第2行,對服務器發(fā)出連接請求,第3行一直等待連接的建立。與服務器建立連接后,第4,5行負責組建帶有微博內容和圖片長度的HTTP數(shù)據(jù)包,第6行負責發(fā)送微博內容,第7,8行發(fā)送圖片數(shù)據(jù)。第9行是讀取W5500接收到的數(shù)據(jù)長度,第10行從W5500的接收緩存中把接收到的數(shù)據(jù)讀到tmp_buf中。由于接收到的數(shù)據(jù)包含了HTTP頭,第11行是把HTTP頭去掉,得到服務器的返回結果。服務器返回結果的類型請參看《為你的設備添加社交網(wǎng)絡功能》一文。

          好了,代碼就這么多,趕快編譯燒到單片機里面吧,上電,對著麥克風說出一句已經(jīng)寫到LD3320里的話,當對應的指示燈亮或者閃爍,說明已經(jīng)識別成功,然后對著攝像頭微笑吧,這時攝像頭為我們拍張照片,上傳微博,然后看串口調試信息,如果收到“255:ok”,那就成功了,登錄到微博看看,寫進程序里的話以及自己的照片出現(xiàn)在微博上面。如圖11。

          圖11系統(tǒng)發(fā)送微博效果圖

          至此,我們的基于語音識別的微博簽到系統(tǒng)已經(jīng)大功告成,你心動了嗎?趕快制作你自己的微博簽到系統(tǒng)吧。


          上一頁 1 2 下一頁

          評論


          技術專區(qū)

          關閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();