2022年十月份电赛OpenMV巡线方案(2)---主控代码详细分析
前言
(1)继上一篇:2022年十月份电赛OpenMV巡线方案详细代码分析(1)
(2)这个代码适用于所有主控,只需要更改一下串口接收部分的API,别问我某某MCU能不能跑的这种废话!
(3)本文使用的协议与正点原子的串口通讯协议一致,看不懂的建议学一下正点原子的那个串口通讯协议。
(4)==最后强调一边:本文的代码是伪代码!也就是说,不能够直接使用!需要灵活变更!==
主控代码及讲解
main.c
(1)我们OpenMV的数据最终会存放在16bit_state.state和5bit_state.state。16bit_state.state存放横向16bit的数据,5bit_state.state存放右侧的5bit的数据。我们可以根据这个参数来判断不同的情况。
(2)需要注意的一点是,每次OpenMV_data_read()函数之后,16bit_state.state和5bit_state.state这两个数据才会更新。否则一直是一个数值。
(3)OpenMV_data_read()函数有一个返回值,如果有数据更新,那么就会返回1,没有数据更新就会返回0。你们可以根据自己的需求看要不要利用上这个返回值。
#include "bsp_OpenMV.h"
void main()
{
while(1)
{
OpenMV_data_read(); //读取OpenMV的数据,有返回值,但是我没有进行处理
switch(16bit_state.state) //OpenMV横向16个数据的处理
{
case 0x01:
break;
case 0x02:
break;
default:
break;
}
switch(5bit_state.state) //OpenMV纵向5个数据的处理
{
case 0x01:
break;
case 0x02:
break;
default:
break;
}
}
}
user_interrupt.c
(1)我一般喜欢用一个user_interrupt.c文件存放所有的中断程序。
(2)这里你只需要做一件事情,将获得到8bit数据传入OpenMV_agreement_receive()函数里面。
#include "bsp_OpenMV.h"
void UARTx_IRQHandler(void)
{
//...是你这一款MCU的串口接收函数
uint8_t UARTx_recevie= ...;
//将接收到的数据进行协议处理
OpenMV_agreement_receive(UARTx_recevie);
}
bsp_OpenMV.h
#ifndef _bsp_openmv__H
#define _bsp_openmv__H
/***** 参数宏定义 *******/
#define USART_REC_LEN 5 //定义最大接收字节数 5
/***** 变量外部使用声明 *******/
extern _gray_state 16bit_state,5bit_state; //用于记录OpenMV传输过来的值
/***** 结构体声明 *******/
typedef struct
{
uint8_t bit1 :1;
uint8_t bit2 :1;
uint8_t bit3 :1;
uint8_t bit4 :1;
uint8_t bit5 :1;
uint8_t bit6 :1;
uint8_t bit7 :1;
uint8_t bit8 :1;
uint8_t bit9 :1;
uint8_t bit10 :1;
uint8_t bit11 :1;
uint8_t bit12 :1;
uint8_t bit13 :1;
uint8_t bit14 :1;
uint8_t bit15 :1;
uint8_t bit16 :1;
}gray_flags; //位域,将黑线信息都存放进一个16bit的数据中
typedef union //共用体,可以利用这两个值来判断巡线状态
{
gray_flags gray;
uint16_t state;
}_gray_state;
/***** 函数声明 *******/
void OpenMV_agreement_receive(uint8_t OpenMV_recevie); //OpenMV数据协议
int OpenMV_receive_if_finish(void); //判断是否与OpenMV通讯完成
int OpenMV_data_read(void); //读取OpenMV的值
#endif
bsp_OpenMV.c
(1)OpenMV_data_read()这个c文件,我们只需要关注这个函数。
<1>因为2022年十月份电赛OpenMV巡线方案详细代码分析(1)中设置了,OpenMV会给主控发送3个字节数据。所以我这里的OpenMV_receive_if_finish() == 3进行判断,看看是否接收到了3个字节数据。如果不是3个字节的数据,那么就说明数据传输未完成,或者是出现了问题。
<2> 因为上一篇文章里面,OpenMV是先传输高8位的数据,所以这里需要USART_RX_BUF[0] << 8,然后再‘|’。
<3>依旧是要根据上一篇文章,我们知道第三个数据才是右侧横向5bit数据,所以5bit.state = USART_RX_BUF[2];
<4>数据处理完之后,需要清空标志位USART_RX_STA。
(2)这里的OpenMV_receive_if_finish()函数和OpenMV_agreement_receive()不要进行更改!我已经给你们封装好了,如果看不懂的,请自己去看正点原子的串口通讯教程!
(3)USART_RX_STA是标志位,用于存放如下注释中的数据。因为我已经使用OpenMV_receive_if_finish()函数进行了封装,所以这个常量你不知道没有事情。
/*
=============================================================================================================
USART_RX_STA
=============================================================================================================
bit15 | bit14 | bit13--bit0
=============================================================================================================
接收完成标志位(0x0A,换行键) | 接收到0x0d(回车键) | 接收到的有效数据个数
=============================================================================================================
*/
uint16_t USART_RX_STA = 0; //接收状态标记
uint8_t USART_RX_BUF[USART_REC_LEN] = {0}; //存放接收到的OpenMV数据
/* 作用 : OpenMV数据协议
* 传入参数 :
OpenMV_recevie : 将串口接受中断的uint8_t数据传入
* 返回参数 : 无
*/
void OpenMV_agreement_receive(uint8_t OpenMV_recevie)
{
if((USART_RX_STA&0x8000)==0) //bit15没有被置为1,接收未完成
{
if(USART_RX_STA&0x4000) //bit14被置为1,表示接收到了'\n'(0x0d)
{
if((OpenMV_recevie)!=0x0a)USART_RX_STA=0; //如果bit14被置1了,但是bit15并不是换行操作,表示接收错误,重新开始
else USART_RX_STA|=0x8000; //接收完成了
}
else //还没收到'\n'(0x0d)
{
if((OpenMV_recevie)==0x0d)USART_RX_STA|=0x4000; //如果接收到了'\n'(0x0d),bit14被置为1
else
{
USART_RX_BUF[USART_RX_STA&0x3FFF]=OpenMV_recevie; //如果没有接收到结束标志,继续将数据写入USART_RX_BUF[]
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0; //如果接收到的数据大于定义最大接收字节数,表示接收数据错误,重新开始接收
}
}
}
}
/* 作用 : 判断是否与OpenMV通讯完成
* 传入参数 : 无
* 返回参数 : 如果与OpenMV通讯完成,返回接收到的字符数量。否则返回0
*/
int OpenMV_receive_if_finish(void)
{
if(USART_RX_STA & 0x8000) //如果接收完成
{
return USART_RX_STA&0x3fff;
}
return 0; //没有接收完成返回错误
}
/* 作用 : 读取OpenMV的数据
* 传入参数 : 无
* 返回参数 : 如果成功读取到了数据,返回1。否则返回0。
*/
_gray_state 16bit_state,5bit_state; //用于记录OpenMV传输过来的值
int OpenMV_data_read(void)
{
if(OpenMV_receive_if_finish() == 3)//如果串口接收到三个数据,表示OpenMV发送数据完成
{
16bit.state = (USART_RX_BUF[0] << 8 | (USART_RX_BUF[1])); //处理OpenMV的横线16路数据
5bit.state = USART_RX_BUF[2]; //处理OpenMV的纵线5路数据
USART_RX_STA=0; //标志位清零
return 1;
}
return 0;
}
总结
(1)你需要变动的地方
<1>user_interrupt.c的串口中断里面,写入当前MCU的串口接收函数。
<2>OpenMV_data_read()根据需求进行调整。
<3>看看main.c,根据需求编写main.c
- 点赞
- 收藏
- 关注作者
评论(0)