OpenMV与STM32之间的通信(附源码)

本篇文章旨在记录我电赛期间使用openmv和stm32单片机之间进行串口通信,将openmv识别到的坐标传输给单片机。背景是基于2023年全国大学生电子设计大赛E题:舵机云台追踪识别。

单片机的串口通信原理我便不再详细讲解,下面直接上代码分析。

值得注意的是接线:RX——>TX

                                 TX——>RX

                                 单片机和OPENMV必须共地

非常重要!!!!

一、串口通信传输两个数据(x坐标和y坐标) 

(一)、 OPENMV串口通信部分

import sensor, image, time,math,pyb
from pyb import UART,LED
import json
import ustruct

sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False) # must be turned off for color tracking
sensor.set_auto_whitebal(False) # must be turned off for color tracking
red_threshold_01=(10, 100, 127, 32, -43, 67)
clock = time.clock()

uart = UART(3,115200)   #定义串口3变量
uart.init(115200, bits=8, parity=None, stop=1) # init with given parameters

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 sending_data(cx,cy,cw,ch):
    global uart;
    #frame=[0x2C,18,cx%0xff,int(cx/0xff),cy%0xff,int(cy/0xff),0x5B];
    #data = bytearray(frame)
    data = ustruct.pack("<bbhhhhb",      #格式为俩个字符俩个短整型(2字节)
                   0x2C,                      #帧头1
                   0x12,                      #帧头2
                   int(cx), # up sample by 4   #数据1
                   int(cy), # up sample by 4    #数据2
                   int(cw), # up sample by 4    #数据1
                   int(ch), # up sample by 4    #数据2
                   0x5B)
    uart.write(data);   #必须要传入一个字节数组


while(True):
    clock.tick()
    img = sensor.snapshot()
    blobs = img.find_blobs([red_threshold_01])
    max_b = find_max(blobs)
    cx=0;cy=0;
    if blobs:
            #如果找到了目标颜色
            cx=max_b[5]
            cy=max_b[6]
            cw=max_b[2]
            ch=max_b[3]
            img.draw_rectangle(max_b[0:4]) # rect
            img.draw_cross(max_b[5], max_b[6]) # cx, cy
            FH = bytearray([0x2C,0x12,cx,cy,cw,ch,0x5B])
            #sending_data(cx,cy,cw,ch)
            uart.write(FH)
            print(cx,cy,cw,ch)

注意观察下图标注的部分,我不做详细讲解,但是很容易理解: 

接下来请看STM32串口通信部分的代码:

#include "uart.h"
#include "oled.h"
#include "stdio.h"

static u8 Cx=0,Cy=0,Cw=0,Ch=0;

void USART1_Init(void)
{
	//USART1_TX:PA 9   
	//USART1_RX:PA10
	GPIO_InitTypeDef GPIO_InitStructure;     //串口端口配置结构体变量
	USART_InitTypeDef USART_InitStructure;   //串口参数配置结构体变量
	NVIC_InitTypeDef NVIC_InitStructure;     //串口中断配置结构体变量

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);   //打开PA端口时钟

    //USART1_TX   PA9
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;          		 //PA9
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  		 //设定IO口的输出速度为50MHz
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	   		 //复用推挽输出
    GPIO_Init(GPIOA, &GPIO_InitStructure);             	 	 //初始化PA9
    //USART1_RX	  PA10
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;             //PA10
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  //浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);                 //初始化PA10 

    //USART1 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
		NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;  //抢占优先级0
		NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;		  //子优先级2
		NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			  //IRQ通道使能
		NVIC_Init(&NVIC_InitStructure);	                          //根据指定的参数初始化VIC寄存器

    //USART 初始化设置
		USART_InitStructure.USART_BaudRate = 115200;                  //串口波特率为115200
		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);                     //初始化串口1

    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //使能中断
    USART_Cmd(USART1, ENABLE);                     //使能串口1

  	//如下语句解决第1个字节无法正确发送出去的问题
	  USART_ClearFlag(USART1, USART_FLAG_TC);        //清串口1发送标志
		
}

