前言: 今天我们学习STM32CubeMX串口的操作,以及HAL库串口的配置,我们会详细的讲解各个模块的使用和具体功能,并且基于HAL库实现Printf函数功能重定向,UART中断接收,本系列教程将HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用
) b( v1 d: T' c2 ~8 u所用工具: 1、芯片: STM32F407ZET6 2、STM32CubeMx软件 3、IDE: MDK-Keil软件 4、STM32F1xx/STM32F4xxHAL库 5、串口: 使用USART1 PA9,PA10 知识概括: 通过本篇博客您将学到: STM32CubeMX创建串口例程 HAL库UATR函数库 重定义printf函数 HAL库,UART中断接收 HAL库UATR接收与发送例程 工程创建' w U6 B- ~+ u* J( I
1设置RCC - 设置高速外部时钟HSE 选择外部时钟源
2 @8 u1 X0 h: j+ t( U8 k: S
2设置串口 - 1点击USATR1
- 2设置MODE为异步通信(Asynchronous)
- 3基础参数:波特率为115200 Bits/s。传输数据长度为8 Bit。奇偶检验无,停止位1 接收和发送都使能
- 4GPIO引脚设置 USART1_RX/USART_TX
- 5 NVIC Settings 一栏使能接收中断
: Q3 k. `# c% F
3设置时钟 我的是 外部晶振为8MHz - 1选择外部时钟HSE 8MHz
- 2PLL锁相环倍频72倍
- 3系统时钟来源选择为PLL
- 4设置APB1分频器为 /2
* r! C- F% f9 z1 _0 N& H8 ? B0 j( S/ v+ C5 x! P: |
4项目文件设置 - 1 设置项目名称
- 2 设置存储路径
- 3 选择所用IDE
. D5 ^+ L( o ?5 }9 \1 w+ K0 c* t: V$ z
5创建工程文件 然后点击GENERATE CODE 创建工程 配置下载工具新建的工程所有配置都是默认的 我们需要自行选择下载模式,勾选上下载后复位运行 HAL库UART函数库介绍: y7 N! A: e8 {; S, \
UART结构体定义 UART_HandleTypeDef huart1;$ E" c5 d; {8 f# r; F
UART的名称定义,这个结构体中存放了UART所有用到的功能,后面的别名就是我们所用的uart串口的别名,默认为huart1 可以自行修改 1、串口发送/接收函数 - HAL_UART_Transmit();串口发送数据,使用超时管理机制
- HAL_UART_Receive();串口接收数据,使用超时管理机制
- HAL_UART_Transmit_IT();串口中断模式发送
- HAL_UART_Receive_IT();串口中断模式接收
- HAL_UART_Transmit_DMA();串口DMA模式发送
- HAL_UART_Transmit_DMA();串口DMA模式接收5 c" H1 u+ @4 Y# P0 L" s! d. @
这几个函数的参数基本都是一样的,我们挑两个讲解一下 串口发送数据: HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)3 Z# c, @3 \" w4 e* }2 x
功能:串口发送指定长度的数据。如果超时没发送完成,则不再发送,返回超时标志(HAL_TIMEOUT)。 参数: - UART_HandleTypeDef *huart UATR的别名 如 : UART_HandleTypeDef huart1; 别名就是huart1
- *pData 需要发送的数据
- Size 发送的字节数
- Timeout 最大发送时间,发送数据超过该时间退出发送5 B, I& o \. m+ _
举例: HAL_UART_Transmit(&huart1, (uint8_t *)ZZX, 3, 0xffff); //串口发送三个字节数据,最大传输时间0xffff
) d5 w' W5 x! V' P中断接收数据: HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
, G; X* C) F) @功能:串口中断接收,以中断方式接收指定长度数据。
) S* K. {5 F m大致过程是,设置数据存放位置,接收数据长度,然后使能串口接收中断。接收到数据时,会触发串口中断。8 t; V$ E" _& w& m8 M* D' A- E3 A
再然后,串口中断函数处理,直到接收到指定长度数据,而后关闭中断,进入中断接收回调函数,不再触发接收中断。(只触发一次中断) 参数: - UART_HandleTypeDef *huart UATR的别名 如 : UART_HandleTypeDef huart1; 别名就是huart1
- *pData 接收到的数据存放地址
- Size 接收的字节数
$ s5 }! P9 I0 [4 n: C+ Z2 |( o ] 举例: HAL_UART_Receive_IT(&huart1,(uint8_t *)&value,1); //中断接收一个字符,存储到value中
# k8 _/ {: r, B+ [2、串口中断函数 7 \- [" D+ }; [) n0 r! z( D
- HAL_UART_IRQHandler(UART_HandleTypeDef *huart); //串口中断处理函数
- HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart); //串口发送中断回调函数
- HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart); //串口发送一半中断回调函数(用的较少)
- HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); //串口接收中断回调函数
- HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);//串口接收一半回调函数(用的较少)
- HAL_UART_ErrorCallback();串口接收错误函数/ v# m6 }, ], i7 Z' m1 }5 o
串口接收中断回调函数: HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
$ w4 [' N+ p; y7 |* s; S功能:HAL库的中断进行完之后,并不会直接退出,而是会进入中断回调函数中,用户可以在其中设置代码, 串口中断接收完成之后,会进入该函数,该函数为空函数,用户需自行修改, 参数: - UART_HandleTypeDef *huart UATR的别名 如 : UART_HandleTypeDef huart1; 别名就是huart13 c: V9 L8 [3 w: M) G! w
举例: HAL_UART_RxCpltCallback(&huart1){ //用户设定的代码 }
8 _ S4 O0 a t' G7 j1 N$ \串口中断处理函数 HAL_UART_IRQHandler(UART_HandleTypeDef *huart);
& q8 X2 @, j& T7 B% V& {0 t- c功能:对接收到的数据进行判断和处理 判断是发送中断还是接收中断,然后进行数据的发送和接收,在中断服务函数中使用
' C/ o) ^; b$ V! a+ x4 T2 L如果接收数据,则会进行接收中断处理函数 - 9 T& P6 t2 a( l |) e; k( z
3 ?, ^# p0 M) z; Q4 l5 a5 D
/* UART in mode Receiver ---------------------------------------------------*/5 o6 p; Y7 \* W# E- ~4 r
' Y* Y( n' s; E+ F. u) W
& h5 U5 l/ H8 q1 N b- _( X, f. j/ N5 v
if((tmp_flag != RESET) && (tmp_it_source != RESET))7 ?6 C, |/ w; k! m
! b) T* o% D; E5 c2 N- 2 ?6 i! @+ N% T o$ q5 Y
, D. |/ G, F$ d+ [$ d
{( S u3 N: Q# H: @9 I6 o4 |
+ T/ j. K! }5 W- G/ L+ p( s
& p9 j Y3 w* J+ L" z' o; I3 e" e# k. h7 A, n2 U0 Z+ k
UART_Receive_IT(huart);
1 s. q' U8 `9 W* y5 S, H( z1 h+ w* y- m
`3 b. D2 v8 Y$ s5 V. ?% S
) c& |" v* s7 J! b}
g. d5 Y# e2 j3 R D
9 y6 ~- z" E/ @: `( p$ _1 }7 F& p% }0 x. ?3 q2 T0 X. ^$ P' s
4 ^! `' g% g% o+ ^# e( z如果发送数据,则会进行发送中断处理函数 - " t" L1 Y. m$ y. J
; O/ L* m4 W+ ^$ m/ f- p' g8 A8 I
/* UART in mode Transmitter ------------------------------------------------*/6 ^7 a. k4 S8 T4 V9 w& C& l
9 p# P8 A% X( q
- 1 z+ w8 _) R( C1 }, j* y) i7 @$ z
, y- m" \: E( G, o
if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
9 e, }2 w! z" m* Q. d! z
9 J" j6 u7 z" S6 k H - , v! I3 c2 t0 _& ]
& k7 P# ]& \- E$ b! z/ E{
% C! K2 ~. z% k# `, Z% M: D$ c/ k4 k' V
0 D) J) }8 U# a% H; V$ p h/ y# m! s0 s3 x; G7 A" G' a
UART_Transmit_IT(huart);/ Q& b2 @9 E( p E9 X' B
3 o* e& w, ]* k6 v+ S* _
- ' f: ]/ i1 z7 I
2 }+ g, N3 s8 @$ T0 qreturn;0 L# }' a: g' ~" @# a6 ]" g
4 D4 f2 P& `# D z' y9 U6 m
- & O, E) s; r" @5 c6 O" E
, O$ q8 Z! c7 i9 j+ \# B
}/ g, H5 K# v7 C
0 b# w5 g8 r* t' V9 D$ i a
( [: `" O& X2 ]; X6 G
( G/ p8 n9 p2 s+ s: @/ L# ~! v, e3串口查询函数 HAL_UART_GetState(); 判断UART的接收是否结束,或者发送数据是否忙碌 举例: while(HAL_UART_GetState(&huart4) == HAL_UART_STATE_BUSY_TX) //检测UART发送结束" z# J2 {6 i `" J- G0 q6 g
. j G) V2 w. w% q# C( BUSART接收与发送4 d7 Y; H; s. E0 h5 a
重新定义printf函数- 在 stm32f4xx_hal.c中包含#include <stdio.h>
1 M6 o# n/ n! N+ t$ N
" S5 n0 t6 V; q+ T4 E
; |6 M! Y7 M/ ^+ P9 l3 u#include"stm32f4xx_hal.h"
2 Q% a. |) D- Y! ]6 K6 q" f2 h. `! E0 f
- " L! G5 k8 i% ~( b) z& b H2 [
% d0 |5 z, F# F#include<stdio.h>) a% H4 e5 f) z) P' o
. Q3 _- V6 e/ e2 U2 r
$ M# |+ N% D) ~! u4 L, \( j, @( \/ c: Q
extern UART_HandleTypeDef huart1; //声明串口
. V8 I' k0 k; \' z
# Q' s3 h& \/ T- r. U
# U9 W" j( G. I5 U& B, k- _; k2 y
/ w" v% S+ y3 j. p# e& L' v- 在 stm32f4xx_hal.c 中重写fget和fput函数
- /**8 {- [3 g* w4 V1 {: l8 h
在main.c中添加
8 k) I) x3 i- f8 Y% |& n% j
8 P- W( J+ P( f1 t) t4 I/ K; i# P, E# G6 {8 r5 o: b
#define RXBUFFERSIZE 256
0 v& z: y( ^% f( A6 B" `7 W. Z' x3 F' |. ^
3 E- g! l% |6 C' s4 N6 X0 D
" U) K& I. C a$ e) Schar RxBuffer[RXBUFFERSIZE];
( e- R' s7 G+ a& S# {
) n0 e* [! g [" b4 H# u* |
" i+ k) m+ ^$ `
' ^3 s, V9 W! F- 6 a; [# i" H# k' ]. m# h
, b" J0 \7 R3 {2 F! f _9 E
6 d) [8 \ J$ H
C1 b8 |- ?% j3 l4 a# p
9 a. O- n! z0 e, ]( X+ ?, |) ?
8 U% Q4 @+ `& lwhile (1)
9 B9 x1 p/ A6 W# t% A3 Y* W* [, Z/ a% R# `
- 9 M' Z7 G) e& e! k
, g% z& m; B& T5 p" U: t7 O
{ T# @8 J7 P$ y f
7 K# E. ?$ p/ i# p - ! x% O7 W& l! z& r
3 N+ A/ W( r4 g' c; [/* USER CODE END WHILE */5 H3 b7 j0 ^8 B& l+ A
5 g( w- F# W4 E/ F* S$ {4 E ^$ W
+ P: Z7 Z* T% i, |
' Z9 f" W# v' d6 W: k6 |! ]printf("Z小旋测试\n");
/ v! M* t# z/ C B. C' {( ~7 Z e9 V
' u& g& C' Z4 ^- Z5 D
& [; A2 i, a) r) [% p5 }
7 q; \) s7 c. }, i( O" zHAL_Delay(1000);
5 g3 \4 D1 ~' P0 n3 o
; j2 [! G0 j' z. }9 s( `% n
' E% t3 s" Z/ B7 l0 Y
^- K' y/ ]7 x3 i/* USER CODE BEGIN 3 */1 \0 J, T C6 v8 r4 _0 r$ x
+ ?- B% H3 z: C( x7 b/ y
- # e, _5 H; u: J% M
$ j0 [. y; Z- t4 U7 C2 _}+ K/ X* |0 K9 |! Y, q
- O$ Q) Q4 V- D) q1 r& q
2 h6 H& n# u5 G8 s* J: \* Q2 ^0 j ! r& R) v2 D: H
之后便可以使用Printf函数和Scanf,getchar函数 UART接收中断因为中断接收函数只能触发一次接收中断,所以我们需要在中断回调函数中再调用一次中断接收函数 具体流程:1、初始化串口 2、在main中第一次调用接收中断函数 3、进入接收中断,接收完数据 进入中断回调函数 4、修改HAL_UART_RxCpltCallback中断回调函数,处理接收的数据, 5 回调函数中要调用一次HAL_UART_Receive_IT函数,使得程序可以重新触发接收中断 函数流程图: HAL_UART_Receive_IT(中断接收函数) -> USART2_IRQHandler(void)(中断服务函数) -> HAL_UART_IRQHandler(UART_HandleTypeDef *huart)(中断处理函数) -> UART_Receive_IT(UART_HandleTypeDef *huart) (接收函数) -> HAL_UART_RxCpltCallback(huart);(中断回调函数) HAL_UART_RxCpltCallback函数就是用户要重写在main.c里的回调函数。 代码实现: 并在main.c中添加下列定义: - 3 Z3 D6 z' W: I* v; o/ G
+ O4 f+ I4 {; z#include<string.h>
/ E6 s$ L2 _. m
. P7 J! a7 h. s) l/ Q
$ A( P, h/ C( \/ w: ]' f& L" F, \
$ U# E% W2 y7 s
4 O: r% s% g4 ~
% u# j: G) v& ~) y0 A( r) Y! o- 6 Y( R0 w" l7 g Y
/ v8 j1 d d% n6 D+ D/ H2 i
#define RXBUFFERSIZE 256 //最大接收字节数
. E+ ~' _8 |+ F- ~3 ~ r2 e' o) S4 V0 n6 e
- 6 c3 P0 h7 X2 @0 F4 m% E' A
: P9 f: `3 M/ U- C# v0 w
char RxBuffer[RXBUFFERSIZE]; //接收数据& w! b7 L" U k$ R* Z( L: v: p
8 M0 K( e$ L: [; |" K
- ( q# ?$ l4 p" A2 k5 Y% G7 m
K- V7 Q. s; |) v! o- q6 g2 v/ N
uint8_t aRxBuffer; //接收中断缓冲& v6 U6 W8 P4 c
+ `: ?, r/ v8 }( X
" ^# i# P- I6 v9 k5 w9 B% ]" W$ m2 x) e/ O/ _
uint8_t Uart1_Rx_Cnt = 0; //接收缓冲计数
# X8 F0 W* B& U0 S0 `6 [9 Z- W
0 ~+ d; ~5 \5 _/ |' k: l- S6 g- T- c
0 E4 ~1 E2 n- e, H7 ~& m5 `0 e在main()主函数中,调用一次接收中断函数 - 9 x9 h5 n; ]( [/ f
' _0 l" X4 j, W1 s$ K
/* USER CODE BEGIN 2 */( S8 @3 w, N. h. D
$ W) c( ]4 A' T/ K7 N Q2 L - : ^6 M, g4 \2 ] T, E5 u+ W
5 r' F* _" I8 B8 g- ?7 {0 t _- @; Y
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1); M5 x. p6 u6 W8 S3 l* V
' |6 a0 D6 w! S( t& V8 O: a
4 o. f* I& D7 C+ b
+ X7 |' t# n6 M/ ]/* USER CODE END 2 */5 N2 I$ H" B g- h% t" s" B0 Y
6 ~% K! {! {, }
6 u# j; j; n* N2 a# B1 w# ?
* v4 _; k5 c+ \ _* V% S; z在main.c下方添加中断回调函数
2 X% _' Z0 x9 S8 o# L# u0 c
' e2 w1 l( E4 |/* USER CODE BEGIN 4 */
: l7 P) _' d! z! \& A
t; K9 r3 [/ Z: X& m T6 x1 v
: B: S, S& p( P' [* `
! e; M% u! [1 J2 l# N. S& D* R! E2 \
# v3 J" F+ h' [& H! E; V
6 P0 E( Z2 p5 d& y6 p9 @3 p) T$ R+ b1 `, m
voidHAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)! J/ t6 b7 k3 h6 O2 O# Y& @7 V
& p% R' \1 {* F+ F6 j
; p8 d) u4 y4 ]+ k2 p6 x, l) P5 [9 n$ Z9 y+ x6 T: L- m
{
# q8 L M6 n L' q) b8 O6 }/ U, O& j5 J$ n
- " }/ Q% y2 d% o) N9 v* _8 A
8 y4 v+ a( k1 W, Z* Q
/* Prevent unused argument(s) compilation warning */$ p! ^+ ^+ j% } x0 ?! s9 z5 u
- p d$ G4 I3 B% b I0 u - & Y6 h8 w9 @& y$ _* q" r$ D( R
" B+ P/ @0 m/ {8 t
UNUSED(huart);
2 A: ]6 \# g4 q' M# i. X
1 b( ?% _) V6 ^
, \/ z. G; b% Y2 _7 e7 a% S9 I3 u+ C9 H0 f3 |
/* NOTE: This function Should not be modified, when the callback is needed,4 H3 ?4 h1 G2 v6 `. @7 w, y
' x( ]* b6 ]+ w
- ) V1 t2 r9 h1 ]$ G6 q6 c
- H! _& `+ ?2 }: r+ P; C. G
the HAL_UART_TxCpltCallback could be implemented in the user file; D, z" `8 `; w, y, {5 |5 w" m4 }) M2 a0 y
0 [+ a4 t5 d3 t7 g3 C
, ^- s9 y+ ~4 x9 w* b }! }
- M5 P0 q" X4 i2 ]; X*/ g4 g2 A, p; h# I( n( O
# S( H! y8 C9 [6 g
0 g/ ?9 n& R( u8 n, {
: u" ~. ~& @) V1 L( y X I; n3 ?
) X2 @' U& P( ~+ _- A) ~( C6 f+ A0 L' `* g& j
- ; C) e! Q y Q8 X2 C# Y; i2 ]2 g
_2 y5 A3 o. m/ q" l. `if(Uart1_Rx_Cnt >= 255) //溢出判断9 k# O, \/ E- `+ E/ S& W2 [9 X
/ ?) o8 _6 r) V# ]7 N4 C - ! `7 j5 s% Z& c( T! b* `
" ^6 E. A! h- ]+ v" @{4 n& S+ R) V, K
0 S; j% [! p) }1 _
# d3 a) X1 x+ Z" A2 c. ]2 z" J B
Uart1_Rx_Cnt = 0;3 w- v& q& T: H8 G e* b2 `) r
4 @- E2 x) |: d) ], z& g# m
5 Y+ T3 P0 j6 `- c1 V7 z3 p' r: ]' {8 F
memset(RxBuffer,0x00,sizeof(RxBuffer));" R1 J, _) T9 v5 c
$ d- A0 ]- J$ }& _: E# N0 [$ z- 4 S& O9 D, W9 }9 T( p4 L
: y( h: }" n% w
HAL_UART_Transmit(&huart1, (uint8_t *)"数据溢出", 10,0xFFFF);
5 _5 X9 x7 K* o0 u2 ^8 h0 Z( R. R5 z- d0 H3 X
3 l8 V. Y; \ }. ?+ x+ I
2 S* f4 [0 i _- r, `
# N H0 D- D6 ], \
5 F- z9 {+ O5 L" h- " A: D8 S9 M, N
) Q& c" T& |% |}
* @1 L0 ?* F0 G5 g) B9 G$ ~! W3 U8 i" a4 a
" z' g& ^6 ~' u5 q! Q/ E9 \% g9 h
- h# [, o. _7 h2 A' ~: belse& F6 }4 S0 b; Q, F" v2 W
; V. u. R! ~9 w9 ]; A
0 d7 M& X: k7 d6 f5 ~ ]: L. j7 E+ Y& M; W% @9 u7 y' A$ Z( \9 q
{
5 j9 {5 e0 v) i. l
4 }( d2 U0 P; n4 I9 h; [
! `9 z4 X- D, p, U' p2 J/ o7 x g
RxBuffer[Uart1_Rx_Cnt++] = aRxBuffer; //接收数据转存) G. D# S) s B2 G6 y/ Y; x* I
1 d* l2 k7 b5 f# Y1 n" r
- 7 c9 V# p. h4 |3 F. p
% Z2 O% J: q0 ?. i9 i
/ j. ?) e4 h [) a- Y3 u( v$ [
; I8 D3 k" ~" Y3 x' e6 u - 6 r! T( d' N) M+ o0 Y9 s. |
: q6 V/ \, R; M _if((RxBuffer[Uart1_Rx_Cnt-1] == 0x0A)&&(RxBuffer[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位# J- F" K) `! R! s, m
0 E4 T8 q6 G# O+ M( U6 i- l/ j& o: p
' F; [, a, X! K' ?& O, {7 N' i' A3 a+ m8 ^2 }
{- C% n E4 ^" G
$ t4 c& s5 R0 k5 f! R- $ o+ `2 A- x1 J6 C Q& n
4 D( |" F. z- |8 OHAL_UART_Transmit(&huart1, (uint8_t *)&RxBuffer, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去: W- n5 S$ J) ]
7 N) W1 \# R1 _- R* v0 d |9 b0 [
8 T1 n/ W- c. \5 E1 x2 S
! h. ~/ |" @' @( Pwhile(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);//检测UART发送结束
P& w$ S- i+ l5 D, \% T! J, D' w2 ?% Y( G, K8 F8 ]9 g
- v- S1 `( E$ P
% ]+ d5 k+ G8 O' s
Uart1_Rx_Cnt = 0;+ y# x; L0 j; k/ p* ]4 Y
3 [# F* N$ ]6 U: r+ f) i - / w1 @1 K6 b/ r4 `% C% _+ z0 h9 d
* T$ n+ H/ a! U; }memset(RxBuffer,0x00,sizeof(RxBuffer)); //清空数组" `6 Q+ M% l6 x% v) t1 t( C
. d; X0 T( R# i2 V' \$ `7 q5 Q
: q0 R* l; t7 |& [
9 N9 S& I. A2 \" z9 d}
/ P. q- [" V" M( j! A
) V1 v. r) o) N
' f5 ]& A P* P) Z4 [5 O3 f
) N2 ^4 l' ]7 n+ ]% ?}
( A3 X' f) K* W( ~# L1 {" o5 H; G! b8 G% N, w+ B
- 1 `% A$ B5 p( P3 [" `; ]1 Q8 V3 |
+ K# m, M( q5 x+ a' X! L
" L2 R6 I; r$ X0 T/ R+ Y& ~6 I! T) j: c0 |' E0 J1 _5 ^! Z
! q- N- V/ a, w. O- W* U9 O! I g2 w" F0 s) h7 M
HAL_UART_Receive_IT(&huart1, (uint8_t *)&aRxBuffer, 1); //再开启接收中断
9 |, q5 `) V- c4 e5 k: {7 i1 N# Q {- C" _7 t a- o# k
- ; U+ A- x4 U; M7 U r
% W! k6 H; s) H
}4 H4 V" V& p! e/ T& Z% J
6 i0 z* E0 |1 s5 W* r2 R
: C' m( k: `; J: M& \" s$ L% [, l( t; X) x0 L' x7 U6 X* t' [" U
/* USER CODE END 4 */8 v. Y- q2 L2 T
" R+ x$ X/ L4 v: r/ A* `: K% e8 m+ |% V( p& @# [3 i0 z& W. p
* a7 P! {2 }- V+ `: Z. w1 q7 \发送数据被正常返回 + L- X2 x u+ ~. N9 y9 ^. h8 L
- @$ J5 j. m. H1 j: e: }$ K4 x |