OPENMV-STM32串口通信

阅读: 评论:0

OPENMV-STM32串⼝通信
OPENMV-STM32串⼝通信
⽬录标题
前⾔
最近要准备⼯巡赛,突然要发现需要进⾏视觉传动,所以我最近⼏天⼜温顾了⼀下Openmv,以前学习Openmv都是通过电脑对其进⾏控制,但是这样学习OpenMV是远远不够的,还需要实现与单⽚机的通信,本以为很简单,在CSDN,github上了⼀些开源代码,然后进⾏复制与粘贴,原本我以为这就掌握了,但是在后期的传输我犯了许多低级的错误,中间也反映了我的⼀些不⾜,我最后通过OLED连进⾏数据传输,调试后,我特地写下此博客来记录我⾃⼰的学习经历。
硬件选择
我选择的是openmv4 CamH7智能摄像头,OLED, stm32f104c8t6, ST-JINK, 若⼲数据线和杜邦线
硬件的通信连接
这是openmv4 CamH7智能摄像头,由图可知openmv4 CamH7只有1个串⼝,USART3,
由图知UART_RX—P5 UART_TX—P4
那么在STM32中
我们选择
PB10,PB11,来进⾏串⼝选择USART3.
STM32的TX(RX)接OpenMV的RX(TX),OLED连接到STM32即可
OPENMV软件分析
import sensor, image, time,math,pyb
from pyb import UART,LED
import json拇指再造
import ustruct
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])
cx=0;cy=0;
if blobs:
max_b = find_max(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)
在这⾥我借鉴了这位博主的代码
对于为什么不直接使⽤send()函数,在这⾥他是这么认为的
bytearray([, , ,])组合uart.write()的作⽤与直接调⽤sending_data(cx,cy,cw,ch)作⽤是⼀样的
我看来都⽆所谓,我是使⽤了send()函数,其实⽅法都⽆所谓的,只要能够传输数据就⾏。
在这⾥我们通过openmv对电脑进⾏串⼝通信来判断openmv是否通信成功,将openmv与TTL连接,打开串⼝助⼿XCOM来进⾏查看数据是否传输成功
串⼝通信成功,代码有效
让我们看看STM32的程序,我们要打开串⼝的驱动,我们要打开的串⼝驱动为USART3,
#include"uart.h"
#include"show.h"
#include"gpio.h"
u8 Cx=0,Cy=0,Cw=0,Ch=0;
void uart3_Init(void)
{
//USART3_TX PB10
//USART3_RX PB11
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
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);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel=USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
我不是宋承宪歌词NVIC_Init(&NVIC_InitStructure);
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(USART3,&USART_InitStructure);
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//使能中断
USART_Cmd(USART3, ENABLE);//使能串⼝3
USART_ClearFlag(USART3, USART_FLAG_TC);//清串⼝3发送标志
}
void USART3_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(USART3,USART_IT_RXNE)!=RESET)//接收中断
{
USART_ClearITPendingBit(USART3,USART_IT_RXNE);//清除中断标志
com_data =USART_ReceiveData(USART3);//串⼝3接收数据
if(RxState==0&&com_data==0x2C)//0x2c帧头开始数据接收处理
{
RxState=1;
RxBuffer1[RxCounter1++]=com_data;
忏悔录奥古斯丁
OLED_Refresh_Gram();
//    GPIO_SetBits(GPIOB,GPIO_Pin_4);
}
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)//检测是否接受到结束标志
陈礼久
else if(RxState==3)//检测是否接受到结束标志
{
if(RxBuffer1[RxCounter1-1]==0x5B)
{
USART_ITConfig(USART3,USART_IT_RXNE,DISABLE);//关闭DTSABLE中断
if(RxFlag1)
{
OLED_Refresh_Gram();
OLED_ShowNumber(0,0,Cx,3,16);
OLED_ShowNumber(0,17,Cy,3,16);
OLED_ShowNumber(0,33,Cw,3,16);
OLED_ShowNumber(0,49,Ch,3,16);
oled_show();
}
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;//将存放数据数组清零
}
}
}
}
代码解析:RxBuffer1[]数组是⽤来存储数据的,先存储帧头,后存储数据,帧头的数值可以任选,0x2c为数据帧的帧头,即检测到数据流的开始,但是⼀个帧头可能会出现偶然性,因此设置两个帧头0x2c与0x12以便在中断中检测是否检测到了帧头以便存放有⽤数据。
0x5b为帧尾,即数据帧结束的标志。我们储存数据完毕需要7次中断,进⾏完7次中断后才能将数据输⼊进去。
OLED模块由于代码的数据量过多,⽽且我使⽤的是六针OLED,对于OLED的驱动可能会与市场常见的OLED可能不⼀样,在这⾥我先把OLED的驱动填写上,
#include"oled.h"
#include"stdlib.h"
#include"oledfont.h"
#include"delay.h"
u8 OLED_GRAM[128][8];
/**************************************************************************
Function: Refresh the OLED screen
Input  : none
Output  : none
函数功能:刷新OLED屏幕,更新缓存,显⽰内容
⼊⼝参数:⽆

本文发布于:2023-07-11 07:59:37,感谢您对本站的认可!

本文链接:https://patent.en369.cn/xueshu/200323.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:数据   是否   标志   中断   检测
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 369专利查询检索平台 豫ICP备2021025688号-20 网站地图