哦豁,拖貼貌似有段時間了,技術(shù)比較垃圾,也不知道寫點啥,就湊合著搞點簡單的湊湊數(shù)吧。最近看到理想的智能汽車車窗語音控制和手勢識別控制,于是想了下能不能我也來整活兒一下。于是下面就開始我的表演了。
一、選擇LPC55S16作為主控
首先介紹一下LPC55S16BD100的芯片吧,LPC55S16是NXP基于ARM-CortexM33架構(gòu),這種新架構(gòu)的意義主要是兼顧這三個方面。其一,更具完美的性能,LPC55S16的最高頻率能夠達到150MHz,能夠完成很多微控制器使用環(huán)境下的高速信息交互。其二,在高頻率的環(huán)境下運行中更好的實現(xiàn)了低功耗。詳細參數(shù)請對照下列框圖進行解讀。
因為能力和時間有限并沒有對其中的功能做過多的探索,項目就實現(xiàn)了usart接受離線語音模塊的信息反饋、IO口模擬SPI協(xié)議使得OLED顯示屏進行信息顯示、timer做的定時器使得產(chǎn)生PWM方波控制步進電機的方向旋轉(zhuǎn)、以及IO口控制指示燈的顯示關(guān)斷等功能。
二、功能塊主要解析
串口波特率115200,使用中斷模式進行收發(fā)數(shù)據(jù)。因為離線語音模塊串口發(fā)出的信息為16進制hex格式,所以本人基于正點原子串口的接收末尾校驗理念自己寫了一個判斷函數(shù)。首先對離線語音的功能使用比較少,這里就簡單例舉一下,其他語義信息也可以根據(jù)以上進行仿寫,這里就簡單的使用了開窗/關(guān)窗的語音要義。并付出所使用的兩條語音反饋信息:
這里我就用了“打開/關(guān)閉第一路”的命令詞的串口輸出段來進行判斷,并給出對應(yīng)的狀態(tài)對應(yīng):
void DEMO_USART_IRQHandler(void)
{
uint8_t data;
/* If new data arrived. */
if ((kUSART_RxFifoNotEmptyFlag | kUSART_RxError) & USART_GetStatusFlags(USART0))
{
data = USART_ReadByte(USART0);
if((rxSta & 0x8000) == 0){
if(rxSta & 0x4000) { // 接收到了0x0d
if(data != 0x16) rxSta = 0; // 接收錯誤,重新接收
else rxSta |= 0x8000; // 接收全部完成
}
else { // 還沒接收到0x0d
if(data == 0x12 || data == 0x11) {
if(data == 0x11) {
status_component_open = false;
status_component_close = true;
}
else if(data == 0x12){
status_component_open = true;
status_component_close = false;
}
rxSta |= 0x4000;
}
else{
demoRingBuffer[rxSta & 0x3fff] = data;
rxSta ++;
if(rxSta > (DEMO_RING_MaxBUFFER_SIZE - 1)) rxSta = 0;
}
}
}
}
然后OLED顯示就是常規(guī)的IO口進行模擬的,具體函數(shù)以下表現(xiàn):
#define oled_sclk_pin 1
#define oled_sdin_pin 2
#define oled_rst_pin 3
#define oled_dc_pin 5
#define oled_cs_pin 26
#define OLED_SCLK_Clr() GPIO_PinWrite(GPIO,1, oled_sclk_pin, 0)//CLK,D0
#define OLED_SCLK_Set() GPIO_PinWrite(GPIO,1, oled_sclk_pin, 1)
#define OLED_SDIN_Clr() GPIO_PinWrite(GPIO,1, oled_sdin_pin, 0)//DIN,D1
#define OLED_SDIN_Set() GPIO_PinWrite(GPIO,1, oled_sdin_pin, 1)
#define OLED_RST_Clr() GPIO_PinWrite(GPIO,1, oled_rst_pin, 0)//RES
#define OLED_RST_Set() GPIO_PinWrite(GPIO,1, oled_rst_pin, 1)
#define OLED_DC_Clr() GPIO_PinWrite(GPIO,1, oled_dc_pin, 0)//DC
#define OLED_DC_Set() GPIO_PinWrite(GPIO,1, oled_dc_pin, 1)
#define OLED_CS_Clr() GPIO_PinWrite(GPIO,0, oled_cs_pin, 0)//CS
#define OLED_CS_Set() GPIO_PinWrite(GPIO,0, oled_cs_pin, 1)
#define OLED_CMD 0 //寫命令
#define OLED_DATA 1 //寫數(shù)據(jù)
void SPI_Init(void)
{
gpio_pin_config_t sclk_config={kGPIO_DigitalOutput,0}; //low
gpio_pin_config_t sdin_config={kGPIO_DigitalOutput,0}; //low
gpio_pin_config_t rst_config= {kGPIO_DigitalOutput,0}; //low
gpio_pin_config_t dc_config= {kGPIO_DigitalOutput,0}; //low
gpio_pin_config_t cs_config= {kGPIO_DigitalOutput,0}; //low
/* Init output LED GPIO. */
GPIO_PinInit(GPIO, 1, oled_sclk_pin, &sclk_config);
GPIO_PinInit(GPIO, 1, oled_sdin_pin, &sdin_config);
GPIO_PinInit(GPIO, 1, oled_rst_pin, &rst_config);
GPIO_PinInit(GPIO, 1, oled_dc_pin, &dc_config);
GPIO_PinInit(GPIO, 0, oled_cs_pin, &cs_config);
}
最后就是電機驅(qū)動部分,項目中使用了L298N作為電機驅(qū)動器對步進電機進行驅(qū)動調(diào)節(jié)。這里電機的路徑過程我是用timer來模擬的路徑=時間*速度。具體項目中還是需要一個紅外開關(guān)進行鎖合。
SCTIMER_GetDefaultConfig(&sctimerInfo);
/* Initialize SCTimer module */
SCTIMER_Init(SCT0, &sctimerInfo);
/* Configure PWM params with frequency 24kHZ from output */
pwmParam.output = DEMO_SCTIMER_OUT;
pwmParam.level = kSCTIMER_HighTrue;
pwmParam.dutyCyclePercent = updatedDutycycle;
if (SCTIMER_SetupPwm(SCT0, &pwmParam, kSCTIMER_CenterAlignedPwm, 24000U, sctimerClock, &eventNumberOutput) ==
kStatus_Fail)
{
return -1;
}
/* Enable interrupt flag for event associated with out 4, we use the interrupt to update dutycycle */
SCTIMER_EnableInterrupts(SCT0, (1 << eventNumberOutput));
/* Receive notification when event is triggered */
SCTIMER_SetCallback(SCT0, SCTIMER_LED_HANDLER, eventNumberOutput);
/* Enable at the NVIC */
EnableIRQ(SCT0_IRQn);
/* Start the 32-bit unify timer */
SCTIMER_StartTimer(SCT0, kSCTIMER_Counter_U);
三、最終功能實現(xiàn)
通過語音可以對步進電機實行前進后退的控制,以及車窗狀態(tài)的更新顯示。從而達到通過語音實現(xiàn)對車窗的開關(guān)控制。