你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F427IIH6芯片通过DMA+USART与树莓派进行双工通信

[复制链接]
STMCU小助手 发布时间:2021-7-26 11:27
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
  1. <font face="微软雅黑" size="3">def __init__(self):& P2 z/ `) I6 \  Q& j; ~: H
  2.         print("move init finish"), L5 A& x  _3 n$ m) R
  3.         self.time1 = time.time()
    + H& L" p2 U: J: v" c
  4.         self.time2 = time.time()
    $ V1 w, D" T9 v2 d; q
  5.         self.flag = False& a( g0 V$ T! X% X, M
  6.         self.port_chassis = serial.Serial(CHASSIS_SERIAL_PORT, 9600, timeout=1)4 ?- ^" f( ?- j4 Z9 j0 ^9 M& o
  7.         # print('port_chassis is :' + self.port_chassis.is_Open())2 S  h# @7 q. a7 ^
  8.         self.port_chassis.flushInput()
    5 i* Y; B% D6 \$ o* ]& ]7 j
  9.         self.port_chassis.flushOutput()</font>
复制代码
接下来就是发送数据,我们的购物机器人是通过树莓派做为整个的 “大脑”,是由树莓派里的python脚本给底盘发送指令,所以这个函数就是python让底盘移动distance个格子的函数,这个函数里面也是通过USART(UART)给底盘发送指令的,所用函数就是self.port_chassis.write((direction + str(distance)).encode())
: e9 B- e; {$ C2 u5 \
  1. <font face="微软雅黑" size="3"> def move_by_grid(self, direction, distance=''):9 {4 M+ B  _6 O( H7 N5 P& A$ e
  2.         # print('move by grid')4 [& w8 l: O% ]) R6 j+ R
  3.         self.port_chassis.write((direction + str(distance)).encode())
    " [  y5 r/ b) Y2 h2 {- q, {; ^
  4.         self.time1 = time.time()& y3 B) i$ s( r8 s+ y
  5.         print(direction + str(distance))- {* \$ }4 }0 i9 h. b
  6.         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
  1. <font face="微软雅黑" size="3">def wait_for_act_end_signal_chassis(self, ret=None, distance=0):
    . F6 L7 l* T8 f
  2.         print('waiting chassis...')
    1 N+ ?4 P7 ]" T2 N/ x
  3.         while True:% g2 f& e; Y: H, o
  4.             sig = self.port_chassis.readline().decode(). e0 d/ g5 s) ]
  5. " I* k3 j5 ?1 L4 x8 i
  6.             # print(self.time2 - self.time1)6 z0 J. M4 p6 z8 q
  7. % h; J4 j8 k! C  [
  8.             sig = sig[0:2]
    - b9 U6 T  _) U: p& M  b
  9.             print(sig)2 t2 D& \4 h$ u# I& }5 |
  10.             #
    9 X2 U! z* E! q. `( W+ |
  11.             if sig == 'HI':
    5 `3 [' ]$ r7 `( w. N8 G/ k) P
  12.                 self.time2 = time.time()
    / i( m6 g$ [  t' h8 F
  13.                 print(self.time2 - self.time1)/ V% ^5 p/ f4 g" R; M% s4 ~# r
  14.                 if self.time2 - self.time1 < 1.0 and self.flag == False and distance == 1:7 ]) S5 \" j  p( E/ i
  15.                     print('1 step deal error')% l1 ~$ ]8 a% @: T2 g9 I4 y
  16.                     self.flag = True
    ' |" n3 J/ o' n  z; N7 T
  17.                     if (ret == dir_up or ret == dir_back):
    & Q9 f( S9 W8 W/ R7 S& b& @" q4 C
  18.                         self.move_by_grid(ret, 1). O7 F6 r; c  D
  19.                     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
  1. <font face="微软雅黑" size="3">void MX_DMA_Init(void) ' S5 O3 U6 f/ j- }  I
  2. {/ w' u6 B2 s, p( b3 U

  3. ( `& S4 ~4 O1 U
  4.   /* DMA controller clock enable */) F, D; J0 P4 Q# |. r- t/ T
  5.   __HAL_RCC_DMA1_CLK_ENABLE();
    * @; T* l, F) [
  6.   __HAL_RCC_DMA2_CLK_ENABLE();/ q4 r9 I% m) Z6 S+ D

  7. " ~+ D+ ~0 `# Y( ^' f
  8.   /* DMA interrupt init */0 N; e2 F2 {/ W) X* ]
  9.   /* DMA1_Stream0_IRQn interrupt configuration */) l) y. Q( u: q9 S; O  o
  10.   HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
    8 R5 b+ |7 r. K$ D+ A! _
  11.   HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
    ; X% J$ I2 {; O9 k/ r" G
  12.   /* DMA1_Stream1_IRQn interrupt configuration */5 X. P) Y2 J* k4 ]  O& w3 U
  13.   HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);1 t. U  h" |, r
  14.   HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
    3 A4 X. y5 W. ?: _, ?; y# G
  15.   /* DMA1_Stream3_IRQn interrupt configuration */8 S9 |% [+ e( o% H. S# H
  16.   HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 0, 0);
    " M( L1 [% h  y( `- O
  17.   HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
    / T) @! O+ L$ B: ~2 P: J
  18.   /* DMA1_Stream6_IRQn interrupt configuration */( V3 G' g* f* ?# V) _1 V
  19.   HAL_NVIC_SetPriority(DMA1_Stream6_IRQn, 0, 0);
    3 R; h; q3 m+ h$ F: }
  20.   HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn);4 p  `8 ]9 I, z8 y" A6 f
  21.   /* DMA2_Stream1_IRQn interrupt configuration *// i/ Q9 q! g+ M: ^2 V
  22.   HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0, 0);% Q) s/ s' I- Q  Z  @* y
  23.   HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);7 W  `  h5 ^5 s+ f
  24.   /* DMA2_Stream6_IRQn interrupt configuration */
    , F0 {' n" B' i6 a
  25.   HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 0, 0);! x* a3 ]- X4 [0 a6 ]
  26.   HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);' e) ]7 }* P! Z' M

  27. 0 {9 H  x' M6 a& c
  28. }
    3 g& P+ l$ \' ]6 g% B3 ^
  29. </font>
