Openmv与stm32通信笔记:
首先,用个例子来简单理理通信的步骤:
? 假如我现在想要识别红杆,先要在主函数里写入对应的发送模式(这里假设 写入Mode = 0x12为识别红杆),然后stm32会根据你写入的发送函数,将Mode = 0x12的数据包发送给Openmv执行,在Openmv里得到你识别红杆需要的数据,然后再在Openmv中选择对应的发送模式,将我们需要的数据打包后以包的形式发送过来(这里要注意,根据所需数据的不同,包的形式也不同,具体看个人对包怎么创建),然后Stm32再一个一个将数据拿出,用switch的方式选择接收的数据存到哪些变量中,再把变量调用回主函数。
注意:数据包的发送和接收是按我们规定的时间间隔执行的。
1.Uart等初始化及配置
#include "Basic.h"
#include "drv_Uart2.h"
#include "Quaternion.h"
#include "MeasurementSystem.h"
#include "STS.h"
#include "Sensors_Backend.h"
#include "RingBuf.h"
#include "TM4C123GH6PM.h"
#include "uart.h"
#include "sysctl.h"
#include "gpio.h"
#include "pin_map.h"
#include "interrupt.h"
#include "hw_ints.h"
#include "hw_gpio.h"
#include "Timer.h"
#include "udma.h"
#include "drv_LED.h"
#include "InteractiveInterface.h"
#define Uart0_BUFFER_SIZE 64
static void UART0_Handler();
static uint8_t Uart0_tx_buffer[Uart0_BUFFER_SIZE];
static RingBuf_uint8_t Uart0_Tx_RingBuf;
static uint8_t Uart0_rx_buffer[Uart0_BUFFER_SIZE];
static RingBuf_uint8_t Uart0_Rx_RingBuf;
static bool SDI_RCTrigger( unsigned int Task_ID );
static void SDI_Server( unsigned int Task_ID );
static bool SDI_TXTrigger( unsigned int Task_ID );
static void SDI_Tx_model_contrl( unsigned int Task_ID );
void init_drv_Uart0()
{
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIOA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet() , 115200,
(UART_CONFIG_WLEN_8
| UART_CONFIG_STOP_ONE
| UART_CONFIG_PAR_NONE));
RingBuf_uint8_t_init( &Uart0_Tx_RingBuf , Uart0_tx_buffer , Uart0_BUFFER_SIZE );
RingBuf_uint8_t_init( &Uart0_Rx_RingBuf , Uart0_rx_buffer , Uart0_BUFFER_SIZE );
UARTIntEnable( UART0_BASE , UART_INT_RX | UART_INT_RT);
UARTIntRegister( UART0_BASE , UART0_Handler );
uDMAChannelControlSet( UDMA_PRI_SELECT | UDMA_CH9_UART0TX , \
UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1 );
UARTDMAEnable( UART0_BASE , UART_DMA_TX );
UARTIntRegister( UART0_BASE , UART0_Handler );
uDMAChannelAssign(UDMA_CH9_UART0TX );
IntPrioritySet( INT_UART0 , INT_PRIO_7 );
IntEnable( INT_UART0 );
STS_Add_Task( STS_Task_Trigger_Mode_Custom , 0 , SDI_RCTrigger , SDI_Server );
STS_Add_Task( STS_Task_Trigger_Mode_Custom , 0 , SDI_TXTrigger , SDI_Tx_model_contrl );
}
? 以上是对stm32串口的简单配置,具体配置可按个人具体要求来改动,其中两个STS_Add_Task()函数则是进行数据的接收与发送(Rx、Tx),第一个变量设置触发函数类型(具有多种触发类型)为自定义函数触发,第二个变量为触发的时间间隔,第三个变量则是自己定义的触发函数,第四个变量为触发以后将会执行的主函数。
2.控制Openmv执行指令
uint8_t SDI_mode_contrl = 0;
uint8_t SDI_tc_mode = 0;
static bool SDI_TXTrigger( unsigned int Task_ID )
{
if( SDI_mode_contrl != 0 )
{
SDI_tc_mode = SDI_mode_contrl;
SDI_mode_contrl = 0;
return true;
}
return false;
}
static void SDI_Tx_model_contrl( unsigned int Task_ID )
{
uint8_t tc_buf[6] = {0};
uint8_t tc_cnt = 0;
uint8_t sum = 0;
uint16_t tc_data_buf = 0;
tc_buf[0] = 0xAA;
tc_buf[1] = 0x55;
tc_buf[2] = 0x18;
tc_buf[3] = 0x02;
switch(SDI_tc_mode)
{
case 0xff:
{
tc_buf[4] = 0xff;
}break;
case 33://蓝杆测距
{
tc_buf[4] = 0x16;
}break;
case 23://识别蓝杆
{
tc_buf[4] = 0x2C;
}break;
case 3://起飞后发送33找橙杆
{
tc_buf[4] = 0x21;
}break;
case 13:
{
tc_buf[4] = 0x0B;
}break;
case 43:
{
tc_buf[4] = 55;
}break;
case 101:
{
tc_buf[4] = 101;
}break;
case 103:
{
tc_buf[4] = 103;
}break;
}
tc_buf[5] = (tc_buf[0] + tc_buf[1] + tc_buf[2] + tc_buf[3] + tc_buf[4])%256;
Uart0_Send(tc_buf,6);
}
? 本段代码先是定义SDI_tc_mode()用于发送我们想让openmv执行的模式(以switch的方式选择,便于后期添加或删除模式),然后再定义tc_buf[6]将包头等数据全部打包,在最后用Uart0_Send(tc_buf,6)将数据以包的形式输出openmv。 注意:包头、包尾是自己喜好定义的,而数据位和数据长度则是按自己对于通信的要求来定义,任务内容也是按自己需要编写,最后的tc—buf[5]是采取求和取余的方式来校验数据是否打包完成。
3.控制输入
static bool SDI_RCTrigger( unsigned int Task_ID )
{
if( Uart0_DataAvailable() )
return true;
return false;
}
uint8_t SDI_west = 0;
uint8_t SDI_color = 0;
uint8_t SDI_sequence = 0;
uint8_t SDI_area_block=0;
uint8_t SDI_area_cx=0;
uint8_t SDI_forward=0;
int8_t SDI_delta_x=0;
uint8_t SDI_line_coordinate[3] = {0};
int8_t line_angle=0;
uint16_t SDI_poles_distance=0;
uint16_t SDI_find_pole=0;
uint16_t msg_pack1;
uint16_t msg_pack2;
static void SDI_Server ( unsigned int Task_ID )
{
static uint8_t rc_step1 = 0;
#define MAX_SDI_PACKET_SIZE 11
static uint8_t msg_type;
static uint8_t msg_length;
ALIGN4 static uint8_t msg_pack[MAX_SDI_PACKET_SIZE]={0};
static uint8_t sumB;
#define reset_SDI_RC ( rc_step1 = rc_step2 = 0 )
uint8_t rc_buf[20];
uint8_t length = read_Uart0( rc_buf , 20 );
for( uint8_t i = 0 ; i < length ; ++i )
{
uint8_t r_data = rc_buf[i];
switch( rc_step1 )
{
case 0 :
sumB=0;
if(r_data == 0xAA)
{
sumB += r_data;
rc_step1 = 1;
}
break;
case 1:
if(r_data == 0x55)
{
sumB += r_data;
rc_step1 = 2;
}
else reset_SDI_RC;
break;
case 2:
if(r_data > 0x09 && r_data < 0x30)
{
msg_type = r_data;
sumB += r_data;
rc_step1 = 3;
rc_step2 = 0;
}
else reset_SDI_RC;
break;
case 3:
if( r_data > MAX_SDI_PACKET_SIZE )
{
reset_SDI_RC;
break;
}
msg_length = r_data;
sumB += r_data;
rc_step1 = 4;
rc_step2 = 0;
break;
case 4:
msg_pack[ rc_step2 ++] = r_data;
sumB += r_data;
if( rc_step2 >= msg_length )
{
rc_step1 = 5;
rc_step2 = 0;
}
break;
case 5:
if(sumB == r_data)
{
if(msg_type == 0x18)
{
Find_redpole1 = msg_pack[0];
}
else if(msg_type == 0x19)
{
Find_redpole = msg_pack[2];
SDI_delta_x = msg_pack[1];
pole_distance = msg_pack[0];
}
}
reset_SDI_RC;
break;
}
}
}
void Uart0_Send( const uint8_t* data , uint16_t length )
{
IntDisable( INT_UART0 );
int16_t buffer_space = RingBuf_uint8_t_get_Freesize( &Uart0_Tx_RingBuf );
int16_t DMA_Remain = uDMAChannelSizeGet( UDMA_CH9_UART0TX );
int16_t max_send_count = buffer_space - DMA_Remain;
if( max_send_count < 0 )
max_send_count = 0;
uint16_t send_count = ( length < max_send_count ) ? length : max_send_count;
RingBuf_uint8_t_push_length( &Uart0_Tx_RingBuf , data , send_count );
if( uDMAChannelIsEnabled( UDMA_CH9_UART0TX ) == false )
{
uint16_t length;
uint8_t* p = RingBuf_uint8_t_pop_DMABuf( &Uart0_Tx_RingBuf , &length );
if( length )
{
uDMAChannelTransferSet( UDMA_PRI_SELECT | UDMA_CH9_UART0TX , \
UDMA_MODE_BASIC , p , (void*)&UART0->DR , length );
uDMAChannelEnable( UDMA_CH9_UART0TX );
}
}
IntEnable( INT_UART0 );
}
static void UART0_Handler()
{
UARTIntClear( UART0_BASE , UART_INT_OE );
UARTRxErrorClear( UART0_BASE );
while( ( UART0->FR & (1<<4) ) == false )
{
uint8_t rdata = UART0->DR;
RingBuf_uint8_t_push( &Uart0_Rx_RingBuf , rdata );
}
if( uDMAChannelIsEnabled( UDMA_CH9_UART0TX ) == false )
{
uint16_t length;
uint8_t* p = RingBuf_uint8_t_pop_DMABuf( &Uart0_Tx_RingBuf , &length );
if( length )
{
uDMAChannelTransferSet( UDMA_PRI_SELECT | UDMA_CH9_UART0TX , \
UDMA_MODE_BASIC , p , (void*)&UART0->DR , length );
uDMAChannelEnable( UDMA_CH9_UART0TX );
}
}
}
uint16_t read_Uart0( uint8_t* data , uint16_t length )
{
IntDisable( INT_UART0 );
uint8_t read_bytes = RingBuf_uint8_t_pop_length( &Uart0_Rx_RingBuf , data , length );
IntEnable( INT_UART0 );
return read_bytes;
}
uint16_t Uart0_DataAvailable()
{
IntDisable( INT_UART0 );
uint16_t bytes2read = RingBuf_uint8_t_get_Bytes2read( &Uart0_Rx_RingBuf );
IntEnable( INT_UART0 );
return bytes2read;
}
? 接收原理与发送原理一致,首先是识别包头,然后确定接收到的模式,用于接收对应模式所需要传达的信息。
7.26学习笔记 bytes = RingBuf_uint8_t_pop_length( &Uart0_Rx_RingBuf , data , length ); IntEnable( INT_UART0 ); return read_bytes; }
uint16_t Uart0_DataAvailable() { IntDisable( INT_UART0 ); uint16_t bytes2read = RingBuf_uint8_t_get_Bytes2read( &Uart0_Rx_RingBuf ); IntEnable( INT_UART0 ); return bytes2read; }
? 接收原理与发送原理一致,首先是识别包头,然后确定接收到的模式,用于接收对应模式所需要传达的信息。
7.26学习笔记
|