哦豁,拖贴貌似有段时间了,技术比较垃圾,也不知道写点啥,就凑合着搞点简单的凑凑数吧。最近看到理想的智能汽车车窗语音控制和手势识别控制,于是想了下能不能我也来整活儿一下。于是下面就开始我的表演了。
一、选择LPC55S16作为主控
首先介绍一下LPC55S16BD100的芯片吧,LPC55S16是NXP基于ARM-CortexM33架构,这种新架构的意义主要是兼顾这三个方面。其一,更具完美的性能,LPC55S16的最高频率能够达到150MHz,能够完成很多微控制器使用环境下的高速信息交互。其二,在高频率的环境下运行中更好的实现了低功耗。详细参数请对照下列框图进行解读。
因为能力和时间有限并没有对其中的功能做过多的探索,项目就实现了usart接受离线语音模块的信息反馈、IO口模拟SPI协议使得OLED显示屏进行信息显示、timer做的定时器使得产生PWM方波控制步进电机的方向旋转、以及IO口控制指示灯的显示关断等功能。
二、功能块主要解析
串口波特率115200,使用中断模式进行收发数据。因为离线语音模块串口发出的信息为16进制hex格式,所以本人基于正点原子串口的接收末尾校验理念自己写了一个判断函数。首先对离线语音的功能使用比较少,这里就简单例举一下,其他语义信息也可以根据以上进行仿写,这里就简单的使用了开窗/关窗的语音要义。并付出所使用的两条语音反馈信息:
这里我就用了“打开/关闭第一路”的命令词的串口输出段来进行判断,并给出对应的状态对应:
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显示就是常规的IO口进行模拟的,具体函数以下表现:
#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 //写数据
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);
}
最后就是电机驱动部分,项目中使用了L298N作为电机驱动器对步进电机进行驱动调节。这里电机的路径过程我是用timer来模拟的路径=时间*速度。具体项目中还是需要一个红外开关进行锁合。
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);
三、最终功能实现
通过语音可以对步进电机实行前进后退的控制,以及车窗状态的更新显示。从而达到通过语音实现对车窗的开关控制。