2022年十月份电赛OpenMV巡线方案(2)---主控代码详细分析

简介: 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


目录
相关文章
|
传感器 Linux Python
一起玩转树莓派(19)——红外遥控控制实验
红外遥控是生活中非常常见的电子器具,电视机,空调,音响等电器都可以通过遥控器进行控制。本篇博客,我们尝试来通过红外发生器和红外信号接受器来进行红外控制实验,在树莓派上通过红外遥控的按键来处理LED灯的控制。
2023 0
|
5月前
|
芯片
stm32f407探索者开发板(二十)——独立看门狗实验
stm32f407探索者开发板(二十)——独立看门狗实验
339 0
【期末不挂科-单片机考前速过系列P5】(第五章:11题速过中断系统和中断系统结构)经典例题盘点(带图解析)
【期末不挂科-单片机考前速过系列P5】(第五章:11题速过中断系统和中断系统结构)经典例题盘点(带图解析)
|
7月前
|
C++ 内存技术
【期末不挂科-单片机考前速过系列P8】(第八章:21题速过AT89S51单片机的内部硬件结构)经典例题盘点(带图解析)
【期末不挂科-单片机考前速过系列P8】(第八章:21题速过AT89S51单片机的内部硬件结构)经典例题盘点(带图解析)
|
7月前
|
传感器 Linux 编译器
不同平台下的点灯代码,你在点灯的哪个段位?
不同平台下的点灯代码,你在点灯的哪个段位?
|
7月前
|
传感器 监控 测试技术
单片机开发|基于51单片机的全自动黑板檫粉尘清除装置设计与实现
单片机开发|基于51单片机的全自动黑板檫粉尘清除装置设计与实现
|
异构计算
实验四 基于FPGA的数字电子钟设计(1) 基本功能的实现 quartus电路图演示
实验四 基于FPGA的数字电子钟设计(1) 基本功能的实现 quartus电路图演示
977 0
实验四 基于FPGA的数字电子钟设计(1) 基本功能的实现 quartus电路图演示
|
7月前
|
传感器 人工智能 Java
单片机开发|基于51单片机的全自动黑板檫粉尘清除装置设计
教师常年在课堂上上课,粉笔的灰尘会对学生的健康造成很大的危害,很多教师都会患上肺部疾病。教师在课堂教学中,如何有效地消除粉尘对教师的身体造成的不良影响,是一个亟待解决的问题。本文以51单片机为核心,实现并设计一种全自动黑板檫粉尘清除装置。由黑板擦上的压力传感器进行检测,由51单片机来控制吸尘器(吸尘风机),以完成清理。本系统的主要功能包括:压力检测、按键控制、灯光显示、电扇除尘等。本文在对国内外有关文献进行整理和归纳的基础上,首先介绍了全自动黑板檫粉尘清除装置的研制背景和研究意义,并结合国内外的研究情况,提出了本文的主要研究内容和系统的设计思路。接着,对系统的硬件电路进行了详细的设计,并编写了
|
传感器 监控 测试技术
单片机开发|基于51单片机的全自动黑板檫粉尘清除装置设计与实现
教师常年在课堂上上课,粉笔的灰尘会对学生的健康造成很大的危害,很多教师都会患上肺部疾病。教师在课堂教学中,如何有效地消除粉尘对教师的身体造成的不良影响,是一个亟待解决的问题。本文以51单片机为核心,实现并设计一种全自动黑板檫粉尘清除装置。由黑板擦上的压力传感器进行检测,由51单片机来控制吸尘器(吸尘风机),以完成清理。本系统的主要功能包括:压力检测、按键控制、灯光显示、电扇除尘等。本文在对国内外有关文献进行整理和归纳的基础上,首先介绍了全自动黑板檫粉尘清除装置的研制背景和研究意义,并结合国内外的研究情况,提出了本文的主要研究内容和系统的设计思路。接着,对系统的硬件电路进行了详细的设计,并编写了
192 0
|
算法 Linux Android开发
动手智能小车记(5)-坦克底盘硬件模块大杂烩
动手智能小车记(5)-坦克底盘硬件模块大杂烩
249 0