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

相关推荐
hollq12 小时前
STM32F103RCT6+STM32CubeMX+keil5(MDK-ARM)+Flymcu实现串口重定向
arm开发·stm32·嵌入式硬件
小鱼儿电子14 小时前
17-基于STM32的宠物饲养系统设计与实现
stm32·嵌入式硬件·物联网·宠物·宠物饲养系统
小莞尔15 小时前
【51单片机】【protues仿真】基于51单片机四层电梯系统
单片机·嵌入式硬件
CFZPL15 小时前
使用江科大串口发送函数发送freertos的vTaskList出现跑飞
单片机
F1331689295716 小时前
WD5030A,24V降5V,15A 大电流,应用于手机、平板、笔记本充电器
stm32·单片机·嵌入式硬件·51单片机·硬件工程·pcb工艺
易享电子17 小时前
基于单片机电器断路器保护器系统Proteus仿真(含全部资料)
单片机·嵌入式硬件·fpga开发·51单片机·proteus
爱倒腾的老唐20 小时前
01、如何学习单片机
单片机·嵌入式硬件·学习
点灯小铭20 小时前
基于单片机的夹具压力控制系统设计
单片机·嵌入式硬件·mongodb·毕业设计·课程设计
雾削木1 天前
stm32解锁芯片
javascript·stm32·单片机·嵌入式硬件·gitee
热爱编程的小刘1 天前
STM32学习路线开启篇:外部中断
stm32