19.4-STM32接收数据-状态显示在屏幕 openMV寻迹与小车控制 Openmv+STM32F103C8T6视觉巡线小车

这个是全网最详细的STM32项目教学视频。

第一篇在这里:

视频在这里

STM32智能小车V3-STM32入门教程-openmv与STM32循迹小车-stm32f103c8t6-电赛 嵌入式学习 PID控制算法 编码器电机 跟随

19.4-STM32接收数据-状态显示在屏幕

先通过串口上位机模拟发送、

STM32有视觉循迹模式、该模式下接收到数据根据状态显示在屏幕上,现在此状态并不控制电机。

复制一下18在上面基础改,命名成19-4_LED

可以先复制到桌面英文路径,防止出现中文路径兼容问题。

看原理图摄像头是预留什么引脚

PCB中可以看到接口位置

所以我们要初始化一下串口二,然后开启串口接收中断

串口2 开启初始化

开启串口中断

生成代码

打开代码

如果发现18章代码经常出现黑屏,那可能就是6050的初始化卡住了,我们可以注释掉一下MPU6050部分的代码。


我们先定义一个串口二接收数据变量

c 复制代码
uint8_t g_ucUsart2ReceiveData;  //保存串口二接收的数据

开启接收中断

c 复制代码
  HAL_UART_Receive_IT(&huart2,&g_ucUsart2ReceiveData,1);  //串口二接收数据

声明一下变量

c 复制代码
extern uint8_t g_ucUsart2ReceiveData;  //保存串口二接收的数据

我们需要在串口中断回调函数中加入我们对接收到数据的解析

c 复制代码
	if(huart == &huart2)//判断中断源 是否来自串口二
	{
		//这里增加解析函数	
		HAL_UART_Receive_IT(&huart2,&g_ucUsart2ReceiveData,1);  //启动串口二接收数据
	}

在usart.c文件中定义一个函数

