1. 树莓派1 n9 p& o( F. _6 L$ R
, j) `; P( `! W, E1 C2 L
树莓派端我们需要找到USB端口设备,我的树莓派上是CHASSIS_SERIAL_PORT = '/dev/ttyUSB0',获得了端口设备之后就可以开始调库了,这也是python语言的拿手好戏。这次我们用的库是serial,我们需要这个库里的函数3 u y( ~6 F9 B) \
$ v. L, P$ W, c& @) `* z7 c串口初始化:self.port_chassis = serial.Serial(CHASSIS_SERIAL_PORT, 9600, timeout=1)3 I7 o/ Q7 c) _9 _
; l$ o2 U2 Z {; |* e6 C- n5 |发送数据:self.port_chassis.write((direction + str(distance)).encode())/ ~! k- x3 x4 g. A# M; O
1 f! b0 m- _( M/ l读取数据:self.port_chassis.readline().decode()1 R0 x6 X7 U% N8 T4 S
" J! @( A' d2 v, S! G" q
流初始化:
" _0 T! r a4 J& x& pself.port_chassis.flushInput();self.port_chassis.flushOutput()
3 B( m2 N% { l# L- i; j( o# {$ k; I! g3 m: g
有了上面几个函数之后,就可以开始写python脚本啦,结合代码来进行分析
. g. ~8 V* u! W) I1 m7 U4 z首先是类的初始化函数,目的主要是初始化USART(UART)的波特率" ~$ a) O2 z |2 ~( i0 A
- <font face="微软雅黑" size="3">def __init__(self):& P2 z/ `) I6 \ Q& j; ~: H
- print("move init finish"), L5 A& x _3 n$ m) R
- self.time1 = time.time()
+ H& L" p2 U: J: v" c - self.time2 = time.time()
$ V1 w, D" T9 v2 d; q - self.flag = False& a( g0 V$ T! X% X, M
- self.port_chassis = serial.Serial(CHASSIS_SERIAL_PORT, 9600, timeout=1)4 ?- ^" f( ?- j4 Z9 j0 ^9 M& o
- # print('port_chassis is :' + self.port_chassis.is_Open())2 S h# @7 q. a7 ^
- self.port_chassis.flushInput()
5 i* Y; B% D6 \$ o* ]& ]7 j - self.port_chassis.flushOutput()</font>
复制代码 接下来就是发送数据,我们的购物机器人是通过树莓派做为整个的 “大脑”,是由树莓派里的python脚本给底盘发送指令,所以这个函数就是python让底盘移动distance个格子的函数,这个函数里面也是通过USART(UART)给底盘发送指令的,所用函数就是self.port_chassis.write((direction + str(distance)).encode())
: e9 B- e; {$ C2 u5 \- <font face="微软雅黑" size="3"> def move_by_grid(self, direction, distance=''):9 {4 M+ B _6 O( H7 N5 P& A$ e
- # print('move by grid')4 [& w8 l: O% ]) R6 j+ R
- self.port_chassis.write((direction + str(distance)).encode())
" [ y5 r/ b) Y2 h2 {- q, {; ^ - self.time1 = time.time()& y3 B) i$ s( r8 s+ y
- print(direction + str(distance))- {* \$ }4 }0 i9 h. b
- self.wait_for_act_end_signal_chassis(direction, distance)</font>
复制代码 最后是接收数据,既然树莓派要控制底盘,树莓派自然也要接收到底盘回传的数据,这里用到的USART(UART)接收数据函数是self.port_chassis.readline().decode(),sig就是树莓派接收到的USART(UART)数据,用户就可以对其做处理啦。( a* Q% \6 Z3 g- R+ r) j# L& e
- <font face="微软雅黑" size="3">def wait_for_act_end_signal_chassis(self, ret=None, distance=0):
. F6 L7 l* T8 f - print('waiting chassis...')
1 N+ ?4 P7 ]" T2 N/ x - while True:% g2 f& e; Y: H, o
- sig = self.port_chassis.readline().decode(). e0 d/ g5 s) ]
- " I* k3 j5 ?1 L4 x8 i
- # print(self.time2 - self.time1)6 z0 J. M4 p6 z8 q
- % h; J4 j8 k! C [
- sig = sig[0:2]
- b9 U6 T _) U: p& M b - print(sig)2 t2 D& \4 h$ u# I& }5 |
- #
9 X2 U! z* E! q. `( W+ | - if sig == 'HI':
5 `3 [' ]$ r7 `( w. N8 G/ k) P - self.time2 = time.time()
/ i( m6 g$ [ t' h8 F - print(self.time2 - self.time1)/ V% ^5 p/ f4 g" R; M% s4 ~# r
- if self.time2 - self.time1 < 1.0 and self.flag == False and distance == 1:7 ]) S5 \" j p( E/ i
- print('1 step deal error')% l1 ~$ ]8 a% @: T2 g9 I4 y
- self.flag = True
' |" n3 J/ o' n z; N7 T - if (ret == dir_up or ret == dir_back):
& Q9 f( S9 W8 W/ R7 S& b& @" q4 C - self.move_by_grid(ret, 1). O7 F6 r; c D
- else:</font>
复制代码 8 h. S8 X7 \+ ?4 [3 N
8 B5 _8 f4 x# g' v( Q8 h5 s0 m$ T
2. STM32F427IIH6
7 E, G1 R! V7 W
4 I- W/ I8 `9 n2 W( p4 b h
: \; r9 V. M( v W+ k在嵌入式芯片STM32F427IIH6里,我们首先要打开芯片的DMA功能,然后进行USART(UART)的初始化,最后设置USART(UART)的回调函数即可。$ O' P7 y$ a3 `5 j7 _" p2 d- f: o
, R! `5 x4 F& E' W7 [7 J
9 H8 F9 t. T. k首先进行DMA的初始化,在这些初始化里面完成的就是DMA时钟的使能和DMA中断的使能。
7 K* N. P" M- B! K) r7 @2 J M: g: |) G$ K' J
- <font face="微软雅黑" size="3">void MX_DMA_Init(void) ' S5 O3 U6 f/ j- } I
- {/ w' u6 B2 s, p( b3 U
-
( `& S4 ~4 O1 U - /* DMA controller clock enable */) F, D; J0 P4 Q# |. r- t/ T
- __HAL_RCC_DMA1_CLK_ENABLE();
* @; T* l, F) [ - __HAL_RCC_DMA2_CLK_ENABLE();/ q4 r9 I% m) Z6 S+ D
-
" ~+ D+ ~0 `# Y( ^' f - /* DMA interrupt init */0 N; e2 F2 {/ W) X* ]
- /* DMA1_Stream0_IRQn interrupt configuration */) l) y. Q( u: q9 S; O o
- HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
8 R5 b+ |7 r. K$ D+ A! _ - HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
; X% J$ I2 {; O9 k/ r" G - /* DMA1_Stream1_IRQn interrupt configuration */5 X. P) Y2 J* k4 ] O& w3 U
- HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);1 t. U h" |, r
- HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
3 A4 X. y5 W. ?: _, ?; y# G - /* DMA1_Stream3_IRQn interrupt configuration */8 S9 |% [+ e( o% H. S# H
- HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 0, 0);
" M( L1 [% h y( `- O - HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
/ T) @! O+ L$ B: ~2 P: J - /* DMA1_Stream6_IRQn interrupt configuration */( V3 G' g* f* ?# V) _1 V
- HAL_NVIC_SetPriority(DMA1_Stream6_IRQn, 0, 0);
3 R; h; q3 m+ h$ F: } - HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn);4 p `8 ]9 I, z8 y" A6 f
- /* DMA2_Stream1_IRQn interrupt configuration *// i/ Q9 q! g+ M: ^2 V
- HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0, 0);% Q) s/ s' I- Q Z @* y
- HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);7 W ` h5 ^5 s+ f
- /* DMA2_Stream6_IRQn interrupt configuration */
, F0 {' n" B' i6 a - HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 0, 0);! x* a3 ]- X4 [0 a6 ]
- HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);' e) ]7 }* P! Z' M
-
0 {9 H x' M6 a& c - }
3 g& P+ l$ \' ]6 g% B3 ^ - </font>
复制代码 DMA使能完成之后就要进行USART(UART)的基本配置了,这里我设置的就是波特率9600(各个USART(UART)波特率初始化大同小异,因此在这里只放了usart6的初始化,其他类似,不做赘述)。 X4 b: a6 A, O! v! F
- <font face="微软雅黑" size="3">void MX_USART6_UART_Init(void)
6 j0 ?6 W T3 l+ @, s9 q - {
) p; P* G+ N4 m4 P5 c3 Q9 l -
" ~4 E" A) Q% y, L - huart6.Instance = USART6;8 _) k4 g: J& Z- A5 H
- huart6.Init.BaudRate = 9600;4 g, B d0 Z/ E# @* h: m
- huart6.Init.WordLength = UART_WORDLENGTH_8B;' @5 n. i1 ^- I4 d4 r' ^& _
- huart6.Init.StopBits = UART_STOPBITS_1;
0 X5 e* z, H0 G" @1 R - huart6.Init.Parity = UART_PARITY_NONE;3 E9 q" P% u6 n0 }4 I
- huart6.Init.Mode = UART_MODE_TX_RX;
4 }# F2 j7 d! q% T" \ - huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE;
* p! y+ W( G- K- l8 W @; D - huart6.Init.OverSampling = UART_OVERSAMPLING_16;8 ]* |7 W' I3 T. D2 i2 C) u
- if (HAL_UART_Init(&huart6) != HAL_OK)* r& f3 Q% O' `" Y! k% S: d! O
- {0 \- S! c! H3 ]% P; s2 t9 ^
- Error_Handler();. d2 m, q8 p; \! T* |6 G( S% K
- }
9 L, X; G- w0 D! X( ~3 N# `0 ? -
6 f, S; Q4 [% j2 ~2 L - }</font>
复制代码 完成了芯片级的配置之后,就要开始配置用户自己需求的USART(UART)功能了,简单点来说就是就是设置回调函数,并且编写回调函数内容。) B2 f, N+ G3 M% n
; ]/ c& m, v0 A0 ]: k% [& o% f) j* ^% T. G9 q; D# T' ^8 S
0 a2 a! X+ n3 S& D7 k: Q( K, |
) Y; ?& r$ T5 `! U在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)接收到的数组数据 啦,接下来用户就可以对其做处理啦。3 P! J/ X6 |" O( B) }
- <font face="微软雅黑" size="3">
* f4 l! A' U* T - void USR_UartInit(void) O/ e/ [% |5 _) g. a& ~
- { g2 o& @) N( Y' B j8 V9 B7 F
- test1++;; q9 \* [* w* G2 w# w% G% G7 ~
- ) s& z v/ [8 b% R# Y
- uart8RxLength = 0; 7 B4 ]9 E: i0 k2 X4 _ F
- HAL_UART_Receive_DMA(&huart8, uart8Rx, buffer_size);
. _% k3 o/ E3 S" F6 i! }3 Y9 } - uart7RxLength = 0; g( s8 X& ?8 Z$ Z. Q
- HAL_UART_Receive_DMA(&huart7, uart7Rx, buffer_size);
5 D! E$ r) ]. |+ E - uart6RxLength = 0;
( @# C4 p5 ^* g5 X5 _& r: J3 ? - HAL_UART_Receive_DMA(&huart6, uart6Rx, buffer_size);
0 W l/ v% k* a1 Y4 ~1 F -
7 w' X: n! ]) N- O1 {2 Y. h8 B - __HAL_UART_ENABLE_IT(&huart8, UART_IT_IDLE);
! e7 c) {* u* l: N4 x - __HAL_UART_ENABLE_IT(&huart7, UART_IT_IDLE); & m' u1 d* C9 v) p7 a/ J1 c! f
- __HAL_UART_ENABLE_IT(&huart6, UART_IT_IDLE);
. r- V; ?2 n0 {* M) \ N - }) G S: r r' F% l/ L' _$ |+ I' d
- void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
0 |* _( }( |3 T# R - {
, s: b) h) e7 k: s -
9 a% C& J) K/ y4 Y, J7 } - HAL_UART_Receive_DMA(&huart8, uart8Rx, buffer_size);
3 t2 i6 x+ ]3 b4 Q/ e - HAL_UART_Receive_DMA(&huart7, uart7Rx, buffer_size);
p9 E- U+ \4 j w. j9 |) ^1 v - HAL_UART_Receive_DMA(&huart6, uart6Rx, buffer_size);7 h& K& s5 p8 G0 l' K1 z; P
- __HAL_DMA_ENABLE(&hdma_uart8_rx);
9 t3 B/ V: s$ ~! E- J - __HAL_DMA_ENABLE(&hdma_uart7_rx);5 }. B- t, w3 a9 m& i9 B: i2 H
- __HAL_DMA_ENABLE(&hdma_usart6_rx);
8 A( M" _- Y% V/ p - test2++;
- L. b/ v7 J; G. ^8 F - }, l; o6 p0 }4 N0 x. H- V2 L
- uint8_t RxLenHi, RxLenlo;
% l! h: B8 W( U( X% C4 v - void HAL_UART_IdleCpltCallback(UART_HandleTypeDef *huart)8 J4 b( _. w, D
- {6 a6 o+ z, c( e7 x% e u0 ~* a
- __HAL_UART_CLEAR_IDLEFLAG(huart);
1 B# u( [$ X9 X, q& d% w) @ - 2 n+ v' x% U5 J9 b3 U2 H& I3 X$ q/ `, P
- if( huart == &huart8)3 E& V! ~* m _5 m) [
- {# @! l6 u+ T9 Z0 t: z5 {! ?
- test3++;+ d7 s+ |( P! s: P( z1 E% Q/ Q
- HAL_UART_Receive_DMA(&huart8, uart8Rx, buffer_size); 0 Q0 c$ @; v& [- z+ t1 |
- - w0 P+ p. g+ b" O
- uart8RxLength = buffer_size-__HAL_DMA_GET_COUNTER(&hdma_uart8_rx);
/ T7 e0 P, k8 `% q - if(uart8Rx[0]=='@'
7 m W- p$ E9 P& m+ _2 P+ w3 @ - &&uart8Rx[1]=='c'
/ |7 M0 _1 Y: e1 z" r - &&uart8Rx[2]=='m'
- f1 _3 J0 F: E9 C& d7 f' `3 t5 A - &&uart8Rx[3]=='d') 2 l* `/ ?' ^( G" c3 R1 g: `
- { X5 S& L. I5 L# \
- if(!SERDEB_CmdValid())) J6 r! }& ?* t- @2 q* d$ D
- SERDEB_PushCmd(uart8Rx, uart8RxLength);
8 R7 q9 j0 a& [ E4 O1 y - }- q6 [/ `* E6 p
- __HAL_DMA_DISABLE(&hdma_uart8_rx);
$ x! {$ P4 ^3 I M# p; ? - HAL_GPIO_TogglePin(GPIOG,GPIO_PIN_8); ; T( B; I0 g1 q n% A9 r/ O
- }
& r0 r& T. f) ]0 V) B) C( M -
% b3 @7 @( l- J4 d - if( huart == &huart7)0 R6 d0 Q2 K3 d M1 Q( P3 F: Q
- { ' f/ l6 B" J6 y
- __HAL_DMA_DISABLE(&hdma_uart7_rx);
, X% M2 u3 g t S9 C, M( O& |! x6 | - HAL_UART_Receive_DMA(&huart7, uart7Rx, buffer_size); / D G+ Z3 {2 {. l2 i% S# f( l
- __HAL_DMA_DISABLE(&hdma_uart7_rx);
$ u! b) s/ I* B - }
4 z V0 v9 G5 k8 W; P -
0 H4 b' u1 w8 v# V9 }4 u2 E - if( huart == &huart6)
8 A# g; | U6 C5 c5 `! J - {
2 f3 s- T: L! l1 X2 c- p - __HAL_DMA_DISABLE(&hdma_usart6_rx);3 Y- G: [5 @/ ?1 d$ _! F: B
- HAL_UART_Receive_DMA(&huart6, uart6Rx, buffer_size); 2 H- @3 A& ~& A9 S8 Y: b
- __HAL_DMA_DISABLE(&hdma_usart6_rx);
8 D* Y3 e+ \2 y - }' ^4 n% ~1 X6 {( Y9 `- N6 N
- 1 [# B! q* W6 F, z
- }</font>
复制代码 至此完成了双工通信的基本配置。, f5 P# H! t1 h1 P
9 t3 R5 N( ^, Z& t/ i0 H0 K2 k/ G2 @% U2 I4 L* f% \
! U5 g# f* A/ X4 s ^3 o6 S! c& P' ~$ ?9 o, ?* r( d
|