当前位置: 首页 > news >正文

第三章 Freertos智能小车遥控控制

        本文基于小车APP,通过与蓝牙模块进行连接,发送特定信号给小车主控,实现对小车的模式切换、灯光控制、前进、后退、左右控制。目前还未加入电机控制,具体的电机控制效果还不能实现,但是可以进行模式切换与灯光控制
        这里先将对应的代码和手机APP进行开源,并进行效果展示。资料下载

         这里对于APP的设计和Freertos不过多赘述,有兴趣的通过这篇文章进行跳转回顾前期的内容:零基础制作Freertos智能小车(教程非常简易)

1.蓝牙连接

        这里采用的是蓝牙与单片机连接的方式,这里希望大家能从第一章的教程一路看过来,方便进行学习以及器件买哪种。APP已经放在文章的开头,方便大家直接下载。
        大家蓝牙模块按照下面的方式进行接线,电源的话选择3.3v-5.5v的。

/*********************蓝牙模块*********************/
//USART1_TX PA9     USART1_RX  PA10

        蓝牙连接成功后, 可以先进行上电测试,一般蓝牙未与手机进行连接时,蓝牙模块始终处于闪烁的状态,手机与蓝牙模块连接成功后,蓝牙模块的指示灯会变成常亮的状态。以下是具体的连接过程。蓝牙的模块根据商家的不同,可能会略有不同,可能是1234或者0000

 2.串口通信(stm32)

        这里如果没有串口通信基础的同学建议先看下这篇文章,看完以后能帮助大家更快的了解和学习串口协议:串口通信(基于stm32)
        当手机APP发送指令到下位机的时候,会有一个信息的流转,首先发送给蓝牙模块,蓝牙模块在通过串口协议将APP的内容传给stm32。stm32的串口中断将信息存储到了USART_RX_BUF中。

void USART1_IRQHandler(void)                	//蓝牙信号接收中断
{static uint8_t Serial_RxState = 0;		//定义表示当前状态机状态的静态变量static uint8_t Serial_pRxPacket = 0;	//定义表示当前接收数据位置的静态变量if (USART_GetITStatus(USART1, USART_IT_RXNE) == SET){uint8_t Serial_RxData  = USART_ReceiveData(USART1);if (Serial_RxState == 0){if (Serial_RxData == '@' && USART_RxFlag == 0)		//如果数据确实是包头,并且上一个数据包已处理完毕{Serial_RxState = 1;			//置下一个状态Serial_pRxPacket = 0;			//数据包的位置归零}}/*当前状态为1,接收数据包数据,同时判断是否接收到了第一个包尾*/else if (Serial_RxState == 1){if (Serial_RxData == '#')			//如果收到第一个包尾{Serial_RxState = 0;			//状态归0USART_RX_BUF[Serial_pRxPacket] = '\0';			//将收到的字符数据包添加一个字符串结束标志USART_RxFlag = 1;		//接收数据包标志位置1,成功接收一个数据包Handle_Msg(USART_RX_BUF);}else						//接收到了正常的数据{USART_RX_BUF[Serial_pRxPacket] = Serial_RxData;		//将数据存入数据包数组的指定位置Serial_pRxPacket ++;			//数据包的位置自增}}USART_ClearITPendingBit(USART1, USART_IT_RXNE);}
}

        当我们将这批的信息处理完成后,则需要将信息进行二次的处理。通过LED[0]、LED[1]控制灯光,Mode控制模式,Contral控制电机转向(开发中...)

