1. 树莓派( `7 r J& q {* \7 x' y
% [4 q$ _2 W; K' A' Y4 G
树莓派端我们需要找到USB端口设备,我的树莓派上是CHASSIS_SERIAL_PORT = '/dev/ttyUSB0',获得了端口设备之后就可以开始调库了,这也是python语言的拿手好戏。这次我们用的库是serial,我们需要这个库里的函数
, z) U# w3 ^) D1 n: Q! R: m
9 z8 O2 d* I( e. Y5 p6 N串口初始化:self.port_chassis = serial.Serial(CHASSIS_SERIAL_PORT, 9600, timeout=1)
g. O% X( v3 L# e4 F: }9 v
$ X. M1 e/ i2 {4 l- e3 a+ r发送数据:self.port_chassis.write((direction + str(distance)).encode())4 c/ ^6 w9 \& O1 o
& ~6 [, z5 Y2 c; j
读取数据:self.port_chassis.readline().decode()7 [' D. r9 R% B, i6 m& a% @
. g- r8 {0 f2 J! o4 T
流初始化:
3 v$ E6 `, G0 E; O8 Wself.port_chassis.flushInput();self.port_chassis.flushOutput()* R% {0 c7 r j) w1 v! n
6 J: }% q) x0 q, v9 Z D有了上面几个函数之后,就可以开始写python脚本啦,结合代码来进行分析
9 \6 e8 e% \: Z首先是类的初始化函数,目的主要是初始化USART(UART)的波特率
2 J9 P0 R: q$ d' Y! J* m- <font face="微软雅黑" size="3">def __init__(self):) U* N! w/ {$ R# k* L( Y2 X3 R2 ~
- print("move init finish")
' _. ~! G/ L/ `7 G1 k4 _ s. o - self.time1 = time.time()
. n& K0 T0 f& G. {( F& D0 { - self.time2 = time.time()0 m y# a9 W2 ]( K2 E. ]2 s
- self.flag = False
, }$ ^5 M& S# {8 Z6 r9 g" h - self.port_chassis = serial.Serial(CHASSIS_SERIAL_PORT, 9600, timeout=1)
) L" Z) G6 A' Z) F - # print('port_chassis is :' + self.port_chassis.is_Open())! k* v0 @3 v) q
- self.port_chassis.flushInput()' e9 j- m0 q0 a! }; m" b: T7 ?
- self.port_chassis.flushOutput()</font>
复制代码 接下来就是发送数据,我们的购物机器人是通过树莓派做为整个的 “大脑”,是由树莓派里的python脚本给底盘发送指令,所以这个函数就是python让底盘移动distance个格子的函数,这个函数里面也是通过USART(UART)给底盘发送指令的,所用函数就是self.port_chassis.write((direction + str(distance)).encode())0 W2 T) u7 ^9 K! z( B
- <font face="微软雅黑" size="3"> def move_by_grid(self, direction, distance=''):
9 M$ L# F6 |6 n8 n( y3 f5 t - # print('move by grid')
6 H+ P8 c4 E, N4 m( N - self.port_chassis.write((direction + str(distance)).encode())0 n7 ^8 z$ D8 L, |; `
- self.time1 = time.time()8 I$ Z; t6 c' @2 E8 J& ^- S
- print(direction + str(distance))
+ j, o, O+ J6 O& U! I& V - self.wait_for_act_end_signal_chassis(direction, distance)</font>
复制代码 最后是接收数据,既然树莓派要控制底盘,树莓派自然也要接收到底盘回传的数据,这里用到的USART(UART)接收数据函数是self.port_chassis.readline().decode(),sig就是树莓派接收到的USART(UART)数据,用户就可以对其做处理啦。" \8 s( S# J% `
- <font face="微软雅黑" size="3">def wait_for_act_end_signal_chassis(self, ret=None, distance=0):8 R# j9 }5 F5 ~% t3 I8 W- _
- print('waiting chassis...')& [. X3 R1 {' }/ t
- while True:
& J0 i1 x, ~( W5 t$ ]) K6 `% F - sig = self.port_chassis.readline().decode()
6 T% R% F0 m. _ - 9 l v. [' {0 q4 K3 D
- # print(self.time2 - self.time1)6 b% I8 J: ` V2 z9 B
- . F1 {, M0 K0 |4 B j& n3 o
- sig = sig[0:2]1 w! k: L A) H* b3 H# I) W- r" b, q
- print(sig)' H- N# t/ n2 g5 k; y5 F: U# n8 |
- #( @4 S5 R7 @2 e% [) }
- if sig == 'HI':
* ?" r2 a; }1 P7 k4 I8 j - self.time2 = time.time()
+ z! n( n' T7 S, ?0 r - print(self.time2 - self.time1)% z1 H( j/ b1 A' I5 r5 c: v/ n i1 z/ x
- if self.time2 - self.time1 < 1.0 and self.flag == False and distance == 1:
0 P# J5 J9 Z- P - print('1 step deal error')
: D" n! l( ` Z* @ - self.flag = True
, H6 u! _- u3 T5 E0 g+ x% f2 _ - if (ret == dir_up or ret == dir_back): g! x5 a5 ?; G$ E
- self.move_by_grid(ret, 1), g6 f- A$ V {( X( Z2 F% k4 D
- else:</font>
复制代码
( H$ w9 A/ V& a2 H; ] d, s$ R/ j9 @7 s" q ? W2 n4 `3 }6 s
2. STM32F427IIH6
# E, R. V% l, e' H* a* \6 E0 V, b. W# N- ^. w1 I1 \& F2 j9 N7 n
+ D0 Z) R2 x: X" F% L! z9 p6 t
在嵌入式芯片STM32F427IIH6里,我们首先要打开芯片的DMA功能,然后进行USART(UART)的初始化,最后设置USART(UART)的回调函数即可。+ `" m: x: e% ?( l! ?4 y
a8 Z! z9 z4 J: W' P
$ ^) Q: P- D9 B. T( _7 o
首先进行DMA的初始化,在这些初始化里面完成的就是DMA时钟的使能和DMA中断的使能。' |& m8 Y1 ]0 K+ _5 h
+ a) p. B2 J: V4 G% K, j- <font face="微软雅黑" size="3">void MX_DMA_Init(void) & u, u' R9 L4 P" O9 l: d, r
- {
: b ~' ~9 d+ s7 k, Q: e) c -
6 o' K% |! m! k- o; P# y - /* DMA controller clock enable */% g/ R7 V- A( s8 m3 K5 u2 Q
- __HAL_RCC_DMA1_CLK_ENABLE();
% R! D" ~: Z" `) |6 v9 ]& y- J% A- P - __HAL_RCC_DMA2_CLK_ENABLE();
3 N: L4 ~8 M" h# {; v5 z, r+ {; ] - $ d% X! b3 q7 L9 v. P" H
- /* DMA interrupt init */% Y/ y+ w* O# ]! e
- /* DMA1_Stream0_IRQn interrupt configuration */9 l8 s( O" `5 ~- U. R
- HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0); y( `" T# w9 j- R* U; T
- HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);' B Z; h* C8 t# f
- /* DMA1_Stream1_IRQn interrupt configuration */6 s, J. E- ]: ^- c1 ~7 V
- HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);& l+ ]0 @! B6 P P! F6 G8 p
- HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);% c) E5 P1 I# x' h
- /* DMA1_Stream3_IRQn interrupt configuration */' X3 N/ I- i7 K5 j$ C
- HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 0, 0);$ m; S; j- a9 K' }7 r% i( l8 ~" Y8 W
- HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);$ k/ O! K" j+ v
- /* DMA1_Stream6_IRQn interrupt configuration */: {( _ w$ v/ H- G* j9 o- M
- HAL_NVIC_SetPriority(DMA1_Stream6_IRQn, 0, 0);& |8 O0 h9 d7 L) x3 e
- HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn);
: h3 ]" D7 @$ F( K; ^ - /* DMA2_Stream1_IRQn interrupt configuration */
# c2 P, Y+ d# X5 e& j, i# x - HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0, 0);8 ]6 e# i, H2 }' Q: [7 l1 N# W
- HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);" ^ Q8 m- d) y
- /* DMA2_Stream6_IRQn interrupt configuration */
/ Z$ {7 {8 Z7 q& X5 ^6 ^0 X- | - HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 0, 0);/ K) _; N# e4 r( P3 D
- HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
0 [( a, ]0 i% z3 |/ } -
6 A0 ]( y9 r0 P- Z8 A - }1 s5 S. `* ]3 K5 M+ I
- </font>
复制代码 DMA使能完成之后就要进行USART(UART)的基本配置了,这里我设置的就是波特率9600(各个USART(UART)波特率初始化大同小异,因此在这里只放了usart6的初始化,其他类似,不做赘述)。9 d$ P# q4 U* {- Z3 T
- <font face="微软雅黑" size="3">void MX_USART6_UART_Init(void)# [7 r: k( W3 ?( a x `
- {
! M9 r X4 I8 D4 ]6 l5 ~! z, i - . Z# q0 D, e( Z4 c; n& r* u, f8 j3 P
- huart6.Instance = USART6;
8 k; B2 x! U! p* P& H P - huart6.Init.BaudRate = 9600;
w- A8 u% ^+ Q! e; k' l' {0 a - huart6.Init.WordLength = UART_WORDLENGTH_8B;
# @2 R* R {8 | - huart6.Init.StopBits = UART_STOPBITS_1;
0 a; V( }! f& z1 a: p% |9 T* T - huart6.Init.Parity = UART_PARITY_NONE;
, m- D* v2 l% D' H! a, L - huart6.Init.Mode = UART_MODE_TX_RX;7 D6 Z& O2 s5 t8 N' o. l
- huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE;
: C) E1 q7 ?8 g/ T$ t, M - huart6.Init.OverSampling = UART_OVERSAMPLING_16;% Q" L( F4 ?1 t* L0 [% s& C
- if (HAL_UART_Init(&huart6) != HAL_OK)
( ]+ O% R, `6 j; D% F6 m7 O* { - {
' Y5 F/ u. i2 |" f0 c/ l) c; ^ - Error_Handler();1 {: E5 B4 H ?' k. [
- }
7 F" I2 }1 \1 j, o7 l- F! M -
5 S1 \: `5 h) [0 X& ` - }</font>
复制代码 完成了芯片级的配置之后,就要开始配置用户自己需求的USART(UART)功能了,简单点来说就是就是设置回调函数,并且编写回调函数内容。
# l- i9 R5 [! R# W( G* V' h( N7 Y0 \7 k
2 u( o+ y( L. U
2 d* h i, S3 A; `
+ i0 o% T$ t- R% z在void USR_UartInit(void)中主要是打开USART(UART)的DMA接收功能,并且开启USART(UART)接收中断,HAL_UART_IdleCpltCallback(UART_HandleTypeDef *huart)就是我们的回调函数,uart6Rx[1024],uart7Rx[1024],uart8Rx[1024]这3个数组就是STM32F427IIH6的3个(USART6,UART7,UART8)USART(UART)接收到的数组数据 啦,接下来用户就可以对其做处理啦。" J. G4 ~0 f0 F7 I7 r; l
- <font face="微软雅黑" size="3">" q) N! N" {5 F X9 `$ ?
- void USR_UartInit(void)9 |+ h( }$ B; @ j9 t
- {
* W0 {/ d4 x r F% z% | - test1++;
0 Z: ]* C* C1 T, A- N - % p( t9 [, o) d% M8 j; ?4 l1 Z
- uart8RxLength = 0;
9 a5 S% A, z" g! w v' a - HAL_UART_Receive_DMA(&huart8, uart8Rx, buffer_size);1 t; ~; p" k" w- ]0 P- D0 U) z3 i9 f0 l
- uart7RxLength = 0; 7 l3 C- w; M' E1 W3 s
- HAL_UART_Receive_DMA(&huart7, uart7Rx, buffer_size);
& U. a$ Q" {1 }* w - uart6RxLength = 0; - y3 J+ B8 F) J. a! z
- HAL_UART_Receive_DMA(&huart6, uart6Rx, buffer_size);
; u' S* R1 q6 \# F/ ~ - & C0 r, Y R! l! m: t; ~
- __HAL_UART_ENABLE_IT(&huart8, UART_IT_IDLE);
- Y6 j, q) l4 Z+ G( Y1 u - __HAL_UART_ENABLE_IT(&huart7, UART_IT_IDLE); J- c$ _! O* ^& ]; I
- __HAL_UART_ENABLE_IT(&huart6, UART_IT_IDLE); " D k# }. D, h# ~: L- e
- }" r$ p' \% |8 n6 j: z
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
1 X7 h# J. Z! t - {/ a4 H4 d& \7 s
- ) A6 R" o3 Y2 f2 m* ?% V4 e
- HAL_UART_Receive_DMA(&huart8, uart8Rx, buffer_size);
, p$ w* u: h8 `5 K! M6 | - HAL_UART_Receive_DMA(&huart7, uart7Rx, buffer_size);
3 t0 s% z+ G3 A/ h) L0 W/ I% T( m - HAL_UART_Receive_DMA(&huart6, uart6Rx, buffer_size);. s4 @9 k" e( |2 {
- __HAL_DMA_ENABLE(&hdma_uart8_rx); " i3 _7 H9 \% y- ]
- __HAL_DMA_ENABLE(&hdma_uart7_rx);5 h0 a g1 P+ p, K+ t! d
- __HAL_DMA_ENABLE(&hdma_usart6_rx); o! J5 i* s/ y# Y% B% o
- test2++; E: \( |) ?& g7 f
- }- }$ g( U+ G& R% l. ]# [
- uint8_t RxLenHi, RxLenlo;
9 E% u' ]/ r$ P N# s - void HAL_UART_IdleCpltCallback(UART_HandleTypeDef *huart)! x+ q5 y' D/ c1 w9 Q
- { q1 c: K) n9 x8 s, b
- __HAL_UART_CLEAR_IDLEFLAG(huart);" p) x7 ?, e6 P9 K
- / Y* v) Z, ~6 u5 {) ^' k) r
- if( huart == &huart8)
3 B$ D0 N* t8 w, y - {3 K* f% j& t, X# [& D$ [7 C7 Y
- test3++;/ i( C7 [4 d+ m) G& V. F
- HAL_UART_Receive_DMA(&huart8, uart8Rx, buffer_size);
7 A* @. \7 J6 E! _; E8 i' c -
5 k8 F2 a/ I- E - uart8RxLength = buffer_size-__HAL_DMA_GET_COUNTER(&hdma_uart8_rx); # R- F; U k6 }, |
- if(uart8Rx[0]=='@'7 Q2 K) M& f1 D( F5 ?
- &&uart8Rx[1]=='c'
0 J2 J, J: Y9 f7 ` - &&uart8Rx[2]=='m'
3 ^0 ~2 d4 O' o4 k - &&uart8Rx[3]=='d')
$ a* e4 l: y, { v$ _" r - {# \9 ^5 m1 o& \( t
- if(!SERDEB_CmdValid())
7 H6 I) Y' I0 N4 q5 a+ r - SERDEB_PushCmd(uart8Rx, uart8RxLength);
) B3 k2 q0 x6 y( V( F) A- n - }
4 a: l+ A9 H3 J - __HAL_DMA_DISABLE(&hdma_uart8_rx);
& _% c0 e4 V$ k8 T0 T U - HAL_GPIO_TogglePin(GPIOG,GPIO_PIN_8);
! Q/ f) S* T2 k6 H( C( l - }) b+ m: }3 R$ c$ R0 j' D
- / f. n! c9 Z1 V- R
- if( huart == &huart7)6 o$ N4 u$ c. b" }! M" e
- { , t6 d9 S% L% m4 D, j3 J
- __HAL_DMA_DISABLE(&hdma_uart7_rx); 6 M& w. a# m- k. [& L# b5 K$ M
- HAL_UART_Receive_DMA(&huart7, uart7Rx, buffer_size);
3 l0 @6 A9 e0 G0 N! ~8 p - __HAL_DMA_DISABLE(&hdma_uart7_rx);$ O0 V1 Q" s$ h) s; U& B7 f7 }
- }
' ?0 i3 m5 y, s) u$ ^3 Z+ T5 A - % W, W, n' r2 _8 J. f' {" r
- if( huart == &huart6)" J" B6 \, S5 Z) T8 l3 I/ R( o" o3 d. H
- {# S: U. V1 O& y* B# w
- __HAL_DMA_DISABLE(&hdma_usart6_rx);
, b0 _& C: Y0 L+ G/ Z/ E# h" _8 n2 j/ l$ \ - HAL_UART_Receive_DMA(&huart6, uart6Rx, buffer_size);
1 \( Q9 L2 D; N3 h7 Z - __HAL_DMA_DISABLE(&hdma_usart6_rx);
0 J8 h3 P5 s" ^% c% i3 `- h$ g7 |* ] - }/ c. H5 y% T0 e6 d* \, c
-
" b/ y% C0 x2 v2 j8 d3 ?" u9 c8 w - }</font>
复制代码 至此完成了双工通信的基本配置。' F# ^3 J7 T% T! X6 W* E/ Y% S
: |5 @8 \ q' W+ h( Z( V$ B- s; \$ P) l% B+ }" I8 k
$ X" g; @; s2 o: S, ~+ ?$ |4 ^% ^! o3 f# x* k9 T7 @# x( e
|