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

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

[复制链接]
STMCU小助手 发布时间:2021-7-26 11:27
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
  1. <font face="微软雅黑" size="3">def __init__(self):) U* N! w/ {$ R# k* L( Y2 X3 R2 ~
  2.         print("move init finish")
    ' _. ~! G/ L/ `7 G1 k4 _  s. o
  3.         self.time1 = time.time()
    . n& K0 T0 f& G. {( F& D0 {
  4.         self.time2 = time.time()0 m  y# a9 W2 ]( K2 E. ]2 s
  5.         self.flag = False
    , }$ ^5 M& S# {8 Z6 r9 g" h
  6.         self.port_chassis = serial.Serial(CHASSIS_SERIAL_PORT, 9600, timeout=1)
    ) L" Z) G6 A' Z) F
  7.         # print('port_chassis is :' + self.port_chassis.is_Open())! k* v0 @3 v) q
  8.         self.port_chassis.flushInput()' e9 j- m0 q0 a! }; m" b: T7 ?
  9.         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
  1. <font face="微软雅黑" size="3"> def move_by_grid(self, direction, distance=''):
    9 M$ L# F6 |6 n8 n( y3 f5 t
  2.         # print('move by grid')
    6 H+ P8 c4 E, N4 m( N
  3.         self.port_chassis.write((direction + str(distance)).encode())0 n7 ^8 z$ D8 L, |; `
  4.         self.time1 = time.time()8 I$ Z; t6 c' @2 E8 J& ^- S
  5.         print(direction + str(distance))
    + j, o, O+ J6 O& U! I& V
  6.         self.wait_for_act_end_signal_chassis(direction, distance)</font>
复制代码
最后是接收数据,既然树莓派要控制底盘,树莓派自然也要接收到底盘回传的数据,这里用到的USART(UART)接收数据函数是self.port_chassis.readline().decode(),sig就是树莓派接收到的USART(UART)数据,用户就可以对其做处理啦。" \8 s( S# J% `
  1. <font face="微软雅黑" size="3">def wait_for_act_end_signal_chassis(self, ret=None, distance=0):8 R# j9 }5 F5 ~% t3 I8 W- _
  2.         print('waiting chassis...')& [. X3 R1 {' }/ t
  3.         while True:
    & J0 i1 x, ~( W5 t$ ]) K6 `% F
  4.             sig = self.port_chassis.readline().decode()
    6 T% R% F0 m. _
  5. 9 l  v. [' {0 q4 K3 D
  6.             # print(self.time2 - self.time1)6 b% I8 J: `  V2 z9 B
  7. . F1 {, M0 K0 |4 B  j& n3 o
  8.             sig = sig[0:2]1 w! k: L  A) H* b3 H# I) W- r" b, q
  9.             print(sig)' H- N# t/ n2 g5 k; y5 F: U# n8 |
  10.             #( @4 S5 R7 @2 e% [) }
  11.             if sig == 'HI':
    * ?" r2 a; }1 P7 k4 I8 j
  12.                 self.time2 = time.time()
    + z! n( n' T7 S, ?0 r
  13.                 print(self.time2 - self.time1)% z1 H( j/ b1 A' I5 r5 c: v/ n  i1 z/ x
  14.                 if self.time2 - self.time1 < 1.0 and self.flag == False and distance == 1:
    0 P# J5 J9 Z- P
  15.                     print('1 step deal error')
    : D" n! l( `  Z* @
  16.                     self.flag = True
    , H6 u! _- u3 T5 E0 g+ x% f2 _
  17.                     if (ret == dir_up or ret == dir_back):  g! x5 a5 ?; G$ E
  18.                         self.move_by_grid(ret, 1), g6 f- A$ V  {( X( Z2 F% k4 D
  19.                     else:</font>
复制代码

( H$ w9 A/ V& a2 H; ]  d, s$ R/ j
9 @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
  1. <font face="微软雅黑" size="3">void MX_DMA_Init(void) & u, u' R9 L4 P" O9 l: d, r
  2. {
    : b  ~' ~9 d+ s7 k, Q: e) c

  3. 6 o' K% |! m! k- o; P# y
  4.   /* DMA controller clock enable */% g/ R7 V- A( s8 m3 K5 u2 Q
  5.   __HAL_RCC_DMA1_CLK_ENABLE();
    % R! D" ~: Z" `) |6 v9 ]& y- J% A- P
  6.   __HAL_RCC_DMA2_CLK_ENABLE();
    3 N: L4 ~8 M" h# {; v5 z, r+ {; ]
  7. $ d% X! b3 q7 L9 v. P" H
  8.   /* DMA interrupt init */% Y/ y+ w* O# ]! e
  9.   /* DMA1_Stream0_IRQn interrupt configuration */9 l8 s( O" `5 ~- U. R
  10.   HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);  y( `" T# w9 j- R* U; T
  11.   HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);' B  Z; h* C8 t# f
  12.   /* DMA1_Stream1_IRQn interrupt configuration */6 s, J. E- ]: ^- c1 ~7 V
  13.   HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);& l+ ]0 @! B6 P  P! F6 G8 p
  14.   HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);% c) E5 P1 I# x' h
  15.   /* DMA1_Stream3_IRQn interrupt configuration */' X3 N/ I- i7 K5 j$ C
  16.   HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 0, 0);$ m; S; j- a9 K' }7 r% i( l8 ~" Y8 W
  17.   HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);$ k/ O! K" j+ v
  18.   /* DMA1_Stream6_IRQn interrupt configuration */: {( _  w$ v/ H- G* j9 o- M
  19.   HAL_NVIC_SetPriority(DMA1_Stream6_IRQn, 0, 0);& |8 O0 h9 d7 L) x3 e
  20.   HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn);
    : h3 ]" D7 @$ F( K; ^
  21.   /* DMA2_Stream1_IRQn interrupt configuration */
    # c2 P, Y+ d# X5 e& j, i# x
  22.   HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0, 0);8 ]6 e# i, H2 }' Q: [7 l1 N# W
  23.   HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);" ^  Q8 m- d) y
  24.   /* DMA2_Stream6_IRQn interrupt configuration */
    / Z$ {7 {8 Z7 q& X5 ^6 ^0 X- |
  25.   HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 0, 0);/ K) _; N# e4 r( P3 D
  26.   HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
    0 [( a, ]0 i% z3 |/ }

  27. 6 A0 ]( y9 r0 P- Z8 A
  28. }1 s5 S. `* ]3 K5 M+ I
  29. </font>
复制代码
DMA使能完成之后就要进行USART(UART)的基本配置了,这里我设置的就是波特率9600(各个USART(UART)波特率初始化大同小异,因此在这里只放了usart6的初始化,其他类似,不做赘述)。9 d$ P# q4 U* {- Z3 T
  1. <font face="微软雅黑" size="3">void MX_USART6_UART_Init(void)# [7 r: k( W3 ?( a  x  `
  2. {
    ! M9 r  X4 I8 D4 ]6 l5 ~! z, i
  3. . Z# q0 D, e( Z4 c; n& r* u, f8 j3 P
  4.   huart6.Instance = USART6;
    8 k; B2 x! U! p* P& H  P
  5.   huart6.Init.BaudRate = 9600;
      w- A8 u% ^+ Q! e; k' l' {0 a
  6.   huart6.Init.WordLength = UART_WORDLENGTH_8B;
    # @2 R* R  {8 |
  7.   huart6.Init.StopBits = UART_STOPBITS_1;
    0 a; V( }! f& z1 a: p% |9 T* T
  8.   huart6.Init.Parity = UART_PARITY_NONE;
    , m- D* v2 l% D' H! a, L
  9.   huart6.Init.Mode = UART_MODE_TX_RX;7 D6 Z& O2 s5 t8 N' o. l
  10.   huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    : C) E1 q7 ?8 g/ T$ t, M
  11.   huart6.Init.OverSampling = UART_OVERSAMPLING_16;% Q" L( F4 ?1 t* L0 [% s& C
  12.   if (HAL_UART_Init(&huart6) != HAL_OK)
    ( ]+ O% R, `6 j; D% F6 m7 O* {
  13.   {
    ' Y5 F/ u. i2 |" f0 c/ l) c; ^
  14.     Error_Handler();1 {: E5 B4 H  ?' k. [
  15.   }
    7 F" I2 }1 \1 j, o7 l- F! M

  16. 5 S1 \: `5 h) [0 X& `
  17. }</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
  1. <font face="微软雅黑" size="3">" q) N! N" {5 F  X9 `$ ?
  2. void USR_UartInit(void)9 |+ h( }$ B; @  j9 t
  3. {
    * W0 {/ d4 x  r  F% z% |
  4.     test1++;
    0 Z: ]* C* C1 T, A- N
  5. % p( t9 [, o) d% M8 j; ?4 l1 Z
  6.     uart8RxLength = 0;   
    9 a5 S% A, z" g! w  v' a
  7.     HAL_UART_Receive_DMA(&huart8, uart8Rx, buffer_size);1 t; ~; p" k" w- ]0 P- D0 U) z3 i9 f0 l
  8.     uart7RxLength = 0;   7 l3 C- w; M' E1 W3 s
  9.     HAL_UART_Receive_DMA(&huart7, uart7Rx, buffer_size);
    & U. a$ Q" {1 }* w
  10.     uart6RxLength = 0;   - y3 J+ B8 F) J. a! z
  11.     HAL_UART_Receive_DMA(&huart6, uart6Rx, buffer_size);   
    ; u' S* R1 q6 \# F/ ~
  12. & C0 r, Y  R! l! m: t; ~
  13.     __HAL_UART_ENABLE_IT(&huart8, UART_IT_IDLE);     
    - Y6 j, q) l4 Z+ G( Y1 u
  14.     __HAL_UART_ENABLE_IT(&huart7, UART_IT_IDLE);     J- c$ _! O* ^& ]; I
  15.     __HAL_UART_ENABLE_IT(&huart6, UART_IT_IDLE);   " D  k# }. D, h# ~: L- e
  16. }" r$ p' \% |8 n6 j: z
  17. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    1 X7 h# J. Z! t
  18. {/ a4 H4 d& \7 s
  19. ) A6 R" o3 Y2 f2 m* ?% V4 e
  20.     HAL_UART_Receive_DMA(&huart8, uart8Rx, buffer_size);
    , p$ w* u: h8 `5 K! M6 |
  21.     HAL_UART_Receive_DMA(&huart7, uart7Rx, buffer_size);
    3 t0 s% z+ G3 A/ h) L0 W/ I% T( m
  22.     HAL_UART_Receive_DMA(&huart6, uart6Rx, buffer_size);. s4 @9 k" e( |2 {
  23.     __HAL_DMA_ENABLE(&hdma_uart8_rx); " i3 _7 H9 \% y- ]
  24.     __HAL_DMA_ENABLE(&hdma_uart7_rx);5 h0 a  g1 P+ p, K+ t! d
  25.     __HAL_DMA_ENABLE(&hdma_usart6_rx);  o! J5 i* s/ y# Y% B% o
  26.     test2++;  E: \( |) ?& g7 f
  27. }- }$ g( U+ G& R% l. ]# [
  28. uint8_t RxLenHi, RxLenlo;  
    9 E% u' ]/ r$ P  N# s
  29. void HAL_UART_IdleCpltCallback(UART_HandleTypeDef *huart)! x+ q5 y' D/ c1 w9 Q
  30. {  q1 c: K) n9 x8 s, b
  31.     __HAL_UART_CLEAR_IDLEFLAG(huart);" p) x7 ?, e6 P9 K
  32. / Y* v) Z, ~6 u5 {) ^' k) r
  33.         if( huart == &huart8)
    3 B$ D0 N* t8 w, y
  34.         {3 K* f% j& t, X# [& D$ [7 C7 Y
  35.             test3++;/ i( C7 [4 d+ m) G& V. F
  36.             HAL_UART_Receive_DMA(&huart8, uart8Rx, buffer_size);  
    7 A* @. \7 J6 E! _; E8 i' c

  37. 5 k8 F2 a/ I- E
  38.             uart8RxLength = buffer_size-__HAL_DMA_GET_COUNTER(&hdma_uart8_rx);     # R- F; U  k6 }, |
  39.             if(uart8Rx[0]=='@'7 Q2 K) M& f1 D( F5 ?
  40.             &&uart8Rx[1]=='c'
    0 J2 J, J: Y9 f7 `
  41.             &&uart8Rx[2]=='m'
    3 ^0 ~2 d4 O' o4 k
  42.             &&uart8Rx[3]=='d')
    $ a* e4 l: y, {  v$ _" r
  43.             {# \9 ^5 m1 o& \( t
  44.                 if(!SERDEB_CmdValid())
    7 H6 I) Y' I0 N4 q5 a+ r
  45.                     SERDEB_PushCmd(uart8Rx, uart8RxLength);
    ) B3 k2 q0 x6 y( V( F) A- n
  46.             }
    4 a: l+ A9 H3 J
  47.             __HAL_DMA_DISABLE(&hdma_uart8_rx);
    & _% c0 e4 V$ k8 T0 T  U
  48.             HAL_GPIO_TogglePin(GPIOG,GPIO_PIN_8);   
    ! Q/ f) S* T2 k6 H( C( l
  49.         }) b+ m: }3 R$ c$ R0 j' D
  50. / f. n! c9 Z1 V- R
  51.           if( huart == &huart7)6 o$ N4 u$ c. b" }! M" e
  52.         {        , t6 d9 S% L% m4 D, j3 J
  53.             __HAL_DMA_DISABLE(&hdma_uart7_rx);  6 M& w. a# m- k. [& L# b5 K$ M
  54.             HAL_UART_Receive_DMA(&huart7, uart7Rx, buffer_size);
    3 l0 @6 A9 e0 G0 N! ~8 p
  55.             __HAL_DMA_DISABLE(&hdma_uart7_rx);$ O0 V1 Q" s$ h) s; U& B7 f7 }
  56.         }
    ' ?0 i3 m5 y, s) u$ ^3 Z+ T5 A
  57. % W, W, n' r2 _8 J. f' {" r
  58.         if( huart == &huart6)" J" B6 \, S5 Z) T8 l3 I/ R( o" o3 d. H
  59.         {# S: U. V1 O& y* B# w
  60.             __HAL_DMA_DISABLE(&hdma_usart6_rx);
    , b0 _& C: Y0 L+ G/ Z/ E# h" _8 n2 j/ l$ \
  61.             HAL_UART_Receive_DMA(&huart6, uart6Rx, buffer_size);
    1 \( Q9 L2 D; N3 h7 Z
  62.             __HAL_DMA_DISABLE(&hdma_usart6_rx);
    0 J8 h3 P5 s" ^% c% i3 `- h$ g7 |* ]
  63.         }/ c. H5 y% T0 e6 d* \, c

  64. " b/ y% C0 x2 v2 j8 d3 ?" u9 c8 w
  65. }</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
赞 收藏 评论0 发布时间:2021-7-26 11:27

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版