本文主要是介绍STM32智能小车—蓝牙控制并测速小车、wife控制小车、4g控制小车、语音控制小车,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
1. 蓝牙控制小车
2. 蓝牙控制并测速小车
3. wifi控制测速小车
4. 4g控制小车
5.语音控制小车
5.1语音模块配置:
5.2 语音控制小车开发和调试代码
1. 蓝牙控制小车
- 使用蓝牙模块,串口透传
- 蓝牙模块,又叫做蓝牙串口模块
串口透传技术:
- 透传即透明传送,是指在数据的传输过程中,通过无线的方式这组数据不发生任何形式的改变,仿 佛传输过程是透明的一样,同时保证传输的质量,原封不动地到了最终接收者手里。
- 以太网,蓝牙,Zigbee, GPRS 等模块玩法一样,对嵌入式程序员来说,不需要关心通讯模块内部数据 及协议栈工作原理,只要通过串口编程获得数据即可
代码实现:
整合前面串口控制小车代码,接入蓝牙模块
if (!strcmp(UART1_RX_Buffer, "M1"))
{goForward();HAL_Delay(10);
}
else if (!strcmp(UART1_RX_Buffer, "M2"))
{goBack();HAL_Delay(10);
}
else if (!strcmp(UART1_RX_Buffer, "M3"))
{goLeft();HAL_Delay(10);
}
else if (!strcmp(UART1_RX_Buffer, "M4"))
{goRight();HAL_Delay(10);
}
elsestop();
2. 蓝牙控制并测速小车
原理:
使用蓝牙模块和测速模块,将两者代码整合
代码实现:
usart.c
#include "usart.h"#include "string.h"
#include "stdio.h"
#include "motor.h"//串口接收缓存(1字节)
uint8_t buf=0;//定义最大接收字节数 200,可根据需求调整
#define UART1_REC_LEN 200// 接收缓冲, 串口接收到的数据放在这个数组里,最大UART1_REC_LEN个字节
uint8_t UART1_RX_Buffer[UART1_REC_LEN];// 接收状态
// bit15, 接收完成标志
// bit14, 接收到0x0d
// bit13~0, 接收到的有效字节数目
uint16_t UART1_RX_STA=0;#define SIZE 12char buffer[SIZE];// 接收完成回调函数,收到一个数据后,在这里处理
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{// 判断中断是由哪个串口触发的if(huart->Instance == USART1){// 判断接收是否完成(UART1_RX_STA bit15 位是否为1)if((UART1_RX_STA & 0x8000) == 0){// 如果已经收到了 0x0d (回车),if(UART1_RX_STA & 0x4000){// 则接着判断是否收到 0x0a (换行)if(buf == 0x0a){// 如果 0x0a 和 0x0d 都收到,则将 bit15 位置为1UART1_RX_STA |= 0x8000;// 灯控指令if(!strcmp(UART1_RX_Buffer, "M1"))goForward();else if(!strcmp(UART1_RX_Buffer, "M2"))goBack();else if(!strcmp(UART1_RX_Buffer, "M3"))goLeft();else if(!strcmp(UART1_RX_Buffer, "M4"))goRight();elsestop();memset(UART1_RX_Buffer, 0, UART1_REC_LEN);UART1_RX_STA = 0;}else// 否则认为接收错误,重新开始UART1_RX_STA = 0;}else // 如果没有收到了 0x0d (回车){//则先判断收到的这个字符是否是 0x0d (回车)if(buf == 0x0d){// 是的话则将 bit14 位置为1UART1_RX_STA |= 0x4000;}else{// 否则将接收到的数据保存在缓存数组里UART1_RX_Buffer[UART1_RX_STA & 0X3FFF] = buf;UART1_RX_STA++;// 如果接收数据大于UART1_REC_LEN(200字节),则重新开始接收if(UART1_RX_STA > UART1_REC_LEN - 1)UART1_RX_STA = 0;}}}// 重新开启中断HAL_UART_Receive_IT(&huart1, &buf, 1);}
}int fputc(int ch, FILE *f)
{ unsigned char temp[1]={ch};HAL_UART_Transmit(&huart1,temp,1,0xffff); return ch;
}
oled.c
#include "oled.h"
#include "i2c.h"
#include "oledfont.h"void Oled_Write_Cmd(uint8_t dataCmd)
{HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x00, I2C_MEMADD_SIZE_8BIT,&dataCmd, 1, 0xff);
}void Oled_Write_Data(uint8_t dataData)
{HAL_I2C_Mem_Write(&hi2c1, 0x78, 0x40, I2C_MEMADD_SIZE_8BIT,&dataData, 1, 0xff);
}void Oled_Init(void){Oled_Write_Cmd(0xAE);//--display offOled_Write_Cmd(0x00);//---set low column addressOled_Write_Cmd(0x10);//---set high column addressOled_Write_Cmd(0x40);//--set start line address Oled_Write_Cmd(0xB0);//--set page addressOled_Write_Cmd(0x81); // contract controlOled_Write_Cmd(0xFF);//--128 Oled_Write_Cmd(0xA1);//set segment remap Oled_Write_Cmd(0xA6);//--normal / reverseOled_Write_Cmd(0xA8);//--set multiplex ratio(1 to 64)Oled_Write_Cmd(0x3F);//--1/32 dutyOled_Write_Cmd(0xC8);//Com scan directionOled_Write_Cmd(0xD3);//-set display offsetOled_Write_Cmd(0x00);//Oled_Write_Cmd(0xD5);//set osc divisionOled_Write_Cmd(0x80);//Oled_Write_Cmd(0xD8);//set area color mode offOled_Write_Cmd(0x05);//Oled_Write_Cmd(0xD9);//Set Pre-Charge PeriodOled_Write_Cmd(0xF1);//Oled_Write_Cmd(0xDA);//set com pin configuartionOled_Write_Cmd(0x12);//Oled_Write_Cmd(0xDB);//set VcomhOled_Write_Cmd(0x30);//Oled_Write_Cmd(0x8D);//set charge pump enableOled_Write_Cmd(0x14);//Oled_Write_Cmd(0xAF);//--turn on oled panel
}void Oled_Screen_Clear(void){char i,n;Oled_Write_Cmd (0x20); //set memory addressing modeOled_Write_Cmd (0x02); //page addressing modefor(i=0;i<8;i++){Oled_Write_Cmd(0xb0+i); Oled_Write_Cmd(0x00); Oled_Write_Cmd(0x10); for(n=0;n<128;n++)Oled_Write_Data(0x00); }
}void Oled_Show_Char(char row,char col,char oledChar){ //row*2-2unsigned int i;Oled_Write_Cmd(0xb0+(row*2-2)); //page 0Oled_Write_Cmd(0x00+(col&0x0f)); //lowOled_Write_Cmd(0x10+(col>>4)); //high for(i=((oledChar-32)*16);i<((oledChar-32)*16+8);i++){Oled_Write_Data(F8X16[i]); //写数据oledTable1}Oled_Write_Cmd(0xb0+(row*2-1)); //page 1Oled_Write_Cmd(0x00+(col&0x0f)); //lowOled_Write_Cmd(0x10+(col>>4)); //highfor(i=((oledChar-32)*16+8);i<((oledChar-32)*16+8+8);i++){Oled_Write_Data(F8X16[i]); //写数据oledTable1}
}/******************************************************************************/
// 函数名称:Oled_Show_Char
// 输入参数:oledChar
// 输出参数:无
// 函数功能:OLED显示单个字符
/******************************************************************************/
void Oled_Show_Str(char row,char col,char *str){while(*str!=0){Oled_Show_Char(row,col,*str);str++;col += 8; }
}
main.c
extern uint8_t buf;
unsigned int speedCnt = 0;
char speedMes[24]; //主程序发送速度数据的字符串缓冲区void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{if (GPIO_Pin == GPIO_PIN_14)if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_14) == GPIO_PIN_RESET)speedCnt++;
}void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{printf("speed: %d\r\n", speedCnt);sprintf(speedMes,"speed:%2d cm/s",speedCnt);//串口数据的字符串拼装,speed是格子,每个格子1cmOled_Show_Str(2,2,speedMes);speedCnt = 0;
}
3. wifi控制测速小车
- Wifi模块-ESP-01s
- 蓝牙,ESP-01s,Zigbee, NB-Iot等通信模块都是基于AT指令的设计
AT指令介绍:
- AT指令集是从终端设备(Terminal Equipment,TE)或数据终端设备(Data Terminal Equipment,DTE)向终端适配器(Terminal Adapter,TA)或数据电路终端设备(Data Circuit Terminal Equipment,DCE)发送的。
- 其对所传输的数据包大小有定义:即对于AT指令的发送,除AT两个字符外,最多可以接收1056个 字符的长度(包括最后的空字符)。
- 每个AT命令行中只能包含一条AT指令;对于由终端设备主动向PC端报告的URC指示或者response 响应,也要求一行最多有一个,不允许上报的一行中有多条指示或者响应。AT指令以回车作为结 尾,响应或上报以回车换行为结尾。
硬件接线
- 把esp8266插进串口1
使用方法:
Wifi模块-ESP-01s_esp01s波特率-CSDN博客
4. 4g控制小车
原理:运用EC03-DNC4G通信模块
模块介绍:
- 基于串口AT指令的开发方式
- 有两种工作模式,默认是透传模式,通过其他方式进入AT指令模式
- 注意插卡不要出错,下图红色位置为SIM卡状态灯,亮才是正常
代码不做修改,直接基于蓝牙小车整合, 4g模块只要做好外网透传就可以了
5.语音控制小车
5.1语音模块配置:
使用SU-03T / LD3320
具体介绍看我之前写过的博客:SU-03T语音模块的使用_罗小白的干爹的博客-CSDN博客
5.2 语音控制小车开发和调试代码
硬件接线:
循迹小车:
- 循迹模块(左) -- PB3
- 循迹模块(右) -- PB4
跟随小车:
- 跟随模块(左) -- PA8
- 跟随模块(右) -- PA9
避障小车:
- sg90:PB9
- Trig:PA10
- Echo:PA11
OLED模块:
- SCL -- PB6
- SDA -- PB7
语音模块:
- A25 -- PA15 (跟随)
- A26 -- PA13 (避障)
- A27 -- PA14 (循迹)
cubeMX配置
代码示例:
#include "main.h"
#include "i2c.h"
#include "tim.h"
#include "gpio.h"#include "sg90.h"
#include "sr04.h"
#include "motor.h"
#include "oled.h"#define MIDDLE 0
#define LEFT 1
#define RIGHT 2#define BZ 1
#define XJ 2
#define GS 3#define LeftWheel_Value_XJ HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_3)
#define RightWheel_Value_XJ HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4)#define LeftWheel_Value_GS HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8)
#define RightWheel_Value_GS HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_9)#define A25 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15)
#define A26 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_13)
#define A27 HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_14)void SystemClock_Config(void);char dir;void xunjiMode()
{if(LeftWheel_Value_XJ == GPIO_PIN_RESET && RightWheel_Value_XJ == GPIO_PIN_RESET)goForward();if(LeftWheel_Value_XJ == GPIO_PIN_SET && RightWheel_Value_XJ == GPIO_PIN_RESET)goLeft();if(LeftWheel_Value_XJ == GPIO_PIN_RESET && RightWheel_Value_XJ == GPIO_PIN_SET)goRight();if(LeftWheel_Value_XJ == GPIO_PIN_SET && RightWheel_Value_XJ == GPIO_PIN_SET)stop();
}void gensuiMode()
{if(LeftWheel_Value_GS == GPIO_PIN_RESET && RightWheel_Value_GS == GPIO_PIN_RESET)goForward();if(LeftWheel_Value_GS == GPIO_PIN_SET && RightWheel_Value_GS == GPIO_PIN_RESET)goRight();if(LeftWheel_Value_GS == GPIO_PIN_RESET && RightWheel_Value_GS == GPIO_PIN_SET)goLeft();if(LeftWheel_Value_GS == GPIO_PIN_SET && RightWheel_Value_GS == GPIO_PIN_SET)stop();
}void bizhangMode()
{double disMiddle;double disLeft;double disRight;if(dir != MIDDLE){sgMiddle();dir = MIDDLE;HAL_Delay(300);}disMiddle = get_distance();if(disMiddle > 35){//前进goForward();}else if(disMiddle < 10){goBack();}else{//停止stop();//测左边距离sgLeft();HAL_Delay(300);disLeft = get_distance();sgMiddle();HAL_Delay(300);sgRight();dir = RIGHT;HAL_Delay(300);disRight = get_distance();if(disLeft < disRight){goRight();HAL_Delay(150);stop();}if(disRight < disLeft){goLeft();HAL_Delay(150);stop();}}HAL_Delay(50);
}int main(void)
{int mark = 0;HAL_Init();SystemClock_Config();MX_GPIO_Init();MX_TIM4_Init();MX_TIM2_Init();MX_I2C1_Init();initSG90();HAL_Delay(1000);dir = MIDDLE;Oled_Init();Oled_Screen_Clear();Oled_Show_Str(2,2,"-----Ready----");while (1){//满足寻迹模式的条件if(A25 == 1 && A26 == 1 && A27 == 0){if(mark != XJ){Oled_Screen_Clear();Oled_Show_Str(2,2,"-----XunJi----");}mark = XJ;xunjiMode();}//满足跟随模式的条件if(A25 == 0 && A26 == 1 && A27 == 1){if(mark != GS){Oled_Screen_Clear();Oled_Show_Str(2,2,"-----GenSui----");}mark = GS;gensuiMode();}//满足避障模式的条件if(A25 == 1 && A26 == 0 && A27 == 1){if(mark != BZ){Oled_Screen_Clear();Oled_Show_Str(2,2,"-----BiZhang----");}mark = BZ;bizhangMode();}}
}
这篇关于STM32智能小车—蓝牙控制并测速小车、wife控制小车、4g控制小车、语音控制小车的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!