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

第三章 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 */}
}

http://www.xdnf.cn/news/5198.html

相关文章:

  • 【Web】LACTF 2025 wp
  • 虚拟机风格
  • OpenLayers根据任意数量控制点绘制贝塞尔曲线
  • 关于甲骨文(oracle cloud)丢失MFA的解决方案
  • vim的配置
  • C++(6):逻辑运算符
  • AI 驱动的开发工具
  • 中国古代史1
  • 【ML-Agents】ML-Agents示例项目导入unity报错解决
  • 当冲压焊接遇上Canopen到Profinet协议转换网关
  • 4.分布式锁
  • C++进阶--AVL树的实现续
  • HC-SR04超声波测距传感器
  • Doris和Clickhouse对比
  • 视觉革命来袭!ComfyUI-LTXVideo 让视频创作更高效
  • Kotlin知识体系(七) : Flow线程控制、状态管理及异常处理指南
  • 每日脚本学习5.10 - XOR脚本
  • SSH终端登录与网络共享
  • AI与机器人学:从SLAM到导航的未来
  • HTTP/3展望、我应该迁移到HTTP/2吗
  • 【Linux】线程的同步与互斥
  • 物联网之使用Vertx实现MQTT-Server最佳实践【响应式】
  • 互联网大厂Java面试实录:Spring Boot与微服务架构在电商场景中的应用解析
  • MIT XV6 - 1.4 Lab: Xv6 and Unix utilities - find
  • vllm笔记
  • Linux510 ssh服务 ssh连接
  • 数学证明 | 逻辑的力量
  • 每天五分钟机器学习:拉格朗日对偶函数
  • 2025年渗透测试面试题总结-渗透测试红队面试三(题目+回答)
  • Pandas:数据处理与分析