复制代码
DMA使能完成之后就要进行USART(UART)的基本配置了,这里我设置的就是波特率9600(各个USART(UART)波特率初始化大同小异,因此在这里只放了usart6的初始化,其他类似,不做赘述)。  X4 b: a6 A, O! v! F
  1. <font face="微软雅黑" size="3">void MX_USART6_UART_Init(void)
    6 j0 ?6 W  T3 l+ @, s9 q
  2. {
    ) p; P* G+ N4 m4 P5 c3 Q9 l

  3. " ~4 E" A) Q% y, L
  4.   huart6.Instance = USART6;8 _) k4 g: J& Z- A5 H
  5.   huart6.Init.BaudRate = 9600;4 g, B  d0 Z/ E# @* h: m
  6.   huart6.Init.WordLength = UART_WORDLENGTH_8B;' @5 n. i1 ^- I4 d4 r' ^& _
  7.   huart6.Init.StopBits = UART_STOPBITS_1;
    0 X5 e* z, H0 G" @1 R
  8.   huart6.Init.Parity = UART_PARITY_NONE;3 E9 q" P% u6 n0 }4 I
  9.   huart6.Init.Mode = UART_MODE_TX_RX;
    4 }# F2 j7 d! q% T" \
  10.   huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    * p! y+ W( G- K- l8 W  @; D
  11.   huart6.Init.OverSampling = UART_OVERSAMPLING_16;8 ]* |7 W' I3 T. D2 i2 C) u
  12.   if (HAL_UART_Init(&huart6) != HAL_OK)* r& f3 Q% O' `" Y! k% S: d! O
  13.   {0 \- S! c! H3 ]% P; s2 t9 ^
  14.     Error_Handler();. d2 m, q8 p; \! T* |6 G( S% K
  15.   }
    9 L, X; G- w0 D! X( ~3 N# `0 ?

  16. 6 f, S; Q4 [% j2 ~2 L
  17. }</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) }
  1. <font face="微软雅黑" size="3">
    * f4 l! A' U* T
  2. void USR_UartInit(void)  O/ e/ [% |5 _) g. a& ~
  3. {  g2 o& @) N( Y' B  j8 V9 B7 F
  4.     test1++;; q9 \* [* w* G2 w# w% G% G7 ~
  5. ) s& z  v/ [8 b% R# Y
  6.     uart8RxLength = 0;   7 B4 ]9 E: i0 k2 X4 _  F
  7.     HAL_UART_Receive_DMA(&huart8, uart8Rx, buffer_size);
    . _% k3 o/ E3 S" F6 i! }3 Y9 }
  8.     uart7RxLength = 0;     g( s8 X& ?8 Z$ Z. Q
  9.     HAL_UART_Receive_DMA(&huart7, uart7Rx, buffer_size);
    5 D! E$ r) ]. |+ E
  10.     uart6RxLength = 0;   
    ( @# C4 p5 ^* g5 X5 _& r: J3 ?
  11.     HAL_UART_Receive_DMA(&huart6, uart6Rx, buffer_size);   
    0 W  l/ v% k* a1 Y4 ~1 F

  12. 7 w' X: n! ]) N- O1 {2 Y. h8 B
  13.     __HAL_UART_ENABLE_IT(&huart8, UART_IT_IDLE);     
    ! e7 c) {* u* l: N4 x
  14.     __HAL_UART_ENABLE_IT(&huart7, UART_IT_IDLE);   & m' u1 d* C9 v) p7 a/ J1 c! f
  15.     __HAL_UART_ENABLE_IT(&huart6, UART_IT_IDLE);   
    . r- V; ?2 n0 {* M) \  N
  16. }) G  S: r  r' F% l/ L' _$ |+ I' d
  17. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    0 |* _( }( |3 T# R
  18. {
    , s: b) h) e7 k: s

  19. 9 a% C& J) K/ y4 Y, J7 }
  20.     HAL_UART_Receive_DMA(&huart8, uart8Rx, buffer_size);
    3 t2 i6 x+ ]3 b4 Q/ e
  21.     HAL_UART_Receive_DMA(&huart7, uart7Rx, buffer_size);
      p9 E- U+ \4 j  w. j9 |) ^1 v
  22.     HAL_UART_Receive_DMA(&huart6, uart6Rx, buffer_size);7 h& K& s5 p8 G0 l' K1 z; P
  23.     __HAL_DMA_ENABLE(&hdma_uart8_rx);
    9 t3 B/ V: s$ ~! E- J
  24.     __HAL_DMA_ENABLE(&hdma_uart7_rx);5 }. B- t, w3 a9 m& i9 B: i2 H
  25.     __HAL_DMA_ENABLE(&hdma_usart6_rx);
    8 A( M" _- Y% V/ p
  26.     test2++;
    - L. b/ v7 J; G. ^8 F
  27. }, l; o6 p0 }4 N0 x. H- V2 L
  28. uint8_t RxLenHi, RxLenlo;  
    % l! h: B8 W( U( X% C4 v
  29. void HAL_UART_IdleCpltCallback(UART_HandleTypeDef *huart)8 J4 b( _. w, D
  30. {6 a6 o+ z, c( e7 x% e  u0 ~* a
  31.     __HAL_UART_CLEAR_IDLEFLAG(huart);
    1 B# u( [$ X9 X, q& d% w) @
  32. 2 n+ v' x% U5 J9 b3 U2 H& I3 X$ q/ `, P
  33.         if( huart == &huart8)3 E& V! ~* m  _5 m) [
  34.         {# @! l6 u+ T9 Z0 t: z5 {! ?
  35.             test3++;+ d7 s+ |( P! s: P( z1 E% Q/ Q
  36.             HAL_UART_Receive_DMA(&huart8, uart8Rx, buffer_size);  0 Q0 c$ @; v& [- z+ t1 |
  37. - w0 P+ p. g+ b" O
  38.             uart8RxLength = buffer_size-__HAL_DMA_GET_COUNTER(&hdma_uart8_rx);     
    / T7 e0 P, k8 `% q
  39.             if(uart8Rx[0]=='@'
    7 m  W- p$ E9 P& m+ _2 P+ w3 @
  40.             &&uart8Rx[1]=='c'
    / |7 M0 _1 Y: e1 z" r
  41.             &&uart8Rx[2]=='m'
    - f1 _3 J0 F: E9 C& d7 f' `3 t5 A
  42.             &&uart8Rx[3]=='d') 2 l* `/ ?' ^( G" c3 R1 g: `
  43.             {  X5 S& L. I5 L# \
  44.                 if(!SERDEB_CmdValid())) J6 r! }& ?* t- @2 q* d$ D
  45.                     SERDEB_PushCmd(uart8Rx, uart8RxLength);
    8 R7 q9 j0 a& [  E4 O1 y
  46.             }- q6 [/ `* E6 p
  47.             __HAL_DMA_DISABLE(&hdma_uart8_rx);
    $ x! {$ P4 ^3 I  M# p; ?
  48.             HAL_GPIO_TogglePin(GPIOG,GPIO_PIN_8);    ; T( B; I0 g1 q  n% A9 r/ O
  49.         }
    & r0 r& T. f) ]0 V) B) C( M

  50. % b3 @7 @( l- J4 d
  51.           if( huart == &huart7)0 R6 d0 Q2 K3 d  M1 Q( P3 F: Q
  52.         {        ' f/ l6 B" J6 y
  53.             __HAL_DMA_DISABLE(&hdma_uart7_rx);  
    , X% M2 u3 g  t  S9 C, M( O& |! x6 |
  54.             HAL_UART_Receive_DMA(&huart7, uart7Rx, buffer_size); / D  G+ Z3 {2 {. l2 i% S# f( l
  55.             __HAL_DMA_DISABLE(&hdma_uart7_rx);
    $ u! b) s/ I* B
  56.         }
    4 z  V0 v9 G5 k8 W; P

  57. 0 H4 b' u1 w8 v# V9 }4 u2 E
  58.         if( huart == &huart6)
    8 A# g; |  U6 C5 c5 `! J
  59.         {
    2 f3 s- T: L! l1 X2 c- p
  60.             __HAL_DMA_DISABLE(&hdma_usart6_rx);3 Y- G: [5 @/ ?1 d$ _! F: B
  61.             HAL_UART_Receive_DMA(&huart6, uart6Rx, buffer_size); 2 H- @3 A& ~& A9 S8 Y: b
  62.             __HAL_DMA_DISABLE(&hdma_usart6_rx);
    8 D* Y3 e+ \2 y
  63.         }' ^4 n% ~1 X6 {( Y9 `- N6 N
  64. 1 [# B! q* W6 F, z
  65. }</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
收藏 评论0 发布时间:2021-7-26 11:27

举报

0个回答

所属标签

相似技术帖

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版