c 复制代码
/*******************
*  @brief  摄像头串口协议解析函数 可以连接K210或openmv等
*  @param  data:串口接收到的每个字节
*  @return  
*
*******************/
void usartCamera_Receive_Data(uint8_t data)
{
	static uint8_t state = 0;//定义静态static 变量
	
	if(state==0&&data==0xA5) //判断第一个是不是帧头0xA5
	{
		state=1;//是帧头0xA5 赋值state=1 表示接收下一个数据
		//数据存储在数组中 "g_ucUsart2ReceivCounter++",这里是先用后加,比如g_ucUsart2ReceivCounter 初值为0,执行这个是先g_ucaUsart2ReceiveBuffer[0]=data,然后g_ucUsart2ReceivCounter++,即后g_ucUsart2ReceivCounter = 1的
		g_ucaUsart2ReceiveBuffer[g_ucUsart2ReceivCounter++] = data;
	}
	else if(state==1&&data==0xA6) //第二个是不是帧头0xA6
	{
		state=2;//如果第二个是帧头0xA6 赋值state=2 表示接收下一个数据
		g_ucaUsart2ReceiveBuffer[g_ucUsart2ReceivCounter++] = data;//保存数据
	}
	else if(state==2)//然后确定开头是0XA5 0XA6 就开始接收
	{
		g_ucaUsart2ReceiveBuffer[g_ucUsart2ReceivCounter++]=data;
		if(g_ucUsart2ReceivCounter>9||data==0x5B) state=3;  //接收大于9个或者接收到帧尾0X5B 就置位状态三
	}
	else if(state==3) //状态三
	{
		if(g_ucaUsart2ReceiveBuffer[g_ucUsart2ReceivCounter-1] == 0x5B)  //确定 最后一个是不是0x5B帧尾 是帧尾0x5B 就认为通信正确 处理数据
		{
			state = 0;					//这里就可以处理数据了、处理完记得清空数组和重置标志位与计数值
			g_ucUsart2ReceivCounter = 0;//清零计数值
			//比如根据数据设置红外旋转偏移状态

			//1.设置快速 慢速右边 左边 数字存储的变量意义: [0]和[1]:帧头、[2]:摄像头左边数第一个感兴趣区域、[3]:左边第二个、[4]:左边第三个、[5]:左边第四个、[6]:左边第五个、[7]:帧尾
				 if(g_ucaUsart2ReceiveBuffer[6]==0&&g_ucaUsart2ReceiveBuffer[5]==0&&g_ucaUsart2ReceiveBuffer[3]==0&&g_ucaUsart2ReceiveBuffer[2]==0)
				 {
					g_cThisState=0;//前进
					g_lHW_State=22222;//设置这个显示在OLED上方便调试 五个值 以此从左向右表示 从左向右的五个区域
				 }
				 if(g_ucaUsart2ReceiveBuffer[6]==0&&g_ucaUsart2ReceiveBuffer[5]==1&&g_ucaUsart2ReceiveBuffer[3]==0&&g_ucaUsart2ReceiveBuffer[2]==0)
				 {
					g_cThisState=-1;//应该右转
					g_lHW_State=22212;	//表示右数第二个 识别到线
				 }
				 if(g_ucaUsart2ReceiveBuffer[6]==1&&g_ucaUsart2ReceiveBuffer[5]==0&&g_ucaUsart2ReceiveBuffer[3]==0&&g_ucaUsart2ReceiveBuffer[2]==0)
				 {g_cThisState=-2;//快速右转
				 g_lHW_State=22221;
				 }
				 if(g_ucaUsart2ReceiveBuffer[6]==1&&g_ucaUsart2ReceiveBuffer[5]==1&&g_ucaUsart2ReceiveBuffer[3]==0&&g_ucaUsart2ReceiveBuffer[2]==0)
				 {g_cThisState=-3;//快速右转
				 g_lHW_State=22211;
				 }
				 if(g_ucaUsart2ReceiveBuffer[6]==0&&g_ucaUsart2ReceiveBuffer[5]==0&&g_ucaUsart2ReceiveBuffer[3]==1&&g_ucaUsart2ReceiveBuffer[2]==0)
				 {g_cThisState=1;//应该左转
				 g_lHW_State=21222;
				 }
                 if(g_ucaUsart2ReceiveBuffer[6]==0&&g_ucaUsart2ReceiveBuffer[5]==0&&g_ucaUsart2ReceiveBuffer[3]==0&&g_ucaUsart2ReceiveBuffer[2]==1)
				 {g_cThisState=2;//快速左转
				 g_lHW_State=12222;
				 }
                 if(g_ucaUsart2ReceiveBuffer[6]==0&&g_ucaUsart2ReceiveBuffer[5]==0&&g_ucaUsart2ReceiveBuffer[3]==1&&g_ucaUsart2ReceiveBuffer[2]==1)
				 {g_cThisState=3;//快速左转
				 g_lHW_State=11222;
				 }

				//2.然后清空数组
				for(int i=0;i<10;i++) g_ucaUsart2ReceiveBuffer[i]=0x00;//清空数组
				
		}
		else //不是帧尾说明通信错误重新开始接收
		{
			state=0;
			g_ucUsart2ReceivCounter =0;
			for(int i=0;i<10;i++) g_ucaUsart2ReceiveBuffer[i]=0x00;//清空数组
		}
	}
	else
	{	//其他异常清空
		state=0;
		g_ucUsart2ReceivCounter =0;
		for(int i=0;i<10;i++) g_ucaUsart2ReceiveBuffer[i]=0x00;//清空数组
	}
}

然后声明一下变量

c 复制代码
extern int8_t g_cThisState ;//这次状态

定义一个变量 并且在main文件中声明一下

c 复制代码
int g_lHW_State = 0;//帮助视觉调试 用于表示红外对管或者视觉摄像头识别状态

声明一下

c 复制代码
extern int g_lHW_State;//帮助视觉调试 用于表示红外对管或者视觉摄像头识别状态


我们需要再定义模式,这个模式是视觉循迹模式

视觉模式下 我们显示一下,我们之前赋值的变量 以测试我们接收的数据是否正确。

c 复制代码
			//这里编写触发中断后要执行的程序
			if(g_ucMode == 6) g_ucMode = 1;//g_ucMode模式是0 1 2 3 4 5  6
			else
			{
				g_ucMode+=1;
			}