//USART1 全局中断服务函数
void USART1_IRQHandler(void)			 
{
		u8 com_data; 
		u8 i;
		static u8 RxCounter1=0;
		static u16 RxBuffer1[10]={0};
		static u8 RxState = 0;	
		static u8 RxFlag1 = 0;


		if( USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)  	   //接收中断  
		{
				USART_ClearITPendingBit(USART1,USART_IT_RXNE);   //清除中断标志
				com_data = USART_ReceiveData(USART1);
			
				if(RxState==0&&com_data==0x2C)  //0x2c帧头
				{
					RxState=1;
					RxBuffer1[RxCounter1++]=com_data;OLED_Refresh();
				}
		
				else if(RxState==1&&com_data==0x12)  //0x12帧头
				{
					RxState=2;
					RxBuffer1[RxCounter1++]=com_data;
				}
		
				else if(RxState==2)
				{
					RxBuffer1[RxCounter1++]=com_data;

					if(RxCounter1>=10||com_data == 0x5B)       //RxBuffer1接受满了,接收数据结束
					{
						RxState=3;
						RxFlag1=1;
						Cx=RxBuffer1[RxCounter1-5];
						Cy=RxBuffer1[RxCounter1-4];
						Cw=RxBuffer1[RxCounter1-3];
						Ch=RxBuffer1[RxCounter1-2];
					}
				}
		
				else if(RxState==3)		//检测是否接受到结束标志
				{
						if(RxBuffer1[RxCounter1-1] == 0x5B)
						{
									USART_ITConfig(USART1,USART_IT_RXNE,DISABLE);//关闭DTSABLE中断
									if(RxFlag1)
									{
									OLED_Refresh();
									OLED_ShowNum(0, 0,Cx,3,16,1);
									OLED_ShowNum(0,17,Cy,3,16,1);
									OLED_ShowNum(0,33,Cw,3,16,1);
									OLED_ShowNum(0,49,Ch,3,16,1);
									}
									RxFlag1 = 0;
									RxCounter1 = 0;
									RxState = 0;
									USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
						}
						else   //接收错误
						{
									RxState = 0;
									RxCounter1=0;
									for(i=0;i<10;i++)
									{
											RxBuffer1[i]=0x00;      //将存放数据数组清零
									}
						}
				} 
	
				else   //接收异常
				{
						RxState = 0;
						RxCounter1=0;
						for(i=0;i<10;i++)
						{
								RxBuffer1[i]=0x00;      //将存放数据数组清零
						}
				}

		}
		
}

注意观察下面的图:

二、串口通信传输多个数据(四个点的x、y坐标同时传输给STM32单片机)

(一)OPENMV串口部分

from machine import Pin
import sensor, image, time, pyb
#import seekfree
from pyb import UART

# 初始化TFT180屏幕
#lcd = seekfree.LCD180(3)

# 初始化摄像头
sensor.reset()
sensor.set_pixformat(sensor.RGB565) # 设置图像色彩格式为RGB565格式
sensor.set_framesize(sensor.QQVGA)  # 设置图像大小为160*120
sensor.set_auto_whitebal(True)      # 设置自动白平衡
sensor.set_brightness(3000)         # 设置亮度为3000
sensor.skip_frames(time = 20)       # 跳过帧
uart = UART(3, 115200,timeout_char=3000) #配置串口
clock = time.clock()

def sending_data(cx,cy,cw,ch):
    global uart;
    data = ustruct.pack("<bbhhb",      #格式为俩个字符俩个短整型(2字节)
                   0x2C,                      #帧头1
                   0x12,                      #帧头2
                   int (cx1), # up sample by 4    #数据26
                   int (cy1),
                   int (cx2), # up sample by 4    #数据26
                   int (cy2),
                   int (cx3), # up sample by 4    #数据26
                   int (cy3),
                   int (cx4), # up sample by 4    #数据26
                   int (cy4),
                   0x5B)
    uart.write(data);   #必须要传入一个字节数组

while(True):
    clock.tick()
    img = sensor.snapshot()

