1. 程式人生 > 其它 >飛思卡爾KL36和LD3320結合的語音識別系統

飛思卡爾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;
	}
}

識別不準確的問題

能識別之後,發現,識別非常的不準確,新增垃圾詞之後,勉強能準確那麼一點,但是有時候甚至開燈識別到關燈,這個的話後期經過調整語音監測點暫存器應該能好點,或者說,這個晶片就是識別的這麼不準確,那就沒辦法了

Alt