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

猜你喜欢

转载自blog.csdn.net/qq_63922192/article/details/131852898