目录
一、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
发表评论