stm32与openmv进行串口通讯

avatar
作者
猴君
阅读量:1

目录

一、openmv端配置:

二、STM32F103C8T6端配置


一、openmv端配置:

         openmv代码:

         我使用的是将被识别的目标中心点坐标通过串口通讯发送给STM32,中心值感觉不是很准,后面还需要调整,但是基本的收发已经完成。

# Untitled - By: zzy - 周五 11月 25 2022  import sensor, image, time from pyb import UART import json  #output_str_green="[0,0]" output_str_white="[0,0]"  #green_threshold  = (   0,   80,  -70,   -10,   -0,   30) #使用的白色测试阈值 white_threshold  = (53, 100, -128, 127, -128, 127) sensor.reset() sensor.set_pixformat(sensor.RGB565) sensor.set_framesize(sensor.QVGA) sensor.set_windowing((0,20,320,200))#QVGA find Region Of Interest #sensor.set_windowing((5,10,160,95))#QQVGA find Region Of Interest sensor.skip_frames(10) sensor.set_auto_whitebal(False)#白平衡增益关闭 clock = time.clock()  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  def detect(max_blob):#输入的是寻找到色块中的最大色块     #print(max_blob.solidity())     shape=0     if max_blob.solidity()>0.90 or max_blob.density()>0.84:         img.draw_rectangle(max_blob.rect(),color=(255,255,255))         shape=1      elif max_blob.density()>0.6:         img.draw_circle((max_blob.cx(), max_blob.cy(),int((max_blob.w()+max_blob.h())/4)))         shape=2      elif max_blob.density()>0.4:         img.draw_rectangle(max_blob.rect(),color=(0,0,0))         shape=3      return shape  while(True):     #clock.tick()     img = sensor.snapshot() # Take a picture and return the image.     blobs_white = img.find_blobs([white_threshold])      if blobs_white:         max_blob_white=find_max(blobs_white)         shape_white=detect(max_blob_white)         #img.draw_rectangle(max_blob_blue.rect(),color=(0,0,255))         img.draw_cross(max_blob_white.cx(), max_blob_white.cy(),color=(0,0,255))         output_str_white="[%d,%d]" % (max_blob_white.cx()-160,max_blob_white.cy()-100) #方式1         img_data=bytearray([0x2C,7,4,max_blob_white.cx()-160,max_blob_white.cy()-100,1,0X5B]) # 数据倒数前三位可发送成功         uart.write(img_data)         print('white:',output_str_white)     else:         print('not found white !')      # uart.write(output_str_green + output_str_red + output_str_blue + output_str_brown + output_str_yellow + '\r\n')      #print(clock.fps()) 

上面代码中如果需要引用,最主要的是串口的配置和发送部分,串口配置就一句话,串口的发送是两句话,包括下面这两句:

其中0X2C是帧头,0X5B是帧尾。中间夹的就是数据。目前调用的是第三和第四位数据,STM32那边对应的是第二和第三位。

        img_data=bytearray([0x2C,7,4,max_blob_white.cx()-160,max_blob_white.cy()-100,1,0X5B]) # 数据倒数前三位可发送成功         uart.write(img_data)

根据自己的需要完成OPENMV端的配置后就可跳转到STM32端的配置

二、STM32F103C8T6端配置

     system文件中应包含有sys,usart,delay三个基本文件才能进行后续运行。其中uart需要进行一定的修改。

     下面是相关的库文件代码:

    如果无法移植可直接使用百度网盘下载:链接:  https://pan.baidu.com/s/1PvGVYfdQrutwHfJiNS3TJQ 
提取码:fafu

麻烦大家给个关注

usart.c文件:

