STM32单片机与Openmv的串口通信

cathy的头像

简谈闲话

这两天本人利用周末时间粗略的学习一下openmv的使用,目的是用openmv图像处理数据并通过串口发送数据给STM32F103的单片机,并且用TFTLCD显示屏打印数据。在学习的过程中遇到了一些问题且成功解决,下面将讲述其中的过程,希望可以帮助需要的朋友,欢迎大家一起交流学习。

Openmv主要代码

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

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
clock = time.clock()

uart = UART(3,115200)   #定义串口3变量
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
####################################
#
#此为颜色处理代码
#
###################################
#bytearray为可变序列的字节数组 返回一个新的字节数组(将数据转为16进制)
img_data = bytearray([0x2C,18,X_black_Sign,Y_black_Sign,X_black_relative_displacement,Y_black_relative_displacement,
                           X_red_Sign,Y_red_Sign,X_red_relative_displacement,Y_red_relative_displacement,X_yellow_Sign,
                           Y_yellow_Sign,X_yellow_relative_displacement,Y_yellow_relative_displacement,
                           L_black,L_red,L_yellow,0x5B])


uart.write(img_data)

上述代码中引用了感光元件sensor及串口UART。

先定义了一个寻色块面积最大的函数,然后对目标颜色进行处理,最后通过bytearray对数据进行处理并赋值给变量img_data。

bytearray为python内字节数组。

STM32单片机的配置

UART4库函数初始化配置

void uart4_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure; //串口端口配置结构体变量
	USART_InitTypeDef USART_InitStructure;//串口参数配置结构体变量
	NVIC_InitTypeDef NVIC_InitStructure;//串口中断配置结构体变量
	//使能 UART4 时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART4, ENABLE);	//打开串口复用时钟
   	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);   //打开PC端口时钟
  
	//UART4_TX   GPIOC.10
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PC.10
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//设定IO口的输出速度为50MHz
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
 	 GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOC.10
   
  	//UART4_RX	  GPIOC.11初始化
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//PC.11
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  	GPIO_Init(GPIOC, &GPIO_InitStructure);//初始化GPIOC.10  

 	//Usart1 NVIC 配置
  	NVIC_InitStructure.NVIC_IRQChannel = UART4_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级2
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
	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(UART4, &USART_InitStructure); //初始化串口4
	
	USART_ITConfig(UART4, USART_IT_RXNE, ENABLE);//开启串口接受中断
  
	USART_Cmd(UART4, ENABLE);                    //使能串口4 
  
 	 //如下语句解决第1个字节无法正确发送出去的问题
   	USART_ClearFlag(UART4, USART_FLAG_TC);       //清串口4发送标志
}

UART4的中断函数

void UART4_IRQHandler(void)			   //串口4全局中断服务函数
{
	u8 com_data;
  	//接收中断
	if( USART_GetITStatus(UART4,USART_IT_RXNE) )
	{
		USART_ClearITPendingBit(UART4,USART_IT_RXNE);//清除中断标志
		com_data = UART4->DR;
		Openmv_Receive_Data(com_data);//openmv数据处理函数
	}
}

本次实验我采用的是STM32F103zet6精英版单片机,具体配置请参考其数据手册。

接收openmv数据

void Openmv_Receive_Data(int16_t data)//接收Openmv传过来的数据
{
	static u8 openmv[18];	//存取数据
	static u8 state = 0;	
	static u8 bit_number=0;	
	if(state==0&&data==0x2C)
	{
		state=1;
		openmv[bit_number++]=data;
	}
	else if(state==1&&data==18)
	{
		state=2;
		openmv[bit_number++]=data;
	}
	else if(state==2)
	{
		openmv[bit_number++]=data;
		if(bit_number>=17)
		{
			state=3;
		}
	}
	else if(state==3)		//检测是否接受到结束标志
	{
        	if(data == 0x5B)
        	{
            		state = 0;
            		openmv[bit_number++]=data;
        	}
        	else if(data != 0x5B)
        	{
           		 state = 0;
            		for(i=0;i<18;i++)
            		{
               			 openmv[i]=0x00;
            		}           
        	}
	}    
	else
	{
		state = 0;
		bit_number=0;
            	for(i=0;i<18;i++)
            	{
               		 openmv[i]=0x00;
           	 }
	}
}

函数就是数据后先对比帧头是否正确,正确则进行数据存储,否则数据数组一直等待正确帧头的到来。

主函数

int main(void)
 {		
	delay_init();	    	 //延时函数初始化	  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
	uart_init(115200);	 //串口初始化为115200
	uart4_Init();
 	LED_Init();			     //LED端口初始化
	KEY_Init();          //初始化与按键连接的硬件接口
	LCD_Init();
	POINT_COLOR=RED;
  	while(1) 
	{	
		LCD_ShowNum(0,20,200,10,24);
		LCD_ShowNum(0,40,X_black_data,10,24); 
		LCD_ShowNum(0,70,Y_black_data,10,24);
		LCD_ShowNum(0,90,X_red_data,10,24);
 		LCD_ShowNum(0,110,Y_red_data,10,24);		     					 
		LCD_ShowNum(0,130,X_yellow_data,10,24);	  
		LCD_ShowNum(0,150,Y_yellow_data,10,24);	    		
	}  	 
 }

运行效果图片如下

“STM32单片机与Openmv的串口通信0"

“STM32单片机与Openmv的串口通信0"

“STM32单片机与Openmv的串口通信0"

注意事项

  • 若使用寄存器初始化串口,则应只有USART1使用PCLK2(最高72MHz)。其它USART使用PCLK1(最高36MHz)。
  • openmv的波特率应与接收端单片机串口波特率对应
  • openmv与STM32单片机两个串口的的数据格式应保持一致

版权声明:本文为CSDN博主「啊,小刘」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/LJH_1999/article/details/88782943
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。