Implementation of serial communication between openmv and stm32

I have been in graduate school for nearly three months. Graduate study is very different from undergraduate study. I should be good at finding information and summarizing myself. Therefore, I also decided to write a blog from now on to summarize various difficulties and solutions encountered in each period of time, so as to accumulate experience for future work and facilitate future reference.

This is my first blog. I have been working on projects about raspberry pie and opencv before. Some time ago, the teacher also gave me the idea of a new project, which should be based on visual processing. However, just after the 21 year video game, some students use openmv during the game, so I also want to try openmv to deal with this project, And meet old friends again stm32.

To get back to the point, image processing based on openmv is very simple. The official has given various libraries, which can be used if you take a good look at the examples. However, there are too few pins in openmv, so the functions that can be realized are too single. Therefore, at this time, openmv can only be used as a sensor, and most functions have to rely on stm32. Since openmv is used as a sensor, Therefore, communication between openmv and stm32 must be realized in many ways. I chose the most basic serial communication.

Although the undergraduate has also done a lot of communication between STM32 and various sensors, this time I encountered some little trouble and checked a lot of information on the Internet, but how to say, either the code given is incomplete and I don't know the connection between the top and bottom, or simply talking about STM32 serial communication is not compatible with the subject at all.

Don't talk nonsense. Summarize the code directly. (remember to connect P4 of openmv to PA10 of stm32 and P5 to PA9)

Code about openmv:

# Blob Detection and uart transport
import sensor, image, time,math
from pyb import UART
import json
# For color tracking to work really well you should ideally be in a very, very,
# very, controlled enviroment where the lighting is constant...
yellow_threshold   = (65, 100, -10, 6, 24, 51)
# You may need to tweak the above settings for tracking green things...
# Select an area in the Framebuffer to copy the color settings.

sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.RGB565) # use RGB565.
sensor.set_framesize(sensor.QQVGA) # use QQVGA for speed.
sensor.skip_frames(10) # Let new settings take affect.
sensor.set_auto_whitebal(False) # turn this off.
clock = time.clock() # Tracks FPS.

uart = UART(3, 115200)
def find_max(blobs):
    max_size=0
    for blob in blobs:
        if blob.pixels() > max_size:
            max_blob=blob
            max_size = blob.pixels()
    return max_blob

while(True):
    img = sensor.snapshot() # Take a picture and return the image.

    blobs = img.find_blobs([yellow_threshold])

    img_data=bytearray([0x2C,7,1,2,3,4,0X5B])

    uart.write(img_data)

This code prototype is the official code for finding the largest color block. It is just used to simply transmit data through the serial port, so many core components are deleted. It should be noted that bytearry() is used in the last two lines, so it is necessary to import math at the beginning, in which the 0 bit is the start flag, the last bit is the end flag, and the 1 bit is the total number of digits 7, Others are data to be transmitted.

Code for stm32:

(1)usart.c

#include "sys.h"
#include "usart.h"	
#include "openmv.h"
#include "lcd.h"
// 	 
//If ucos is used, include the following header file
#if SYSTEM_SUPPORT_OS
#include "includes.h" 					// ucos usage	  
#endif
	  
 

//
//Add the following code to support the printf function without selecting use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
//Support functions required by the standard library                 
struct __FILE 
{ 
	int handle; 
}; 

FILE __stdout;       
//Definition_ sys_exit() to avoid using half host mode    
void _sys_exit(int x) 
{ 
	x = x; 
} 
//Redefine fputc function 
int fputc(int ch, FILE *f)
{ 	
	while((USART1->SR&0X40)==0);//Cycle sending until sending is completed   
	USART1->DR = (u8) ch;      
	return ch;
}
#endif
 
#if EN_USART1_RX / / if receive is enabled
//Serial port 1 interrupt service program
//Note that reading usartx - > SR can avoid inexplicable errors   	
u8 USART_RX_BUF[USART_REC_LEN];     //Receive buffer, maximum USART_REC_LEN bytes
//Receiving status
//bit15, 	 Reception completion flag
//bit14, 	 0x0d received
//bit13~0, 	 Number of valid bytes received
u16 USART_RX_STA=0;       //Receive status flag	

//Initialize IO serial port 1 
//bound: baud rate
void uart_init(u32 bound){
   //GPIO port settings
  GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //Enable GPIOA clock
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//Enable USART1 clock
 
	//Serial port 1 corresponding pin multiplexing mapping
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9 multiplexed to USART1
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10 multiplexed to USART1
	
	//USART1 port configuration
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9 and GPIOA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//Reuse function
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//Speed 50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //Push pull multiplex output
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //Pull up
	GPIO_Init(GPIOA,&GPIO_InitStructure); //Initialize PA9, PA10

   //USART1 initialization settings
	USART_InitStructure.USART_BaudRate = bound;//Baud rate setting
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//The word length is in 8-bit data format
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//A stop bit
	USART_InitStructure.USART_Parity = USART_Parity_No;//No parity bit
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//No hardware data flow control
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//Transceiver mode
  USART_Init(USART1, &USART_InitStructure); //Initialize serial port 1
	
  USART_Cmd(USART1, ENABLE);  //Enable serial port 1 
	
	//USART_ClearFlag(USART1, USART_FLAG_TC);
	
#if EN_USART1_RX	
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//Turn on related interrupt

	//Usart1 NVIC configuration
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//Serial port 1 interrupt channel
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//Preemption priority 3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;		//Sub priority 3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ channel enable
	NVIC_Init(&NVIC_InitStructure);	//Initializes the VIC register according to the specified parameters

#endif
	
}