增加模式6,的功能,我们先只显示视觉识别结果

c 复制代码
	if(g_ucMode == 6)
	{
		sprintf((char*)OledString, "lHW:%d  ", g_lHW_State);//视觉识别结果
		OLED_ShowString(0,0,OledString,12);//这个是oled驱动里面的,是显示位置的一个函数,
		motorPidSetSpeed(0,0);//停住电机防止乱跑 方便调试
	}
	

别忘记我们的解析函数,加到串口中断处理函数中

c 复制代码
		usartCamera_Receive_Data(g_ucUsart2ReceiveData);

修改上面程序经过测试,单片机

编译上面程序,并烧录到我们的单片机、单片机连接到电脑、然后电脑模拟openmv发送正确格式的数据,手动点击SSCOM发送数据、单片机可以接收到数据并显示在OLED上(观察的是OLED的第一行数值变化)、当我们设置每1ms发送一次数据时候,单片机的OLED有时候会出现卡死的情况。所以是单片机串口接收大量数据卡死的情况,经过网上搜索发现解决问题的办法。

**这个博客是搜索到可以解决问题的链接:**https://blog.csdn.net/qq_44629109/article/details/131002223

参考博客如下部分:

所以我们要更改如下代码:

c 复制代码
  __HAL_UART_ENABLE_IT(&huart2, UART_IT_ERR);// 启用UART2的错误中断功能

在USART.C 中添加如下代码

c 复制代码
/* UART 错误回调函数 处理串口错误 */
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
    if(__HAL_UART_GET_FLAG(huart,UART_FLAG_ORE) != RESET) //使用__HAL_UART_GET_FLAG宏检查UART的overrun错误标志位是否被置位。如果返回值不等于RESET,表示overrun错误标志位被置位,即发生了overrun错误
    {
        __HAL_UART_CLEAR_OREFLAG(huart);//使用__HAL_UART_CLEAR_OREFLAG宏清除UART的overrun错误标志位
        HAL_UART_Receive_IT(&huart2,&g_ucUsart2ReceiveData,1);  //使用HAL库函数启动UART2接收中断,并设置接收缓冲区的大小为1字节
    }
}

添加串口2接收变量的声明

c 复制代码
extern uint8_t g_ucUsart2ReceiveData;  //保存串口二接收的数据

让单片机处于模式6(按六下 KEY1)

上面我们测试通过上位机发送数据,然后观察屏幕。

然后我们把STM32底板接到openmv,openmv连接电脑,openmv使用的程序是19章3节的程序19-3-openmv

然后上面如果没有问题,就可以把openmv 程序通过"将打开的脚本保存到openmv Cam(作为main.py)"

接法如下:

这里就说明了如何接受的数据,后面的19.5讲解利用数据

相关推荐
来自晴朗的明天4 小时前
16、电压跟随器(缓冲器)电路
单片机·嵌入式硬件·硬件工程
钰珠AIOT5 小时前
在同一块电路板上同时存在 0805 0603 不同的封装有什么利弊?
嵌入式硬件
代码游侠5 小时前
复习——Linux设备驱动开发笔记
linux·arm开发·驱动开发·笔记·嵌入式硬件·架构
代码游侠16 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
xuxg200518 小时前
4G 模组 AT 命令解析框架课程正式发布
stm32·嵌入式·at命令解析框架
CODECOLLECT19 小时前
京元 I62D Windows PDA 技术拆解:Windows 10 IoT 兼容 + 硬解码模块,如何降低工业软件迁移成本?
stm32·单片机·嵌入式硬件
BackCatK Chen20 小时前
STM32+FreeRTOS:嵌入式开发的黄金搭档,未来十年就靠它了!
stm32·单片机·嵌入式硬件·freertos·低功耗·rtdbs·工业控制
全栈游侠1 天前
STM32F103XX 02-电源与备份寄存器
stm32·单片机·嵌入式硬件
Lsir10110_1 天前
【Linux】中断 —— 操作系统的运行基石
linux·运维·嵌入式硬件