# -----矩形框部分-----
    # 在图像中寻找矩形
    for r in img.find_rects(threshold = 10000):
        # 判断矩形边长是否符合要求
        if r.w() > 20 and r.h() > 20:
            # 在屏幕上框出矩形
            img.draw_rectangle(r.rect(), color = (255, 0, 0), scale = 4)
            # 获取矩形角点位置
            corner = r.corners()
            # 在屏幕上圈出矩形角点
            img.draw_circle(corner[0][0], corner[0][1], 5, color = (0, 0, 255), thickness = 2, fill = False)
            img.draw_circle(corner[1][0], corner[1][1], 5, color = (0, 0, 255), thickness = 2, fill = False)
            img.draw_circle(corner[2][0], corner[2][1], 5, color = (0, 0, 255), thickness = 2, fill = False)
            img.draw_circle(corner[3][0], corner[3][1], 5, color = (0, 0, 255), thickness = 2, fill = False)

        # 打印四个角点坐标, 角点1的数组是corner[0], 坐标就是(corner[0][0],corner[0][1])
        # 角点检测输出的角点排序每次不一定一致,矩形左上的角点有可能是corner0,1,2,3其中一个
            corner1_str = f"corner1 = ({corner[0][0]},{corner[0][1]})"
            corner2_str = f"corner2 = ({corner[1][0]},{corner[1][1]})"
            corner3_str = f"corner3 = ({corner[2][0]},{corner[2][1]})"
            corner4_str = f"corner4 = ({corner[3][0]},{corner[3][1]})"
        print(corner1_str + "\n" + corner2_str + "\n" + corner3_str + "\n" + corner4_str)
    # 显示到屏幕上,此部分会降低帧率
    #lcd.show_image(img, 160, 120, 0, 0, zoom=0)  #屏幕显示

    #串口通信传输的数据
        cx1=(int)(corner[0][0]*10)
        cy1=(int)(corner[0][1]*10)

        cx2=(int)(corner[1][0]*10)
        cy2=(int)(corner[1][1]*10)

        cx3=(int)(corner[2][0]*10)
        cy3=(int)(corner[2][1]*10)

        cx4=(int)(corner[3][0]*10)
        cy4=(int)(corner[3][1]*10)

        FH=bytearray([0x2C,0x12,cx1,cy1,cx2,cy2,cx3,cy3,cx4,cy4,0x5B])

        uart.write(FH)

        cx1=0
        cy1=0

        cx2=0
        cy2=0

        cx3=0
        cy3=0

        cx4=0
        cy4=0

    # 打印帧率
    print(clock.fps())

下面请观察这幅代码截图:

(二)、STM32串口通信部分

#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>
#include "OLED.h"
#include "LED.h"
#include "Serial.h"

uint8_t Serial_RxData;
uint8_t Serial_RxFlag;
static int16_t Cx1=0,Cy1=0,Cx2=0,Cy2=0,Cx3=0,Cy3=0,Cx4=0,Cy4=0; 

int Cx5[16];//用于存放分段求的坐标值
int Cy5[16];
//static u8 RxFlag1 = 0;//串口中断接收标志位

extern float Ang1,Ang2,AngFlag;
extern float Angle1,Angle2;

int avel_X1 ;
int avel_X2 ;
int avel_X3 ;
int avel_X4 ;

int avel_Y1 ;
int avel_Y2 ;
int avel_Y3 ;
int avel_Y4 ;

void Serial_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	//TX
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	//RX
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = 115200;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_Init(USART3, &USART_InitStructure);
	
	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	USART_Cmd(USART3, ENABLE);
}

void Serial_SendByte(uint8_t Byte)
{
	USART_SendData(USART3, Byte);
	while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET);
}

void Serial_SendArray(uint8_t *Array, uint16_t Length)
{
	uint16_t i;
	for (i = 0; i < Length; i ++)
	{
		Serial_SendByte(Array[i]);
	}
}

void Serial_SendString(char *String)
{
	uint8_t i;
	for (i = 0; String[i] != '\0'; i ++)
	{
		Serial_SendByte(String[i]);
	}
}

uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
	uint32_t Result = 1;
	while (Y --)
	{
		Result *= X;
	}
	return Result;
}

void Serial_SendNumber(uint32_t Number, uint8_t Length)
{
	uint8_t i;
	for (i = 0; i < Length; i ++)
	{
		Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');
	}
}

int fputc(int ch, FILE *f)
{
	Serial_SendByte(ch);
	return ch;
}