void USART1_IRQHandler(void)                	//Serial port 1 interrupt service program
{
	u8 Res;
#if SYSTEM_SUPPORT_OS  		// If system_ SUPPORT_ If OS is true, you need to support OS
	OSIntEnter();    
#endif
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //Receive interrupt (the received data must end in 0x0D and 0x0a)
	{
		Res =USART_ReceiveData(USART1);//(USART1->DR); 	// Read received data
		Openmv_Receive_Data(Res);
		Openmv_Data();
		if((USART_RX_STA&0x8000)==0)//Reception incomplete
		{
			if(USART_RX_STA&0x4000)//0x0d received
			{
				if(Res!=0x0a)USART_RX_STA=0;//Receive error, restart
				else USART_RX_STA|=0x8000;	//Reception is complete 
			}
			else //I haven't received 0X0D yet
			{	
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
				{
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//Error receiving data, restart receiving	  
				}		 
			}
		}   		 
  } 
#if SYSTEM_SUPPORT_OS  	// If system_ SUPPORT_ If OS is true, you need to support OS
	OSIntExit();  											 
#endif
} 
#endif	

 



(2)usart.h

#ifndef __USART_H
#define __USART_H
#include "stdio.h"	
#include "stm32f4xx_conf.h"
#include "sys.h" 
#define USART_REC_LEN   			 two hundred 	// Define the maximum number of bytes received 200
#define EN_USART1_RX  			 one 		// Enable (1) / disable (0) serial port 1 reception
	  	
extern u8  USART_RX_BUF[USART_REC_LEN]; //Receive buffer, maximum USART_REC_LEN bytes. The last byte is a newline character 
extern u16 USART_RX_STA;         		//Receive status flag	
//If you want to interrupt reception through the serial port, please do not comment on the following macro definitions
void uart_init(u32 bound);
#endif

The official serial port code is used. Anyone who has used stm32 has this code, except when res = USART_ Two lines of openmv functions are added after receivedata (usart1).

(3)openmv.c

#include "openmv.h"
#include "usart.h"
int openmv[7];//stm32 receive data array
int16_t data1;
int16_t data2;
int16_t data3;
int16_t data4;



int i=0;

void Openmv_Receive_Data(int16_t data)//Receive data from Openmv
{
	static u8 state = 0;
	if(state==0&&data==0x2C)
	{
		state=1;
		openmv[0]=data;
	}
	else if(state==1&&data==7)
	{
		state=2;
		openmv[1]=data;
	}
	else if(state==2)
	{
		state=3;
		openmv[2]=data;
	}
	else if(state==3)
	{
		state = 4;
		openmv[3]=data;
	}
	else if(state==4)
	{
        state = 5;
        openmv[4]=data;
	}
	else if(state==5)
	{
        state = 6;
        openmv[5]=data;
	}
	else if(state==6)		//Detect whether the end flag is accepted
	{
        if(data == 0x5B)
        {
            state = 0;
            openmv[6]=data;
            Openmv_Data();
        }
        else if(data != 0x5B)
        {
            state = 0;
            for(i=0;i<7;i++)
            {
                openmv[i]=0x00;
            }           
        }
	}    
	else
		{
			state = 0;
            for(i=0;i<7;i++)
            {
                openmv[i]=0x00;
            }
		}
}

void Openmv_Data(void)
{
    data1=openmv[0];
    data2=openmv[3];
    data3=openmv[4];
    data4=openmv[5];

}

(4)openmv.h

#include "sys.h"


extern int openmv[7];//stm32 receive data array
extern int16_t data1;
extern int16_t data2;
extern int16_t data3;
extern int16_t data4;

void Openmv_Receive_Data(int16_t data);
void Openmv_Data(void);

(5)main.c

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "openmv.h"


int main(void)
{ 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//Set system interrupt priority group 2
	delay_init(168);      //Initialization delay function
	uart_init(115200);		//The baud rate of initialization serial port is 115200
	LED_Init();					  //Initialize LED
 	LCD_Init();           //Initialize LCD FSMC interface
	POINT_COLOR=RED;      //Brush color: Red				 	
  while(1) 
	{		 
		LCD_ShowNum(0,20,200,10,24);
		LCD_ShowNum(0,40,data1,10,24);
	} 
}

Among them, 7 in openmv[7] is the same as the total number of bits of bytearry () in openmv code.

Then download the code and you can see the results on the lcd screen (the lcd screen code is not pasted, and the official information is very detailed).

 

Tags: stm32 ARM

Posted on Mon, 29 Nov 2021 08:09:22 -0500 by Richardtagger