首先总结全文,通过查询方式运用USART1口收发数据的主要步骤如下:
* q) F% r: x4 o$ n1 u' Z; Y4 a$ J9 k1.初始化GPIO口
/ X4 ^( \8 N' d: n2.初始化串口, `) T2 ?6 L7 s; e
3.编写发送数据函数
0 [$ Q. b9 x& H# ^4.编写主函数! m; D. S1 Q% Y; t
下面介绍详细步骤:
9 e5 h" l3 S0 F! h2 ]* F/ l9 o* W8 f+ Z- A; T7 `
1.初始化GPIO口
) W, Z, j8 t5 u! Y- U( x I! ?3 S+ }通过查阅STM32数据手册可知,stm32f103c8 ,USART1的输入、输出引脚,分别为GPIOA端口的 Pin_10,Pin_9引脚,所以先定义GPIO结构体并赋值:
" E2 y% l) i, o( @6 k3 X! h9 G7 ]- void IO_Init()
+ b( _: G* ~ x" Y. i - {: @' F% C( Q! e
- GPIO_InitTypeDef Uart_A;
9 |% M& f v$ H8 b2 k -
: v6 D& S7 H, G+ A$ t0 f - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
; ?* U) Q+ N8 g& ~: _# ~- I/ V( k - Uart_A.GPIO_Pin = GPIO_Pin_9;! a6 ^- s; G c
- Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
- b- P9 J! Q9 P7 X6 c5 K - Uart_A.GPIO_Mode = GPIO_Mode_AF_PP;
/ A' ^( [/ A5 N1 j T5 n - GPIO_Init(GPIOA,&Uart_A);
5 K) P3 I' w$ p -
0 r$ F- G) a! R0 c$ c' l - Uart_A.GPIO_Pin = GPIO_Pin_10;
, E3 M0 P; L' w- U - Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
& w) M1 Y3 v$ D' Y - Uart_A.GPIO_Mode = GPIO_Mode_IN_FLOATING; //stm32 data sheet page 110
8 x6 v) K. z" \2 W( {, R+ m; j' w - GPIO_Init(GPIOA,&Uart_A);
8 D; }- c* m2 y - - n# G' U* z3 x, b, _
- }
复制代码 7 D+ u" G' o& I$ p9 L E
还和以前一样,先定义GPIO结构体变量,在使能GPIO外设时钟,紧接着分别对各个引脚的寄存器赋值并初始化。5 r. ~8 M5 ~$ h
. M8 L9 [2 p& ~* Y6 ^$ t
这里需要注意引脚模式的选择:根据STM32参考手册,在全双工模式下,输出口的引脚(Pin_9)要配置为推挽复用输出,接收口的引脚(Pin_10)要配置为浮空输入或带上拉输入,刚开始学STM32不需要过深了解,只需要知道引脚要配置为相应模式即可。如想深究请查看STM32参考手册110页。
5 a7 B: @/ G6 F6 B# P9 k8 O3 D9 M+ j! K+ f* t2 R
2,初始化串口
3 N% s: b; |4 p! B/ ?( i要初始化串口可以利用库函数中的串口结构体 USART_InitTypeDef,这样对于初学者来说方便易懂。
6 w ^& Q' t4 M" }" [/ C. S# G, u% `, q2 {. L
库函数中的结构体 USART_InitTypeDef为:
/ \6 X# [7 W6 O! H& e2 u1 m* e+ z, U Y" k- u- Y
- typedef struct5 P9 b: W7 D+ K3 M h, P
- {//波特率
, y6 Y; ?' U1 d$ M$ @, D - uint32_t USART_BaudRate; /*!< This member configures the USART communication baud rate.
, r, G7 T7 |- `* B& j9 s b - The baud rate is computed using the following formula:( x4 l, w) G4 L
- - IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct->USART_BaudRate)))
2 @. w( K, L" Q& a1 _7 u - - FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5 */
$ A# V+ y) Q" d - //字长9 @4 t6 O$ b. _7 c: p2 Q
- uint16_t USART_WordLength; /*!< Specifies the number of data bits transmitted or received in a frame.
4 @3 B* h) T3 b) ?7 K - This parameter can be a value of @ref USART_Word_Length */5 e! q% a$ r- d" r; @& k8 |# o
- //停止位
' ~! R8 n! O- {2 u+ G2 }9 c - uint16_t USART_StopBits; /*!< Specifies the number of stop bits transmitted. C& J% y* Q: u } A: H2 P
- This parameter can be a value of @ref USART_Stop_Bits */
/ I! E- k7 ?( r1 q- \+ { - //是否奇偶校验
3 [8 q# { ~/ C8 ?% B5 W - uint16_t USART_Parity; /*!< Specifies the parity mode.
( y6 b0 ? @5 r- w' I% E! | - This parameter can be a value of @ref USART_Parity
% I+ k) _+ E, ~0 i - @note When parity is enabled, the computed parity is inserted
9 p3 D( k* z+ o9 w" e* [ - at the MSB position of the transmitted data (9th bit when* g8 `# x" b. F3 V! S, R" b
- the word length is set to 9 data bits; 8th bit when the
3 U! I2 H) u$ A" d+ x2 C - word length is set to 8 data bits). */
4 U4 d" l2 y n - //串口模式,收or发?8 g% M3 X. @1 n# S: l1 F+ O. _, T/ m
- uint16_t USART_Mode; /*!< Specifies wether the Receive or Transmit mode is enabled or disabled.3 Y6 P. |: F- P
- This parameter can be a value of @ref USART_Mode */
$ I0 U$ J: [1 A. B8 b1 f - //是否使能硬件流,这个初学者暂时先放放,还用不到(博主现在是初学者)7 f) I' \' O) ^. p8 \: j
- uint16_t USART_HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabled
- n. e" Q- ?2 l5 f" c: I, d - or disabled.
2 A# X# ^4 K, Y, u+ e2 M3 l - This parameter can be a value of @ref USART_Hardware_Flow_Control */% U1 L2 S5 a2 ^ K
- } USART_InitTypeDef;
复制代码 $ f0 O' I( s1 |) P* t2 J
知道了结构体,便可轻松理解下面的定义了。
) \1 m8 ~" h1 w7 k3 e3 n! {" I& B9 I( O
+ x6 G/ u z6 n4 |4 ~
2 U4 n# h. P# h/ w/ h* y3 \
使能串口时钟后,依次对结构体中的变量赋值(注:STM32的每个外设都有其单独的时钟,只有使能了其时钟,外设才能开始工作)详细代码如下:5 M+ }3 N/ S$ o: C' `% R
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
o( q0 Q# r5 }( [% h8 ^5 z* w( J4 a - Uart.USART_BaudRate = 115200;//波特率115200, B5 [0 ^9 H: t2 l# T; G `8 g- e4 @1 t
- Uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//硬件流失能
L0 G Q, f% T, A - Uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//设置为 输出和输入模式1 {$ h7 K! M' K9 E0 ^
- Uart.USART_Parity = USART_Parity_No;//不进行奇偶校验
: {5 u7 ~, A9 t! T9 { - Uart.USART_StopBits = USART_StopBits_1;//1个停止位3 E, q' T% `: f
- Uart.USART_WordLength = USART_WordLength_8b;//单次数据长读为8- P6 U; J2 p* k
- USART_Init(USART1,&Uart);//初始化串口
复制代码
2 `, F3 S6 ~" i# v8 V3 {在初始化串口后,按照STM32参考手册还需要对usart使能见下图:
# C" p7 a0 k' R/ ^& F, f/ B$ E) O& l) }/ Y, M1 B
- z$ ~0 M- e/ x' L: T; h
. B5 C8 v+ U# v o(注:博主当时在这里想到一个问题:STM32有多个串口,但是只有这一个串口使能位,也就是这么多串口公用一个使能位,那么,当使用多个串口工作,如果临时需要关闭一个串口,怎么办?答案见文章最下部分,答案1。)& |2 y. x3 Y: o. a
/ _# D, H# O- F, L( b. N由上图可知,在初始化串口完毕后,还需要使能串口:7 ~# ~/ o t' U$ U8 z9 l
, C {/ M! u+ J( n9 M$ W
- USART_Cmd(USART1,ENABLE);
复制代码
2 K! Q2 J( s9 R# _6 T, ?1 D& H/ d6 `+ l
5 @% w ?1 e& f" S; U3 k# f然后根据参考手册:- U) @& g- r v
# I; v& ]' }" z% U3 f4 Y9 E
; X q9 B5 W& O! e4 N
' c& C R" E, H" `( R/ Y) e+ O. \
7 B& R/ T- s8 }/ G" y
1 a2 _8 ~7 W. I+ x
# z$ M' T5 w9 F; |" F8 Z此时还需要先清除状态寄存器USART_SR的发送完成(TC)位,要不然发送数据的第一个字节显示不出来。代码如下:& c5 @( S9 ~1 }/ R' {/ S; }
4 z1 g, U$ `( |5 W% U
- SART_ClearFlag(USART1,USART_FLAG_TC);
复制代码
) r8 Z6 H6 ~" j! w4 L$ P9 Z到此,串口的初始化也就完成了。) w. x! W; ^; S, Y
( Q2 Q' Q7 l8 r; j& a5 U
3,编写发送函数
& g& l4 ?# |, c# ^- S& I$ i U4 i此处比较简单,先说代码:
& U1 A$ s+ {, i/ E5 N5 J- void sendByte(uchar character)) {, N( e0 o7 ` \4 |' @' j, M
- {
* X3 C9 d2 Y7 E" u$ ~ - USART1->DR = character;' i$ ] l: [5 g: \5 d2 K
- while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
. V! J$ b0 P2 R5 c& g - }
复制代码 + b7 R" H9 { G L+ K/ q
需要发送时,直接把数据赋值给USART1的数据寄存器(USART_DR),即可通过串口发出,接下来需要等待数据发送完毕,当数据发送完毕后,USART的状态寄存器的发送寄存器空(TXE)位会置1,(RESET在库函数的宏定义为 0),即,若数据未发送完成,那么循环会一直空转,直到数据全部转到移位寄存器。+ @2 t! N% w. f8 v* S9 i+ L6 s6 r# T9 k
6 f' J5 x6 h$ d; t: k4 k9 @8 Y
4.编写主函数
3 C5 ?) ? [; [本文是通过运用查询方法来实现串口的发送。通过串口向电脑发送一个字符,串口之后会自动向电脑发送已发送字符的后9个。
: k$ M' c4 U+ P# o+ Z k/ X6 n1 h( v8 `2 U4 L$ d6 Y$ q
先粘贴代码在解释:/ v. C: D1 z# a$ z9 o
, P H9 W, k5 {2 e0 Z9 E0 t
- int main()3 f2 `) w- J2 k& C8 c+ N! S
- {
1 |9 B t! q o& [, y; w- j) L - int count= -1;
% q4 R0 ^: p6 y* K - char temp= '0';
+ o. W5 s: a( b# @- i5 n0 m - IO_Init();
! S2 J' f/ S# D* e4 D - Usart1_Init();
j1 b" l, ?" {# i4 \; y! N+ S i, X - while(1){
F2 B! [$ U0 d - if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE))//判断是否接受到数据9 u. R/ @" v3 J5 \1 I" E
- {
8 \( Z5 ~. h% q) P S8 w* ^# V - temp = USART1->DR;//若接收到数据,则将数据从数据寄存器取出7 y$ {$ E, Y4 b; t
- count = 10;0 T4 b$ d T+ b/ W& f @- i) V
- }
5 I* y3 b! c4 R! U- N - if(USART_GetFlagStatus(USART1,USART_FLAG_TC) && (count >=0))//判断能否发送数据. {" \' m; N8 [: i) {3 G
- {% c: m E: G Z. q- x9 e
- while(count >0){- `# k6 a% ^$ ^+ b
- sendByte(temp++);//若能发送数据,则向接收端发送数据
# ?7 N7 w- Q' b - count--;//连着发送10个字符1 R; a# g$ G5 s
- delay(1000);延时一秒: D& x2 J" s8 X$ G$ B! L9 A
- }. T2 i; L* s7 p& w/ ?$ q6 m4 g
- if(count<0){
) p9 G( {5 y5 C- b4 z9 ~6 W% [$ D! o( U - sendByte('\r');//博主本来想在电脑接收端输出回车换行,但是一直接收不了,还没弄明白。
7 a& ?& M% x% q. Y" T+ w- s8 D - }( l& @5 {; k g3 `4 D
- }
9 @. b5 l0 O5 g/ v+ g# t - }
1 T% e o- } C" E% I! G - }
复制代码
/ |/ q4 q/ h5 z, ~( ` f解释见代码中的注释。3 K; p `5 g, ?! T: W; m( S
$ O# W% G( S3 }& @' b
答案1:当不需要使用多个串口中的一个时,直接将对应串口外设的时钟失能就可以了。
3 t' J8 R) T0 k% I! f& a; k7 ^5 Z/ d6 j+ m& h
通过查询方式实现串口收发数据完结。2018年3月20日/ G& b D7 K7 L/ k9 [
b5 Q) j5 H! ]% U
下一篇,通过中断来使用串口。
8 @# X- ~* I- B. D( H% v6 ?) f+ e+ C7 z( l) }
见STM32基础设计(3)---中断串口通信
: i% g- [9 ^# U6 B5 v/ z' o- z w/ r- N; t6 w. f
本文的完整代码如下:
: o: k: G, T6 \$ T, |- #include<stm32f10x.h>
' X( X) R$ K ?: H, L - #define uint unsigned int
6 U9 p; P) W! R6 S - #define uchar unsigned char) U8 Q7 U& a/ U$ y0 y
- void delay(uint n)* Q5 ^. s% T% Y8 S5 e* R2 ?
- {" a' z- U+ p% d
- int i,j;
, { ^$ [0 D7 P2 l% k; _8 K D, l - for(i=0;i<n;i++)
- K' W) X$ c# ~0 w - for(j=0;j<8500;j++);
% T$ U0 E* W# W) t0 [. c$ ^ - }9 D8 c' O. |9 v: H V
- 1 ], m6 W+ c! `
- void IO_Init()
5 I' z/ U1 k4 j4 Z - {
+ }9 X& [! h4 L$ Z, V - GPIO_InitTypeDef Uart_A;
& f4 c6 ^- c/ M5 m. B; o1 ] -
5 k5 E4 z4 k8 L9 @ - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);0 }! U6 \. e/ Y9 z4 a" T
- Uart_A.GPIO_Pin = GPIO_Pin_9;0 L* Q7 g2 Q1 e; ~
- Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
- Q7 H! H; m/ L8 {; P. L _ - Uart_A.GPIO_Mode = GPIO_Mode_AF_PP;/ L9 f9 n# I0 ^/ _
- GPIO_Init(GPIOA,&Uart_A);
/ o8 S8 F: V+ {0 f* |- ~ - / [ I/ I; _6 ^
- Uart_A.GPIO_Pin = GPIO_Pin_10;: A. S0 T( [9 `! H3 u
- Uart_A.GPIO_Speed = GPIO_Speed_50MHz;
( N* d! ~* [! p - Uart_A.GPIO_Mode = GPIO_Mode_IN_FLOATING; //page 110
6 I( R; l( d- @% G+ K - GPIO_Init(GPIOA,&Uart_A);5 ~2 T3 `$ U) B5 y5 F! c9 f0 X+ K
-
2 I9 [1 ]$ _3 f9 e4 h0 X2 c- C+ K - }
4 W: \; H/ b9 d# Y, C6 m& X - void Usart1_Init()7 M- x+ ^$ f( t0 u* g- Q
- {# Y: i5 x. y1 s2 \; P
- USART_InitTypeDef Uart;5 K8 p T! j. W6 ^6 S* i `3 K
-
2 M% P ~5 l6 s& n - RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);2 @/ E1 t$ R4 t: u- X: {2 L4 Y
- Uart.USART_BaudRate = 115200;
! w# u5 w; W* A e8 ^: a7 h - Uart.USART_HardwareFlowControl = USART_HardwareFlowControl_None;. z s; }7 U8 T
- Uart.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;) G5 C8 ?+ b6 m( t! j# o4 I
- Uart.USART_Parity = USART_Parity_No;
6 h$ ]0 v4 N! M9 ~! T - Uart.USART_StopBits = USART_StopBits_1;3 J+ i' ~# T9 N& g2 U) k) c2 g
- Uart.USART_WordLength = USART_WordLength_8b;9 Z% ]) a: }+ c5 u ^7 w2 L* Z
- USART_Init(USART1,&Uart);
# F( {* s M. C1 h$ x - " s8 r J* q& ^- W' e. ~$ u
- USART_Cmd(USART1,ENABLE);
- N- }# U% t% n0 r9 t; T - USART_ClearFlag(USART1,USART_FLAG_TC); //page 540: u4 I* [8 W: h. q, H$ f0 n
- }
/ K2 c# J) L3 E2 h -
; g, _: ]4 {5 G/ d - void sendByte(uchar character)
' T4 {/ I0 v) ?7 E% A - {
) Z: o3 U$ O: e, g# A6 `- ]1 B - USART1->DR = character;
* x% }, s* @ L! f1 Z, P - while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);* L2 M( b6 @" A' k9 l! D
- }
$ O. {4 g( c' I# R8 s' } - 1 ~, h5 r. F) Q
- int main()+ o& E( A9 E3 Z# J: P- O
- {
6 m2 k# S. A7 D- ~+ ~ - int count= -1;
2 C( r6 x1 u% Z& {: M0 Y - char temp= '0';
5 v/ O; E/ @( [% l3 O - IO_Init();/ I& X& H3 z5 f, p
- Usart1_Init();) \& v$ f+ i- O! R6 ^6 ?
- while(1){8 O& G9 U# V( Q0 ^) l1 y
- if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE))
2 x7 p( u& F y) @$ q - {
4 O! J7 W- ] C0 C1 D) e - temp = USART1->DR;7 Q4 A( ^' v: g0 |. N5 \
- count = 10; S/ U; w6 W% J% p, q: q# I7 V
- } & l' g5 Q( i1 U! d( E N
- if(USART_GetFlagStatus(USART1,USART_FLAG_TC) && (count >=0))4 `5 L+ I. V8 ~% _# h6 @( C- e
- {* ^+ H) i8 R. f& b) A" m$ Z
- while(count >0){
" q( g9 k1 e- |$ P! v1 ` - sendByte(temp++);
( C% i6 z& P3 ^; | - count--;' X3 k( W' p" u8 \- z* W
- delay(1000);
^5 w3 F0 B7 u; x, l6 W( k - }( J4 A2 I K' S3 |$ G7 j( b
- if(count<0){
; r" o( g4 K! U4 @1 a - sendByte('\r'); 8 X9 Y/ ?& m; u, k4 @4 ?6 C) s. V
- }
& y8 I8 z. E, O1 }2 s0 ]9 t - }
1 b; W: r- K F2 G - }
5 E4 b# d% i4 ?0 h3 c* [, x" v - }
复制代码 ) i' {# t: E/ b0 ^& G0 t
————————————————' x! t. d* B1 t I: s; r H5 I
版权声明:家安
: k/ [& q' m. w- N( G+ p9 b, j+ R; U6 u! q1 ]" ^; {. x
3 o4 Y. T) L7 O c& [3 \2 Q
|