#include "sys.h" #include "usart.h"	 #include "openmv.h" //如果使用ucos,则包括下面的头文件即可. #if SYSTEM_SUPPORT_OS #include "includes.h"					//ucos 使用	   #endif 	       // //加入以下代码,支持printf函数,而不需要选择use MicroLIB	   #if 1 #pragma import(__use_no_semihosting)              //标准库需要的支持函数                  struct __FILE  {  	int handle;  };    FILE __stdout;        //定义_sys_exit()以避免使用半主机模式     void _sys_exit(int x)  {  	x = x;  }  //重定义fputc函数  int fputc(int ch, FILE *f) { 	 	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕    	USART1->DR = (u8) ch;       	return ch; } #endif   #if EN_USART1_RX   //如果使能了接收 //串口1中断服务程序 //注意,读取USARTx->SR能避免莫名其妙的错误   	 u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节. //接收状态 //bit15,	接收完成标志 //bit14,	接收到0x0d //bit13~0,	接收到的有效字节数目 u16 USART_RX_STA=0;       //接收状态标记	   //初始化IO 串口1  void uart_init(u32 bound){     //GPIO端口设置     GPIO_InitTypeDef GPIO_InitStructure; 	USART_InitTypeDef USART_InitStructure; 	NVIC_InitTypeDef NVIC_InitStructure; 	  	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);	//使能USART1,GPIOA时钟以及复用功能时钟      //USART1_TX   PA.9     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出     GPIO_Init(GPIOA, &GPIO_InitStructure);         //USART1_RX	  PA.10     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入     GPIO_Init(GPIOA, &GPIO_InitStructure);       //Usart1 NVIC 配置      NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; 	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3 	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3 	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能 	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器       //USART 初始化设置  	USART_InitStructure.USART_BaudRate = bound;//一般设置为9600; 	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式 	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位 	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位 	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制 	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式      USART_Init(USART1, &USART_InitStructure); //初始化串口     USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断     USART_Cmd(USART1, ENABLE);                    //使能串口  		printf("usart1_init_success\r\n"); }      void USART1_IRQHandler(void)                	//串口1中断服务程序 { 	u8 Res; #if SYSTEM_SUPPORT_OS 		//如果SYSTEM_SUPPORT_OS为真,则需要支持OS. 	OSIntEnter();     #endif 	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾) 	{ 		Res =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据 		Openmv_Receive_Data(Res); 		Openmv_Data(); 		if((USART_RX_STA&0x8000)==0)//接收未完成 		{ 			if(USART_RX_STA&0x4000)//接收到了0x0d 			{ 				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始 				else USART_RX_STA|=0x8000;	//接收完成了  			} 			else //还没收到0X0D 			{	 				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;//接收数据错误,重新开始接收	   				}		  			} 		}   		    }  #if SYSTEM_SUPPORT_OS 	//如果SYSTEM_SUPPORT_OS为真,则需要支持OS. 	OSIntExit();  											  #endif }  #endif	          

usart.h

#ifndef __USART_H #define __USART_H #include "stdio.h"	 #include "stm32f10x.h" #include "sys.h"  #define USART_REC_LEN  			200  	//定义最大接收字节数 200 #define EN_USART1_RX 			1		//使能(1)/禁止(0)串口1接收 	  	 extern u8  USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.末字节为换行符  extern u16 USART_RX_STA;         		//接收状态标记	 //如果想串口中断接收,请不要注释以下宏定义 void uart_init(u32 bound); #endif 

openmv.c

#include "openmv.h" #include "usart.h" int openmv[7];//stm32接收数据数组 int16_t data1; int16_t data2; int16_t data3; int16_t data4;     int i=0;   void Openmv_Receive_Data(int16_t data)//接收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)		//检测是否接受到结束标志 	{         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];   }  

openmv.h
 

#ifndef  __OPENMV_H #define  __OPENMV_H #include "sys.h" extern int openmv[7];//stm32接收数据数组 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); #endif

最后是main.c

#include "stm32f10x.h" #include "sys.h" #include "delay.h" #include "usart.h" #include "led.h" #include "oled.h" #include "openmv.h"   extern int openmv[7];//stm32接收数据数组 extern int16_t data1; extern int16_t data2; extern int16_t data3; extern int16_t data4; int16_t data; int main(void) {  	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2 	delay_init();      //初始化延时函数 	uart_init(115200);		//初始化串口波特率为115200 	LED_Init();					  //初始化LED  	OLED_Init();           //初始化LCD FSMC接口		 	   while(1)  	{	  		OLED_ShowString(1,1,"CX:");      	OLED_ShowNum(1, 5, data2, 3); 		OLED_ShowString(2,1,"CY:"); 	 	OLED_ShowNum(2, 5, data3, 3); 		delay_ms(150); 	}  }

将上述库文件和主函数配置完成后,按照下面的接线方式进行接线即可完成串口通讯。

 STM32 PA9--P5 OPENMV  STM32 PA10-P4 OPENMV   STM32 GND-GND OPENMV  OLED SCL-PB8  OLED SDA-PB9

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!