/*
*************************************************************************
*                             全局变量
*************************************************************************
*/
int Led[2]={0,0};//数组0代表红灯,数组1代表蓝灯,数值为0时关闭灯,1时开启灯光
/*//为模式切换//Mode == 0 避障//Mode == 1	遥控//Mode == 2 跟随//Mode == 3 循迹
*/
int Mode=1;
/*//控制转向//Contral == F 	前进//Contral == B  后退//Contral == L  左转//Contral == R  右转//Contral == S  停止
*/
char Contral = 'S';void Handle_Msg(char *str) //当蓝牙接收完app的信息以后,统一进入此处进行处理
{if(USART_RxFlag == 1){if (strstr(str, "RED") || strstr(str, "red") || strstr(str, "BLUE") || strstr(str, "blue")){if(strstr(str, "RED"))Led[0] = 1;else if(strstr(str, "red"))Led[0] = 0;else if(strstr(str, "BLUE"))Led[1] = 1;else if(strstr(str, "blue"))Led[1] = 0;}else if(strstr(str, "G")){Mode = 2;//Oled_Show_Image(2);}else if(strstr(str, "X")){Mode = 3;//Oled_Show_Image(0);}else if(strstr(str, "D")){Mode = 0;//Oled_Show_Image(2);}else if(strstr(str, "Y")){Mode = 1;//Oled_Show_Image(1);}else if(strstr(str, "F")){Contral = 'F';}else if(strstr(str, "B")){Contral = 'B';}else if(strstr(str, "L")){Contral = 'L';}else if(strstr(str, "R")){Contral = 'R';}else if(strstr(str, "S")){Contral = 'S';}USART_RxFlag = 0;}
}

3.利用Freertos创建Red_Blue_LED_Task控制小灯任务

        创建的任务过程可以先参考第一章 Freertos入门介绍
        首先我们创建任务句柄

/**************************** 任务句柄 ********************************/
/* * 任务句柄是一个指针,用于指向一个任务,当任务创建好之后,它就具有了一个任务句柄* 以后我们要想操作这个任务都需要通过这个任务句柄,如果是自身的任务操作自己,那么* 这个句柄可以为NULL。*/
static TaskHandle_t AppTaskCreate_Handle = NULL;/* 创建任务句柄 */
static TaskHandle_t Red_Blue_LED_Task_Handle = NULL;/* 蓝灯任务句柄 */

        下一步我们要 编辑AppTaskCreate任务,并在AppTaskCreate创建Red_Blue_LED_Task任务,并配置好任务入口函数、任务名字、任务栈大小、任务入口函数参数、任务的优先级、任务控制块指针。

/************************************************************************ @ 函数名  : AppTaskCreate* @ 功能说明: 为了方便管理,所有的任务创建函数都放在这个函数里面* @ 参数    : 无  * @ 返回值  : 无**********************************************************************/
static void AppTaskCreate(void)
{BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */taskENTER_CRITICAL();           //进入临界区/* 创建Blue_LED_Task任务 */xReturn = xTaskCreate((TaskFunction_t )Red_Blue_LED_Task, /* 任务入口函数 */(const char*    )"Red_Blue_LED_Task",/* 任务名字 */(uint16_t       )512,   /* 任务栈大小 */(void*          )NULL,	/* 任务入口函数参数 */(UBaseType_t    )2,	    /* 任务的优先级 */(TaskHandle_t*  )&Red_Blue_LED_Task_Handle);/* 任务控制块指针 */if(pdPASS == xReturn)//printf("创建Blue_LED_Task任务成功!\r\n");vTaskDelete(AppTaskCreate_Handle); //删除AppTaskCreate任务taskEXIT_CRITICAL();            //退出临界区
}

        接着我们要编辑Red_Blue_LED_Task任务入口函数的内容,通过数组LED来判断红灯和蓝灯的亮灭状态,并每隔100ms进入该任务进行轮询。

/*********************************************************************** @ 函数名  : Red_Blue_LED_Task* @ 功能说明: Red_Blue_LED_Task* @ 参数    :   * @ 返回值  : 无********************************************************************/
static void Red_Blue_LED_Task(void* parameter)
{	while (1){if(Led[0] == 1)Red_ONelse if(Led[0] == 0)Red_OFFif(Led[1] == 1)Blue_ONelse if(Led[1] == 0)Blue_OFFvTaskDelay(100);   /* 延时100个tick */}
}

相关文章:

  • 互联网大厂Java面试实录:Spring Boot与微服务架构在电商场景中的应用解析
  • 21.【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--单体转微服务--身份认证服务拆分规划
  • diy装机成功录
  • C++ learning day 02
  • day010-命令实战练习题
  • 第一个SpringBoot程序
  • 软考中级数据库备考-上午篇
  • Spark的三种部署模式及其特点与区别
  • Autoware播放提示音
  • 基于Spring Boot + Vue的高校心理教育辅导系统
  • adb命令查询不到设备?
  • QTableWidget实现多级表头、表头冻结效果
  • 模型 启动效应
  • WPF之集合绑定深入
  • 配置高级相关
  • 深入理解卷积神经网络的输入层:数据的起点与预处理核心
  • SpringBoot项目容器化进行部署,meven的docker插件远程构建docker镜像
  • [杂谈随感-13]: 人的睡眠,如何布置床的位置比较有安全?感?
  • java命令行打包class为jar并运行
  • 基于人工智能的个性化 MySQL 学习路径推荐研究
  • 巴防空系统击落印度无人机,印称巴方违反停火协议
  • 巴基斯坦外长:印巴已同意立即停火
  • 这座古村,藏着多少赣韵风华
  • 中俄弘扬正确二战史观:缅怀历史,重拾初心,阻止悲剧重演
  • 山东14家城商行中,仅剩枣庄银行年营业收入不足10亿
  • 国博馆刊|北朝至唐初夏州酋豪李氏家族的发展与身份记忆