void Serial_Printf(char *format, ...)
{
	char String[100];
	va_list arg;
	va_start(arg, format);
	vsprintf(String, format, arg);
	va_end(arg);
	Serial_SendString(String);
}
//USART3 全局中断服务函数
void USART3_IRQHandler(void)			 
{
		int com_data; 
		u8 i;
		u8 Jieshou = 1;
		
		static u8 RxCounter1=0;
		static int RxBuffer1[16]={0};
		static u8 RxState = 0;	
		static u8 RxFlag1 = 0;//串口中断接收标志位,已被移除至函数体外作为全局变量

		if( USART_GetITStatus(USART3,USART_IT_RXNE)!=RESET && Jieshou == 1)  	   //接收中断  
		{
//			OLED_ShowSignedNum(1,1,520,4);
				USART_ClearITPendingBit(USART3,USART_IT_RXNE);   //清除中断标志
				com_data = USART_ReceiveData(USART3);
			if(Jieshou == 1)
			{
		
				if(RxState==0&&com_data==0x2C)  //0x2c帧头
				{
					RxBuffer1[RxCounter1++]=com_data;
					RxState=1;
				}
		
				else if(RxState==1&&com_data==0x12)  //0x12帧头
				{
					RxBuffer1[RxCounter1++]=com_data;
					RxState=2;
				}			
				else if(RxState==2)
				{
					RxBuffer1[RxCounter1++]=com_data;

					if(RxCounter1>=14||com_data == 0x5B)       //RxBuffer1接受满了,接收数据结束
					{
						RxState=3;
						RxFlag1=1;
						Jieshou = 2;
						
						Cx1=RxBuffer1[RxCounter1-9];
						Cy1=RxBuffer1[RxCounter1-8];
						
						Cx2=RxBuffer1[RxCounter1-7];
						Cy2=RxBuffer1[RxCounter1-6];
						
						Cx3=RxBuffer1[RxCounter1-5];
						Cy3=RxBuffer1[RxCounter1-4];
						
						Cx4=RxBuffer1[RxCounter1-3];
						Cy4=RxBuffer1[RxCounter1-2];
						
						OLED_ShowSignedNum(1,1,Cx1,4);
						OLED_ShowSignedNum(2,1,Cy1,4);
						OLED_ShowSignedNum(3,1,Cx2,4);
						OLED_ShowSignedNum(4,1,Cy2,4);
						
						OLED_ShowSignedNum(1,7,Cx3,4);
						OLED_ShowSignedNum(2,7,Cy3,4);
						OLED_ShowSignedNum(3,7,Cx4,4);
						OLED_ShowSignedNum(4,7,Cy4,4);
						
					}
				}
			}
				else if(RxState==3)		//检测是否接受到结束标志
				{
					if(RxBuffer1[RxCounter1-1] == 0x5B)
					{
						USART_ITConfig(USART3,USART_IT_RXNE,DISABLE);//关闭DTSABLE中断
						if(RxFlag1)
						{	
							
							AngFlag=0;
							HuanRaoZuoBiao();
//										
//							OLED_ShowSignedNum(1,1,Cx1,4);

//							OLED_ShowSignedNum(2,1,Cx2,4);
//							OLED_ShowSignedNum(3,1,avel_X1,4);
//							OLED_ShowSignedNum(4,1,Cx5[0],4);

							AngFlag=1;
							RxFlag1 = 0;
							RxCounter1 = 0;
							RxState = 0;									
						}
						USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);									
					}
					else   //接收错误
					{
								RxState = 0;
								RxCounter1=0;
								for(i=0;i<10;i++)
								{
										RxBuffer1[i]=0x00;      //将存放数据数组清零
								}
					}
				} 
	
				else   //接收异常
				{
						RxState = 0;
						RxCounter1=0;
						for(i=0;i<10;i++)
						{
								RxBuffer1[i]=0x00;      //将存放数据数组清零
							
						}
				}
			
		}
	}

 注意观察下面这副代码截图:

以上便是我对电赛期间OPENMV与单片机之间实现串口通信的代码实现。学者若有疑问可以私聊我。收到后我会及时回复。

链接:https://pan.baidu.com/s/1sOCuYl7288Ef0l0J41k9hg?pwd=zxf1 
提取码:zxf1 
--来自百度网盘超级会员V4的分享

  • 112
    点赞
  • 486
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 390
    评论
