飛思卡爾KL36和LD3320結合的語音識別系統
KL36和LD3320結合的語音識別系統
前言
在網上買的LD3320一般都是STM32或者STC或者Arduino的,沒有比較冷門的板子,比如飛思卡爾的M+系列或者KL系列,但是我學的又是這些冷門的板子,所以進行了移植,現在算是移植成功了,移植過程遇到了許多問題,來分享一下
兩個板子之間的通訊原理
首先我們要知道他的通訊原理,就是一句話,通過讀或者寫LD33320的暫存器來進行對控制,具體的暫存器可以檢視LD3320的開發手冊,讀和寫暫存器有兩種方式,我們常用的就是用SPI通訊,所以剛一開始遇到的問題就是不能正常讀取暫存器,通過查詢問題發現,是SPI通訊的問題。
SPI通訊遇到的問題
1.讀取暫存器的值為0
首先我們要理解SPI通訊的原理,具體的通訊機制可以上網查,我這裡最後理解的是,在接受資料的時候,主不能沒事幹,只充當一個接收者,也要傳送資料,才能接收到資料,因為KL36板子的spi提供的驅動函式把傳送函式和接收函式是分開的,所以當初一直讀取暫存器為0,頭疼了幾天,最後把兩個函式結合起來,在讀取暫存器函式裡面也要傳送0x00過去,就能正常讀取到暫存器的值了。要注意的是要把CPOL=0,CPHA=1
根本不用進入到SPI中斷拿返回值(KDS提供的中斷都會統一寫在isr.c檔案)
當初也一直以為中斷拿返回值卡了很久
static uint_8 spi_send_byte(uint_8 No, uint_8 data)
{
SPI_MemMapPtr baseadd=SPI_baseadd(No);
while(!(SPI_S_REG(baseadd)&SPI_S_SPTEF_MASK));//等待發送緩衝區空閒
SPI_DL_REG(baseadd)=data;//資料暫存器接收資料
while(!(SPI_S_REG(baseadd)& SPI_S_SPRF_MASK)); //檢測SPI是否收到了資料。
return SPI_DL_REG(baseadd);
}
unsigned char LD_ReadReg( unsigned char address )
{
uint_8 i;
gpio_set(WR, 0);
gpio_set(GEC_22, 0);
spi_send_byte(SPIB,0x05); // 傳送 0x05
spi_send_byte(SPIB,address); // 傳送 address
i=spi_send_byte(SPIB,0x00);
gpio_set(GEC_22, 1);
return i;
}
關於初始化的配置遇到的問題
我們要對一些引腳進行初始化,這些也是我遇到的一些問題
1 初始化了SPIB之後,執行不下去
KL36提供了兩組SPI,當我想使用SPIB進行通訊時,發現程式執行不下去了,但是當我把兩組都初始化之後,就能正常執行下去了,所以應該是要把全部的SPI都進行初始化,才能使用,不知道是不是所有的微控制器都是這樣。
解決方法:把兩組SPI都進行初始化
gpio_init(GEC_31,0,0); //設定SS為輸入
spi_init(SPIA,1,6000,0,0); //初始化SPI0為主機
spi_init(SPIB,1,1500,0,1); //初始化SPI1為主機
gpio_init(GEC_22,1,0); //設定SS為輸入 連LD的CS
2 不能將CS片選訊號進行控制,就是輸出高電平還是低電平
我們知道,SPI通訊有一根線是CS片選訊號,對LD3320進行通訊的時候,要求CS片選訊號是低電平,但是我們利用get獲取引腳電平或者軟體模擬的時候,發現CS引腳總是高電平,就算是用函式輸出低電平還是一樣,經過研究發現,改引腳在SPI_init的時候,把引腳設定為了輸入,所以才總是高電平,控制不了,但是要求是低電平
解決方法:在SPI初始化之後,再將引腳複用為GPIO,輸出,就可以對引腳進行輸出高低電平的控制了
執行的時候遇到的問題
在能正常讀取暫存器之後,以為就能很快進行語音的控制了,但是又遇到了一大堆問題,卡了好幾天
1 不能多次迴圈識別,燒錄進去之後只能執行一次
這個的問題就是不能回到主函式執行迴圈體,當時以為是LD3320不能多次產生中斷,或者是以為退出不了中斷處理程式,因此還加了恩智浦的討論群,後來發現其實不是這樣,這個模組是隻要有聲音,就會產生中斷,多次試驗後發現,是自己寫的中斷出問題了
解決方法:直接在中斷裡面寫開發手冊寫好的中斷,然後自己在關外部中斷開外部中斷
void GPIOB_Handler(void)
{
ProcessInt0();
gpio_clear_int(IRQ);
gpio_reverse(LIGHT_RED);
ENABLE_INTERRUPTS;
}
2 中斷處理函式得到LD3320當前狀態後,不能將LD_ASR_FOUNDOK返回值給主函式,case到然後執行處理函式
這個問題其實是和上面的那個問題結合起來的,所以當時不知道是哪裡出了問題,明明產生中斷了並且識別成功有正確返回值了,但是回到主函式之後就是不能被case到LD_ASR_FOUNDOK,就非常納悶,正常的流程就應該獲取結果然後進行引腳操作,後來參考了別人的程式,
解決方法:執行函式是在switch和while之前插入一個執行函式,就能進入到LD_ASR_FOUNDOK裡面並且能迴圈執行了,非常奇怪,然後自己寫了一個
介面函式
}//switch
control(nAsrRes);//這裡插入
}//while
static void control(uint_8 Coad_val)
{
switch(Coad_val)
{
case 1:
gpio_set(LIGHT_GREEN, LIGHT_ON);
break;
case 3:
gpio_set(LIGHT_GREEN, LIGHT_OFF);
break;
default:
break;
}
}
識別不準確的問題
能識別之後,發現,識別非常的不準確,新增垃圾詞之後,勉強能準確那麼一點,但是有時候甚至開燈識別到關燈,這個的話後期經過調整語音監測點暫存器應該能好點,或者說,這個晶片就是識別的這麼不準確,那就沒辦法了