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讲解利用数据

相关推荐
7yewh3 分钟前
嵌入式硬件杂谈(六)充电器原理 线性电源 开关电源 反激电源原理
单片机·嵌入式硬件·mcu·物联网·硬件架构·硬件工程·pcb工艺
秋风&萧瑟19 分钟前
【freertos】FreeRTOS消息队列的介绍与使用
单片机
FlechazoCLF39 分钟前
小柴冲刺软考中级嵌入式系统设计师系列三、嵌入式硬件设计(1)嵌入式系统电源管理
嵌入式硬件
drinow9 小时前
【纸飞机串口调试工具】预设曲线名称
arm开发·驱动开发·单片机·mcu·dsp开发·fpga·iot
时光の尘10 小时前
C语言菜鸟入门·关键字·int的用法
c语言·开发语言·数据结构·c++·单片机·链表·c
深圳市青牛科技实业有限公司 小芋圆11 小时前
【青牛科技】 GC2803:白色家电与安防领域的卓越驱动芯片可替代ULN2803
科技·单片机·嵌入式硬件·电脑·白色家电·电动卷帘门·工业设备
Arciab12 小时前
51单片机入门:LED灯控制(01)
单片机·led·51
LaoZhangGong12313 小时前
Linux第95步_Linux内核中的INPUT子系统
linux·运维·数据库·经验分享·stm32·input·stm32mp127
BreezeJuvenile15 小时前
STM32总体架构简单介绍
stm32·单片机·嵌入式硬件
scgg16 小时前
STM32抢占优先级不生效
stm32·疑问