Openmv與stm32 的串口通信
前言
假期準備參加電賽,學習了openmv,openmv識別到的資料傳到STM32,然后進行下一步的處理,為了實作來著之間的通信,花了很長時間,終于實作了,現在想想好像也挺簡單的,哈哈哈哈,但是對于我這種小白還是有點難,大佬就不用看啦!!
防止以后忘記,來CSDN做一個筆記吧!!
openmv端
在openmv端主要的作業是對目標物體進行識別,然后將需要的資料通過打包,再使用串口發送個單片機,這里有幾個關鍵的地方:
資料打包的格式:
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); #必須要傳入一個位元組陣列
打包的方式如上圖所示,為了防止資料錯誤,需要加入兩個資料幀頭和一個 資料幀尾,
openmv傳輸的資料的形式
openmv只能傳輸十六進制的資料給STM32,否則STM32將收不到資料,結果就是單片機和openmv都能正常和電腦通信,但是兩者結合就不能正常通信
十六進制資料的實作主要通過 bytearray ()這個函式,具體的格式如下:OUT_DATA =bytearray([0x2C,0x12,cx,cy,cw,ch,0x5B])
在openmv段主要的問題就是這兩個地方,區域的串口的配置,以及資料發送數都是常規的,openmv還有一種資料格式,就是json字串,都是我還沒試過,以后再補上,
openmv端完整的源代碼
from pyb import UART,LED
import json,ustruct,sensor,time
red_threshold = (2, 12, -56, 2, -75, 14)#測驗所用,白色,懶得該名稱
sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.RGB565) # use RGB565.
sensor.set_framesize(sensor.QQVGA) # use QQVGA for speed.
sensor.skip_frames(10) # Let new settings take affect.
sensor.set_auto_whitebal(False) # turn this off.
clock = time.clock() # Tracks FPS.
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[2]*blob[3] > max_size:
max_blob=blob
max_size = blob[2]*blob[3]
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() # Track elapsed milliseconds between snapshots().
img = sensor.snapshot() # Take a picture and return the image.
blobs = img.find_blobs([red_threshold])
if blobs:
max_blob = find_max(blobs)
img.draw_rectangle(max_blob.rect()) # rect
img.draw_cross(max_blob.cx(), max_blob.cy()) # cx, cy
cx=max_blob[5]
cy=max_blob[6]
cw=max_blob[2]
ch=max_blob[3]
OUT_DATA =bytearray([0x2C,0x12,cx,cy,cw,ch,0x5B])
uart.write(OUT_DATA)
print(OUT_DATA)
STM32 端
說到STM32 端真的是讓我走了很多的彎路,就因為printf()重定向,剛開始用的方式有點問題,讓我花了很多很多時間,導致串口除錯助手一直收不到訊息,還以為是板子壞了,最后發現是重定向的問題,這是兩種方式:
經過驗證后的正確方式:
# include "stdio.h"
int fputc(int ch ,FILE *f)
{
//輪詢方式發送一個位元組資料
HAL_UART_Transmit (&huart1 ,(uint8_t *)&ch , 1,HAL_MAX_DELAY );
return ch ;
}
關鍵點:
串口接收中斷 回呼函式:
/*串口接收中斷回呼函式*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
uint16_t tempt /*定義臨時變數存放接受的資料*/;
if(huart->Instance==USART2)
{
tempt=USART2_RXbuff;
Openmv_Receive_Data(tempt);
/*調運資料接收處理函式,每次進入中斷都對資料進行理處
,由于需要接收器個資料,因此要進入七次斷理*/
}
HAL_UART_Receive_IT(&huart2,(void *)&USART2_RXbuff,1);/*再次開啟接收中斷*/
}
最后的重新開啟中斷接收一定不能忘記;
資料讀取的函式
openmv.c
#include "OpenMV.h"
#include "stdio.h"
#include "usart.h"
/*四個變數用于存放目標物體的中心坐標以及寬度,高度*/
static uint8_t Cx=0,Cy=0,Cw=0,Ch=0;
/*資料接收函式*/
void Openmv_Receive_Data(int16_t Com_Data)
{
/*回圈體變數*/
uint8_t i;
/*計數變數*/
static uint8_t RxCounter1=0;//計數
/*資料接收陣列*/
static uint16_t RxBuffer1[10]={0};
/*資料傳輸狀態位*/
static uint8_t RxState = 0;
/*對資料進行校準,判斷是否為有效資料*/
if(RxState==0&&Com_Data==0x2C) //0x2c幀頭
{
RxState=1;
RxBuffer1[RxCounter1++]=Com_Data;
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);
}
else if(RxState==1&&Com_Data==0x12) //0x12幀頭
{
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
RxState=2;
RxBuffer1[RxCounter1++]=Com_Data;
}
else if(RxState==2)
{
RxBuffer1[RxCounter1++]=Com_Data;
if(RxCounter1>=10||Com_Data == 0x5B) //RxBuffer1接受滿了,接收資料結束
{
RxState=3;
Cx=RxBuffer1[RxCounter1-5];
Cy=RxBuffer1[RxCounter1-4];
Cw=RxBuffer1[RxCounter1-3];
Ch=RxBuffer1[RxCounter1-2];
printf("%d\r ",Cx);
printf("%d\r ",Cy);
printf("%d\r ",Cw);
printf("%d\r\n",Ch);
}
}
else if(RxState==3)//檢測是否接受到結束標志
{
if(RxBuffer1[RxCounter1-1] == 0x5B)
{
//RxFlag1 = 0;
RxCounter1 = 0;
RxState = 0;
}
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.h
#ifndef __OpenMV_H
#define __OpenMV_H
#include "stm32f1xx.h"
void Openmv_Receive_Data(int16_t data);
#endif
主函式里面沒什么太多的內容,主要是開啟中斷接收,以及一些變數的定義
/* USER CODE BEGIN 2 */
HAL_UART_Receive_IT(&huart2,(void *)&USART2_RXbuff,1);
HAL_UART_Receive_IT(&huart1,(void *)&USART1_RXbuff,1);
/* USER CODE END 2 */
/* USER CODE BEGIN PV */
uint8_t USART1_RXbuff; // 接識訓沖區;
uint8_t USART2_RXbuff;
uint8_t ch = 0;
cubemx 配置很簡單

最后就是接線的問題啦!!

完成,收工,有問題就私聊吧!!!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/291120.html
標籤:其他