<项目介绍> 该资源内项目源码是个人的毕设,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到94.5分,放心下载使用! 该资源适合计算机相关专业(如人工智能、通信工程、自动化、软件工程等)的在校学生、老师或者企业员工下载,适合小白学习或者实际项目借鉴参考! 当然也可作为毕业设计、课程设计、课程作业、项目初期立项演示等。如果基础还行,可以在此代码基础之上做改动以实现更多功能。 1.物体识别 本次实验目的是使得小车可以跟踪目标,故首先确定跟踪目标,由于小车整体框架从零开始搭建,并没有太多的金钱可以选择昂贵的摄像头,故本次实验的目标识别选择较为简单的方式以减少硬件压力。本次实验首先识别纯色物体,是完成对纯色物体识别之后更进一步选择跟踪AprilTag。 AprilTag是一个视觉基准系统,可用于各种任务,包括AR,机器人和相机校准。这个tag可以直接用打印机打印出来,而AprilTag检测程序可以计算相对于相机的精确3D位置,方向和id。 AprilTag内容主要包含三个步骤: 第一步是如何根据梯度检测出图像中的各种边缘。 第二步即如何在边缘图像中找出需要的四边形图案并进行筛选,AprilTag尽可能的对检测出的边缘检测,首先剔除非直线边缘,在直线边缘进行邻接边缘查找,最终若形成闭环则为检测到一个四边形。对四边形进行解码确定Apriltag标签。 第三步确定四边形的中心点作为要跟踪的三维左边点。 Openmv对以上步骤进行了函数封装,可以用img.find_apriltags()函数定位Apriltag标签,并且可以通过该函数的返回值的方法确定三维坐标和三维角度:可以用获取x轴坐标tag.x_translation(), tag.y_translation()、tag.z_translation()是y、z轴坐标 。 2.云台追踪 openmv中搜索目标函数的返回值包括了目标物体中心的x、y坐标,原点是在图片的最左下角,就是说如果我们按照直接得到的坐标都是正的,但是我们要求云台追踪目标就是让目标始终出现在视野最中间,都是正的值我们无法判断图片到底是往哪边偏。为了解决这样的问题,我们只需要对得到的坐标进行简单的处理,openmv获得图片宽高都可以用函数获得,故已知图片宽width,高度height,目标中心点坐标x,y。按照相对比例来判断目标点在相机内的相对位置: $$ y1=y/height-0.5 $$ $$ x1=x/width-0.5 $$ 这样x1,y1就是我们最新获得的值,其取值范围均为[-0.5,0.5]。 为了实现云台始终追随目标,我们还需要将得到的坐标值转换为舵机旋转的角度,本实验云台为二自由度云台,如图1.1。下面的舵机控制偏航角与相机x轴相关,上面的舵机负责控制俯仰角与相机y轴相关,偏航角舵机的机械转角范围为[0,180],其中,当角度为0时,舵机朝向右侧,角度为180度时,舵机朝向左侧。俯仰角的机械转角范围为[90,180],其中,当角度为90度时,平台成水平,当角度为180度时,平台垂直水平面。 <img src="readme.imgs/1-16497681807631.jpg" style="zoom: 25%;" /> ​ **图1.1** 算法上的实现,算法上的实现可以使用pd控制,pd控制较为稳定更适合舵机。我们已知(x1,y1)为当前目标的坐标,目的是将其移动到镜头中央,那么目标点为(0,0),我们获得了x轴的偏差以及y轴的偏差error_x,error_y上一次x,y偏差为error_x_last,error_y_last。假设此时舵机角度为yaw_now,pitch_now,那么有简化版增量式pd算法为
您可以使用OpenMVSTM32之间的串口通信来传输数据。下面是一个示例代码,展示了如何在OpenMV上接收来自STM32的数据。 在OpenMV上的代码(Python): ```python import sensor import image import time import pyb # 初始化串口 uart = pyb.UART(3, 115200, timeout_char=1000) while(True): # 读取串口数据 data = uart.readline() if data: # 处理接收到的数据 print("Received data:", data) # 在这里添加你的数据处理代码 ``` 在STM32上的代码(C语言): ```c #include "stm32f4xx.h" #include "stm32f4xx_usart.h" void USART_Configuration(void) { USART_InitTypeDef USART_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; // 使能USART2时钟和GPIOA时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // 将PA2引脚配置为复用功能,用于USART2的Tx GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 将PA3引脚配置为复用功能,用于USART2的Rx GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 将PA2引脚复用为USART2 GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2); // 将PA3引脚复用为USART2 GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); // 配置USART2 USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; 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(USART2, &USART_InitStructure); // 使能USART2接收中断 USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); // 配置USART2中断优先级 NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); // 使能USART2 USART_Cmd(USART2, ENABLE); } void USART2_IRQHandler(void) { if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) { // 读取接收到的数据 uint8_t data = USART_ReceiveData(USART2); // 在这里添加你的数据处理代码 USART_ClearITPendingBit(USART2, USART_IT_RXNE); } } int main(void) { USART_Configuration(); while (1) { // 发送数据到OpenMV USART_SendData(USART2, data); // 在这里添加你的数据发送代码 } } ``` 这个示例代码展示了如何通过串口在OpenMVSTM32之间传输数据。您可以根据自己的需求进行修改和扩展。请确保OpenMVSTM32的波特率设置一致,并根据具体情况进行适当的修改。
评论 390
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小_扫地僧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值