首先总结全文,通过查询方式运用USART1口收发数据的主要步骤如下:
' j" C8 D* \( c4 S1.初始化GPIO口
/ k% @$ P4 y+ r. k( y) w: b5 r9 S2.初始化串口
. ?5 e/ ^! i9 X5 D' d* P# h# S$ e3.编写发送数据函数: o0 k* ^7 c: q+ R' l
4.编写主函数
5 B* c: ?2 A* f下面介绍详细步骤:5 H& T! u; a5 x* k
( H3 `/ H: P7 I% p
1.初始化GPIO口% a2 M) |+ i7 i3 J r1 z
通过查阅STM32数据手册可知,stm32f103c8 ,USART1的输入、输出引脚,分别为GPIOA端口的 Pin_10,Pin_9引脚,所以先定义GPIO结构体并赋值:% _$ Z3 O( M$ q5 d
- void IO_Init()
9 M, M. {0 ?0 R1 |7 B$ r0 V - {, V* x. _0 ~9 E! F5 }
- GPIO_InitTypeDef Uart_A;
! W6 q. ^$ S0 m' I - ) c( g- t! d2 Q
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);7 c7 e2 ?! l# n& Z) t) v: g+ o- W
- Uart_A.GPIO_Pin = GPIO_Pin_9;
' q+ R. E6 j9 K6 s - Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
; J! k1 \. y$ |! P - Uart_A.GPIO_Mode = GPIO_Mode_AF_PP;
6 S3 _( V5 l) u. x! P) @0 x - GPIO_Init(GPIOA,&Uart_A);. ^7 t6 j9 l5 w
- 2 N8 Q L$ y6 R% h& G2 `
- Uart_A.GPIO_Pin = GPIO_Pin_10;
4 x: e1 S5 M9 z$ Y4 ?1 S& ` - Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
2 }: X% U) P% y/ R - Uart_A.GPIO_Mode = GPIO_Mode_IN_FLOATING; //stm32 data sheet page 1107 V* c8 N3 y9 s0 n$ X/ W# M
- GPIO_Init(GPIOA,&Uart_A);
# d3 u! I# e \: g6 @ j z+ R -
+ y/ B. s/ K8 ? - }
复制代码 ' z! Y+ L2 s" A' k$ N
还和以前一样,先定义GPIO结构体变量,在使能GPIO外设时钟,紧接着分别对各个引脚的寄存器赋值并初始化。# }% x& W3 k/ V: B. }6 W8 B
! y% x$ z: P6 {* q( t, m% T
这里需要注意引脚模式的选择:根据STM32参考手册,在全双工模式下,输出口的引脚(Pin_9)要配置为推挽复用输出,接收口的引脚(Pin_10)要配置为浮空输入或带上拉输入,刚开始学STM32不需要过深了解,只需要知道引脚要配置为相应模式即可。如想深究请查看STM32参考手册110页。/ R1 x3 D) Y& ?4 X6 d3 k
" p. j1 Z3 p4 ^ `2,初始化串口
X1 p( V, N3 A& m8 M要初始化串口可以利用库函数中的串口结构体 USART_InitTypeDef,这样对于初学者来说方便易懂。3 V3 `+ U# ~ l8 |- q, `: I
7 H1 m( {6 s( T ~) [8 j( L. [+ H0 v: O库函数中的结构体 USART_InitTypeDef为:
7 C7 ~2 w2 n9 f1 c- g6 Q5 R+ g0 r5 s) `. L/ j
- typedef struct
4 F% ^! x# ^7 {9 M- f8 Z2 N - {//波特率# }. p6 B1 K) _/ O( B2 Q
- uint32_t USART_BaudRate; /*!< This member configures the USART communication baud rate.& X2 Z* \% Q% s, v
- The baud rate is computed using the following formula:
( W( F! v& ~, ?6 b2 x - - IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct->USART_BaudRate)))
6 \; @# ]8 H+ f, t$ a A0 F. G - - FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5 */
, {1 A1 | D9 |9 e - //字长& l, Z' l0 c. {; h" Q/ M
- uint16_t USART_WordLength; /*!< Specifies the number of data bits transmitted or received in a frame.- r6 y3 ~* ] e. ?+ o4 b
- This parameter can be a value of @ref USART_Word_Length */
- M$ I' l4 l) F* A0 ? - //停止位3 o! o8 W \0 \* ~. S/ W
- uint16_t USART_StopBits; /*!< Specifies the number of stop bits transmitted.4 K8 a/ {8 Z8 \& I3 ~" Q# m
- This parameter can be a value of @ref USART_Stop_Bits */" V8 o! ?( l$ M- [
- //是否奇偶校验
, O' V- |) n& L9 {9 M$ B" K9 e! x" ]( \ - uint16_t USART_Parity; /*!< Specifies the parity mode.3 I. P) j' u I& b+ d( p
- This parameter can be a value of @ref USART_Parity
% K! b) ~, w+ F. F: S - @note When parity is enabled, the computed parity is inserted6 `& C. p- E7 c0 c+ d. i
- at the MSB position of the transmitted data (9th bit when8 U" I$ @( o% B8 N% L% E1 ^, ^9 ^
- the word length is set to 9 data bits; 8th bit when the
: o$ T2 k0 \) m% m7 A - word length is set to 8 data bits). */$ L E$ r. e1 v# i; ]5 y) t' a( d
- //串口模式,收or发?3 X* h9 G9 S | q+ n* {" V C
- uint16_t USART_Mode; /*!< Specifies wether the Receive or Transmit mode is enabled or disabled.
9 ~; V- P* y$ }/ C6 O8 u8 C! o& i - This parameter can be a value of @ref USART_Mode */2 H T H4 b5 b9 {
- //是否使能硬件流,这个初学者暂时先放放,还用不到(博主现在是初学者)" V! e# s( s1 k1 Q
- uint16_t USART_HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabled
1 | f. {7 } F) P; r5 x5 ], y4 X5 | - or disabled.+ t. S5 ^6 m, h6 i* ^4 k
- This parameter can be a value of @ref USART_Hardware_Flow_Control */+ g% X1 p' r' c- n; X! }" F
- } USART_InitTypeDef;
复制代码 / H& }# n, ]) f$ R& p
知道了结构体,便可轻松理解下面的定义了。& L& z) L. Z/ f2 O* Q
5 o8 N ^& J" l
5 w" r7 A6 t8 U0 _$ ? b* M/ a
' N) C8 Q, ]5 k' O$ z, I! A0 \
使能串口时钟后,依次对结构体中的变量赋值(注:STM32的每个外设都有其单独的时钟,只有使能了其时钟,外设才能开始工作)详细代码如下:: R$ {( y2 J8 E# T5 b, \8 E( w
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);1 N) _+ `' ~7 p, X
- Uart.USART_BaudRate = 115200;//波特率115200
+ ?1 q0 [3 W( _ - Uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//硬件流失能
$ b% d, }( o5 \; t" O - Uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//设置为 输出和输入模式
& I3 J4 Z6 c: Y& k* q4 G# D - Uart.USART_Parity = USART_Parity_No;//不进行奇偶校验" m6 R5 U* c, R2 O# l9 U
- Uart.USART_StopBits = USART_StopBits_1;//1个停止位
8 u9 C0 ?2 a6 k$ i& } - Uart.USART_WordLength = USART_WordLength_8b;//单次数据长读为8& j" U# y7 `2 a( O5 e: Q B# e
- USART_Init(USART1,&Uart);//初始化串口
复制代码 , e+ }* t1 q& j j9 T
在初始化串口后,按照STM32参考手册还需要对usart使能见下图:
- ?- B1 _) ^6 p. Y* y9 M8 W; g7 Z) z
9 P* O3 e$ t( r
7 h" ^' n3 M$ S3 O0 L
8 N5 f5 p: Z. q, K9 J' ~6 N
(注:博主当时在这里想到一个问题:STM32有多个串口,但是只有这一个串口使能位,也就是这么多串口公用一个使能位,那么,当使用多个串口工作,如果临时需要关闭一个串口,怎么办?答案见文章最下部分,答案1。)7 U+ z+ v0 Q% {7 Z+ M5 D, o
' B, M, p" H- U# R" E* n
由上图可知,在初始化串口完毕后,还需要使能串口:( n9 R/ b( I9 K9 @* B
/ S4 q# h2 j0 E5 i T
- USART_Cmd(USART1,ENABLE);
复制代码
2 u9 P) a3 R! z6 m& d8 o( ?0 F& ?: r& l" B0 W0 N: e
{0 C% A5 k& a; J然后根据参考手册:. @7 `- A& E8 e9 M' S6 W6 X
( I. q9 p a0 ^/ W+ H4 {
8 }4 y+ q3 ^7 `
, P7 a5 ~1 K9 |+ ^/ X
$ p2 z% o# G8 U1 |5 b. P6 _( a: L5 y. N8 R6 t* v
( t3 v$ C/ R$ [$ W5 ^% ~
此时还需要先清除状态寄存器USART_SR的发送完成(TC)位,要不然发送数据的第一个字节显示不出来。代码如下:5 ^4 @' S0 f3 T( ^
9 \ J J, y" {, S/ s
- SART_ClearFlag(USART1,USART_FLAG_TC);
复制代码
( p6 {% e% O2 I6 e/ R; n% ~到此,串口的初始化也就完成了。
& m& I6 H: X% n( g% v+ M d
) r z* H+ |% d4 h9 @$ }' u3,编写发送函数
; k, h/ D$ P2 W. f此处比较简单,先说代码:
$ C3 p( l9 y, @. L- void sendByte(uchar character)* u( b6 T- g5 Z- W, Y
- {1 L/ _; f8 y' _: O6 ]! [; p& \
- USART1->DR = character;
8 V# w' G8 T$ Y% a8 }2 h - while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
) Y& _* Z6 J+ u9 N6 j1 x - }
复制代码 1 X/ k8 B" c6 c3 B
需要发送时,直接把数据赋值给USART1的数据寄存器(USART_DR),即可通过串口发出,接下来需要等待数据发送完毕,当数据发送完毕后,USART的状态寄存器的发送寄存器空(TXE)位会置1,(RESET在库函数的宏定义为 0),即,若数据未发送完成,那么循环会一直空转,直到数据全部转到移位寄存器。: N6 I# g8 Z3 j/ j
6 L) r k2 [! \' c7 x- s0 @' i
4.编写主函数
2 L' p# y, y4 r! ~本文是通过运用查询方法来实现串口的发送。通过串口向电脑发送一个字符,串口之后会自动向电脑发送已发送字符的后9个。8 h8 X* E8 H2 T9 e' r* N
" h9 _% h' T" u7 g* J先粘贴代码在解释:( E( m" G) W5 l1 w1 o s
; W/ O( r; V `: |$ m3 s0 \- int main()4 @' a( r; _) q# q0 J$ D
- {" r `# u8 F! S0 l1 Y! G$ a+ M' c
- int count= -1;
/ p* O* w4 v% }, A/ A# q2 e - char temp= '0';
3 U- Z7 [2 P/ u" N/ ~5 o4 T4 \ - IO_Init();
/ p( ~: g! m; k+ p - Usart1_Init();
0 r: x7 j8 w0 K* [, ^2 s0 K - while(1){2 x+ L0 i! f4 Y$ K6 i& |
- if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE))//判断是否接受到数据9 Z, N8 n2 R, P$ p8 A' G
- {
5 L' R. w+ X; B7 O1 r - temp = USART1->DR;//若接收到数据,则将数据从数据寄存器取出( a; t( }' Z. g1 I" C9 F) v
- count = 10;
, o$ X; ]: q0 N" W7 ? - } % M5 m6 O" ]3 [3 X
- if(USART_GetFlagStatus(USART1,USART_FLAG_TC) && (count >=0))//判断能否发送数据- v5 e+ f8 S8 M" k
- {$ ^ k& x+ X1 l
- while(count >0){
. l6 E* Z5 K& |- t7 _: p& @ - sendByte(temp++);//若能发送数据,则向接收端发送数据
; T8 X0 X8 j' D: i) x - count--;//连着发送10个字符- C p! b3 l- d9 g/ o" ]! q i7 z1 h. d
- delay(1000);延时一秒& D3 Z' z9 N4 o3 `
- }1 u& W( i9 U* C% b' k5 Q
- if(count<0){
* Z8 F9 [7 c" Z; }* V: N. g0 s' }3 Y0 f - sendByte('\r');//博主本来想在电脑接收端输出回车换行,但是一直接收不了,还没弄明白。
* J! z0 q7 h; i - }
8 B# B2 @' W! w4 } s, A/ e - }
. j# K% ^6 Y h - }
V8 u1 Q3 T9 v7 d# { n - }
复制代码 5 v0 | E2 m) P. @4 |: G
解释见代码中的注释。( W0 I% Z$ V4 O
* f1 y+ |. B& q/ i( Z2 M
答案1:当不需要使用多个串口中的一个时,直接将对应串口外设的时钟失能就可以了。: |$ c; B) ^6 c) e, ?5 E5 L
9 F- t5 M1 V5 D: W# x通过查询方式实现串口收发数据完结。2018年3月20日$ N( [6 | X$ Y0 c* D1 |6 C% n
& O3 H( C; u+ _9 c7 Z
下一篇,通过中断来使用串口。
! e6 X4 `$ S- n2 |5 `! @2 W! f2 s1 T* j3 U, C' M
见STM32基础设计(3)---中断串口通信
7 L# e8 m& e$ i G% U3 v: `0 M
本文的完整代码如下:
. y% |8 i/ t% a) p. X; R" x- #include<stm32f10x.h>
4 `$ m' D6 d3 S - #define uint unsigned int
! @% d! b# ^# Q( _7 M) ] - #define uchar unsigned char' n* m$ A w9 v3 `( R+ \
- void delay(uint n); h3 P. H9 _! I4 `1 x
- {: C, n+ q6 ]6 O3 W1 X: l: ]
- int i,j;5 Q/ n- c0 s5 d/ j$ J a
- for(i=0;i<n;i++)
. o1 B' f$ @0 p! Z- I - for(j=0;j<8500;j++);
$ t+ u5 f0 e; L# k - }
2 `+ M+ A+ M! r9 m' T { - . e$ I M g: v8 y- k
- void IO_Init()) j6 n' g0 Z' [3 R
- {
$ {/ _9 {: I6 q5 S6 H N' H" d! t& a - GPIO_InitTypeDef Uart_A;' w5 W# c3 G/ F0 h
-
- K, H5 U% @5 D6 ?+ I$ ^4 w - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);2 p$ G/ c0 _% W8 C) Q
- Uart_A.GPIO_Pin = GPIO_Pin_9;
1 N& X! R. V8 e4 X& K+ u - Uart_A.GPIO_Speed = GPIO_Speed_50MHz;; V# @+ j$ Y! H1 ~& x3 _
- Uart_A.GPIO_Mode = GPIO_Mode_AF_PP;7 Z0 R1 Y9 F+ `, a4 O; h' f( m0 K
- GPIO_Init(GPIOA,&Uart_A);5 J6 x( }* X' u! ?1 t- [
- ' B2 w& q# V9 m; P8 J. s
- Uart_A.GPIO_Pin = GPIO_Pin_10;
- i! S; d E' S- D# H8 v# X - Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
* O5 Y1 c o4 K0 I - Uart_A.GPIO_Mode = GPIO_Mode_IN_FLOATING; //page 110
7 x( z! {. f# e- w. F - GPIO_Init(GPIOA,&Uart_A);* l" s% ?1 q3 n: Z3 G
-
* u) z- e5 n* ?+ e7 K9 F - }
8 A) g, a2 z4 ^& _) a - void Usart1_Init(). A! @9 x% X( X; B7 m) O
- {) V, e) x0 R+ K2 V( b6 m, o( a
- USART_InitTypeDef Uart;* r; O' n6 }& F$ Z' ^+ t
- : t3 E9 e. ~" y( l
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);# u" G+ i7 \- Y4 u3 ?. l
- Uart.USART_BaudRate = 115200;) a0 E4 |, R$ l; r, n4 f3 \3 q. u
- Uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
: X2 D% J. q: }* o3 _ - Uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;& s' f3 K& U3 w; Q( W/ H z
- Uart.USART_Parity = USART_Parity_No;' k. {* w9 d; ~' u1 V
- Uart.USART_StopBits = USART_StopBits_1;
( z8 V* d; H% U$ Z: R - Uart.USART_WordLength = USART_WordLength_8b;2 ?0 J1 U- U. G- H+ W! c
- USART_Init(USART1,&Uart); N. b$ s" O8 [: P
-
% L5 \8 b4 P9 z7 z/ n0 [ - USART_Cmd(USART1,ENABLE);
% U+ p: x" V2 R; v) G$ Y - USART_ClearFlag(USART1,USART_FLAG_TC); //page 540
1 N! X4 y1 |- k' Q - }/ s1 x* G+ c' V% E! W/ g/ E
-
* Q& M+ _2 K) Z9 x6 Z# j - void sendByte(uchar character)
2 r: `' K- s$ b8 }8 ]: o - {: |+ t. \& k# A& b% X r) j5 d
- USART1->DR = character;" j9 y5 c/ K4 f, i) J
- while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);# G0 L6 a* P9 ~5 C4 B
- }8 i/ h# h( D) U/ s2 B- R
- : N9 b* ?; h. r5 O1 k
- int main()) C1 y4 {9 _, E- O
- { r) ` R# J. X# s1 t0 R6 g4 T
- int count= -1;- W* {& `& j8 Z" d
- char temp= '0';
7 q# o4 k5 L3 F' F" Q% M* C - IO_Init();
& P% I, x9 J1 h q" b - Usart1_Init();
) ^0 K. M5 n% g, ~6 l4 o - while(1){
4 v' U: `: x0 }$ v0 [; u - if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE))+ l9 ], y- l3 \8 {. R: s |6 L
- {( v& k$ Z% ^' d' D% |
- temp = USART1->DR;
4 e5 m. L5 ?9 ?% i% | - count = 10;" m/ ^6 C3 W7 _: |1 b1 P
- }
& E6 J/ b7 ~1 t1 { - if(USART_GetFlagStatus(USART1,USART_FLAG_TC) && (count >=0))% ~" Q/ ^4 L" A& o
- {8 P, u8 P: ]& I F5 ?, A
- while(count >0){
- Z3 S, o7 i+ n6 m - sendByte(temp++);
1 h b" n0 Q# o" R' \! f - count--;
; `( X2 p3 F- i - delay(1000);
& t6 _7 r) b% u& t7 t# }$ E! p - }! a% |; W- R3 |) U( o( W
- if(count<0){) |9 j* ~6 c: n ]& ?, j
- sendByte('\r'); ! j0 h+ s1 z+ t) ~; p0 F
- }/ t3 s" H; x) `! E( t' ?
- }
. S& Q% H$ [ e7 k1 p - }
6 y7 Y" B9 j' N: y - }
复制代码 / I! N6 u0 j) `( T+ s1 F: o0 Z
————————————————
9 S1 X6 e9 n1 W9 i, @* @版权声明:家安
" ]/ c/ o9 C, F; R+ ]# W; E# b: K" i
" O4 J+ @1 A. Q* m* c2 ]
|