1. 程式人生 > >OpenMV資料打包傳送以及STM32對資料的解析(串列埠方式)

OpenMV資料打包傳送以及STM32對資料的解析(串列埠方式)

    今天嘗試了使用Openmv用串列埠傳送資料,32接收,遇到了一些坑,但是最後還是實現了,難住我的地方並不是關於傳輸的程式碼,而是那個板子串列埠3不知道因為什麼原因接收到的資料是錯誤的,這個原因正在尋找,找到了再記錄。

    Python提供了便捷的將資料打包的方法。我使用的方法就是將資料以二進位制的方式打包然後通過串列埠逐位元組傳送。

    struct模組的pack(fmt, v1, v2, ...)  函式提供了按照給定的格式(fmt),把資料封裝成字串(實際上是類似於c結構體的位元組流)的功能,關與格式,有一個表定義了所有支援的字元及資料格式,如下:

Format

C Type

Python

位元組數

x

pad byte

no value

1

c

char

string of length 1

1

b

signed char

integer

1

B

unsigned char

integer

1

?

_Bool

bool

1

h

short

integer

2

H

unsigned short

integer

2

i

int

integer

4

I

unsigned int

integer or long

4

l

long

integer

4

L

unsigned long

long

4

q

long long

long

8

Q

unsigned long long

long

8

f

float

float

4

d

double

float

8

s

char[]

string

1

p

char[]

string

1

P

void *

long

    microPython的串列埠使用方法也是很簡單的,程式碼如下

uart = pyb.UART(3, 115200)  #串列埠3,波特率115200
uart.init(115200, bits=8, parity=None, stop=1)  #8位資料位,無校驗位,1位停止位

    所以我在openmv的程式碼中定義了一個函式,來將傳入的倆個引數打包然後通過串列埠傳送,程式碼如下

def send_data_packet(x, y):
    temp = struct.pack("<bbii",                #格式為倆個字元倆個整型
                   0xAA,                       #幀頭1
                   0xAE,                       #幀頭2
                   int(x), # up sample by 4    #資料1
                   int(y)) # up sample by 4    #資料2
    uart.write(temp)                           #串列埠傳送

    為什麼不直接通過串列埠傳送字串然後使用sscanf來解析呢:串列埠傳送字串(ASCAII編碼)的方式比較簡單, 用C語言的sscanf()語句解析從語法上是完全可以的, 但是在實際工程上測試,解析不是很穩定,易丟資料。 ASCAII編碼易出錯,缺乏糾錯功能。所以我採用二進位制傳輸的,整數直接傳送,浮點數放大去除小數位,然後以C語言的int,short,char的拆分逐8位形式逐位傳送。 接收以後先計算校驗累加,再重組。這種方式長期使用穩定可靠。

    這樣發出來的資料(int,short型)都是低位的位元組在前,比如傳送整型數9,得到的資料為(0x09 0x00 0x00 0x00)

    所以32端的解析函式為

void Optical_Flow_Receive_Prepare(u8 data)
{
    /* 區域性靜態變數:接收快取 */
    static u8 RxBuffer[10];
    /* 資料長度 *//* 資料陣列下標 */
    static u8  _data_cnt = 0;
    /* 接收狀態 */
    static u8 state = 0;

    /* 幀頭1 */
    if(state==0&&data==TITLE1)
    {
        state=1;
    }
    /* 幀頭2 */
    else if(state==1&&data==TITLE2)
    {
        state=2;
        _data_cnt = 0;
    }
    /* 接收資料租 */
    else if(state==2)
    {
        RxBuffer[++_data_cnt]=data;
        if(_data_cnt>=8)
        {
            state = 0;
            Data_Processing(RxBuffer,_data_cnt);
        }
    }
    /* 若有錯誤重新等待接收幀頭 */
    else
        state = 0;
}


void Data_Processing(u8 *data_buf,u8 num)
{
	int theta_org,rho_org;
    /* 讀取偏移角度原始資料  */
    theta_org = (int)(*(data_buf+1)<<0) | (int)(*(data_buf+2)<<8) | (int)(*(data_buf+3)<<16) | (int)(*(data_buf+4)<<24) ;
    theta_err = theta_org;

    /* 讀取偏移尺寸原始資料 */
    rho_org = (int)(*(data_buf+5)<<0) | (int)(*(data_buf+6)<<8) | (int)(*(data_buf+7)<<16) | (int)(*(data_buf+8)<<24) ;
    rho_err = rho_org;
}

    通過這樣的方式就能將Openmv計算的資料通過串列埠傳送給32,過段時間我會做一個基於openmv+32的尋線小車,單雙軌的尋線演算法已經弄好了,做完以後我會發部落格記錄。