理论学习一、USART介绍
' {; m3 J" k: a2 A) R: O1.1、USART简介
# g+ u0 ~, ^8 Q* Z 通用同步异步收发器(USART)是全双工数据交换,满足外部设备对工业标准NRZ异步串行数据格式要求。通过小数波特率发生器提过多种波特率。支持同步单向通信和半双工单线通信;还支持LIN(局域互连网络)、智能卡协议与IrDA(红外数据协会)SIR ENDEC规范;调制解调器操作(CTS/RTS);多处理器通讯;可以通过配置多个缓冲区使用DMA实现高速数据通讯。
" i: Z B# t5 O ~- `, h+ d3 K) |% v4 d# j+ z
1.2、USART主要特征 x" f( f; p0 I( O! V
全双工异步通讯、单线半双工通信
* O# H9 z7 ^' X: g# J8 M$ E具有小数波特率发生器,可编程收发波特率0 ?7 r. M* n7 v) V- |! v4 \
可配置16倍过采样或8倍过采样,因而速度容差与时钟容差的灵活配置提供可能
- `2 }4 H1 Z7 p1 g" ]; D数据长度可编程(8位或9位),停止位可配置(1位或2位)) F+ ]' u a! G/ a v+ o" C1 H! Z
可以用于同步发送的发送器时钟输出6 v& ~: U7 q$ J0 v1 _; b
具有4个错误标志和10个标志位的中断源
6 |; j' n( I* R两个接收器唤醒模式:地址位(MSB,第9位),线路空闲, v6 D6 y8 a' C k/ s# p# d) l
) I0 I* X$ M. H5 T0 ]: x* @& @$ Z
1.3、USART功能说明0 B" e0 {- J: N6 T
F [: f1 D- y! ^
: i0 D) Z2 |9 d8 l# P$ m- y
+ w( C) K, W/ ^5 g9 j' B
4 e+ _ j2 B3 R8 Z- r3 d
引脚说明:RX-接受数据引脚;TX-发送数据引脚;SCLK-发送器时钟输出;nCTS-"清除以发送"用于在当前传输结束时阻止数据发送(高电平时);nRTS-"请求以发送"用于指示USART已准备好接收数据(低电平)。
$ t+ x3 j( z9 q/ D8 W4 \正常USART模式下(异步全双工),RX、TX以帧的形式发送和接收串行数据:1、发送或接收前保持空闲线路;2、起始位;3、数据(字长 8 位或 9 位);4、最低有效位在前、用于指示帧传输已完成的 0.5 个、1 个、1.5 个、2 个停止位;5、该接口使用小数波特率发生器 - 带 12 位尾数和 4 位小数;6、状态寄存器 (USART_SR);7、数据寄存器 (USART_DR);8、波特率寄存器 (USART_BRR) - 12 位尾数和 4 位小数;9、智能卡模式下的保护时间寄存器 (USART_GTPR)。
6 X0 Y x' O9 _, l: L7 M. Y同步模式下:RX、TX、SCLK引脚+ @, J1 M* ]0 J% J) _; R Z( U
硬件流控制模式下:RX、TX、SCLK、nCTS、nRTS
$ c( i/ W0 X+ R1 H* u* G
! ?$ o. L2 |% A5 v# e1.3.1 传输的数据结构
2 T8 l# S1 z6 f. e/ c起始位
1 A) O0 N6 y0 Z" X5 \, v数据位(8位或9位)
; v+ F3 M, `% G2 |0 z奇偶校验位(第9位)
# F- K | n$ g) V& d停止位(1,15,2位)) l: o( G8 A+ y. |9 r
! R. l* e* V$ O% d# O# i4 ~4 J5 |
2 x2 q9 M, Y9 _( [
^" f$ w/ K: l+ D# C# I1 q% c1 t
可通过对 USART_CR1 寄存器中的 M 位进行编程来选择 8 位或 9 位的字长。 U8 e) ?& V+ e" q7 L! P/ Y6 {
& n: s" V+ h2 j& ?% O# `6 y2 N$ ?3 M- P8 b# Y% e4 n
1.3.3 实现的功能1 h# W+ l1 P/ z- A! s
这里不对功能进行详细介绍,如果想深入了解请参考芯片的参考手册。
6 F5 d1 u- p( _& P9 b& l5 N3 x% T9 }" G2 L% z, g; V
发送器、接收器、小数波特率生成、接收器对时钟偏差的容差、多处理器通讯、奇偶校验控制、LIN(局域互连网络)模式、同步模式、单线半双工通讯、智能卡、IrDA SIR END EC模块、使用DMA进行连续通讯、硬件流控制。
3 i' M( m, w2 T1 O$ t
6 S0 A# [ J. `. I8 ^0 ?6 e F2 Y+ _7 m6 ~. K* Y3 V: U& y
1.4、USART模式配置(串口的波特率、状态、控制)
+ }9 b+ k0 E& n, R+ C* I
0 L9 z W8 ?$ d/ z& Z1 x
( y5 l6 Q4 y4 g9 H3 {7 ]7 @
( n% B) S% W! d9 B
本博客只是简单的实现串口的基本异步通讯功能,USB串口和电脑通讯。不做过多深入的介绍。 串口最基本的设置,就是波特率的设置。STM32F4的串口,只要开启串口时钟、并设置相应IO口的模式、配置一下波特率、数据长度、奇偶校验位等信息,就可以使用了。7 l' }( u" S7 v) d
串口时钟使能:APB1/2ENR" U: a8 s0 J# V! U0 [: E5 j
串口控制:每个串口都有3个控制寄存器USART_CR1~39 G9 }& B5 {% u/ y, p; C$ R
数据发送与接收:数据寄存器USART_DR(双寄存器),TDR(写入)和RDR(读取)
: A2 `7 ?/ A9 b2 M, G串口状态:状态寄存器USART_SR
7 W7 f) @. _8 z- W" r- f0 h# l串口波特率设置:波特率寄存器USART_BRR5 L: O1 H" u. M+ i- G) i w
) W; o2 d9 U7 a* [ \. r% J- i
4 g6 g' F( f; c
3 K( l; Z- c- h" d
4 w& M. s6 u" Q4 N/ Z" V
2 a8 D O# @# }: }* Y/ ?8 |2 ?. g( \# m g" K
以上是相关的寄存器,寄存器具体相关位配置请参考芯片的参考手册2 P9 F: w% l9 q
' g! ~$ b3 E; Z( g
二、IO口复用功能输入/输出) j5 d8 d" [. {. M) C
2.1 复用功能简介8 B$ L& |8 \! @; f# S
每个IO引脚都有一个复用器,采用16路复用功能(AF0到AF15),有两个寄存器(GPIOx_AFRL和GPIOx_AFRH)可用来从每个IO可用的16个复用功能输入、输出中进行选择。借助这些寄存器,可以将引脚配置为复用功能。& `, H/ u7 O! D+ P; V
6 k0 E- i- f; ?6 Q
* G* p" n: {0 L6 ?/ Q$ d$ F1 P% O- i- m s% e5 Z2 w
2 ^# t/ y. v2 k6 f$ U* A* Z: {. I
& K7 `4 i9 {( B* } 2.2 复用功能配置 y; X8 R5 t8 X. ]" s
4 q( C( ^) V) n, ^# A
' C1 a! F5 N1 T
" w5 y/ Z1 G- C, c
( m7 {& W6 y5 n" V4 ~
' B, \7 `. }) ?# U+ r# W
' j4 D/ Z$ [. {8 k
" `: J/ `5 A5 _, A# b' d
7 @$ D9 |1 r* ~% x# @ 除ADC和DAC配置为模拟通道以外其他一律为复用功能。 : F. a5 K7 T9 M5 R# I" |
V* i+ w" W" m( l0 L, y+ Z( h
. j6 J2 U) q/ V; F# ~2.3 USART1对应的复用功能映射引脚5 N$ n' n& ^" N
1 E/ N6 q& p! m
3 O; X2 r" k4 k3 t
( K7 K& q- G0 b, f) X+ j. Q" x8 L
$ F' y; A7 {, z. k) t& A# J( Z5 t) f( a三、NVIC中断优先级管理(串口中断)# @$ ^. L- [% }; L3 }7 [6 W$ a
3.1 NVIC特征
/ m' ?5 H. U/ s: m" a, h8 K STM30F40X具有92个中断(10个内核中断,82个可屏蔽中断),16个可编程优先级(使用了4位中断优先级),低延迟异常和中断处理。
" ^; ~: E7 R' x w3 _' C) x" U; C' W# `
3.2 中断管理方法 @9 L8 l# w9 s* r" e' |
首先将STM32中断分为0~4组,每组都有一个抢占优先级和响应优先级。通过寄存器SCB->AIRCR来配置。8 [- r5 Y6 p9 q
5 h1 t7 u7 i; E
) r4 o |7 n( K1 D6 X/ v/ C6 n$ p1 t6 ]0 \! }' @
高优先级的抢占优先级是可以打断正在进行的低抢占优先级中断的。# B$ q8 t* t: {8 K
抢占优先级相同的中断,高响应优先级不可以打断低响应优先级的中断。7 R; o% H4 d: \ }
抢占优先级相同的中断,当两个中断同时发生的情况下,哪个响应优先级高,哪个先执行。! {, n% k# ?( g% [
如果两个中断的抢占优先级和响应优先级都是一样的话,则看哪个中断先发生就先执行;
k: Q: m% p- f! D! }4 C0 s1 Z' z; H/ P
注:常用 ISER、ICER 和 IP 这三个寄存器,ISER 用来使能中断,ICER 用来失能中断,IP 用来设置中断优先级。' g7 L% \6 @2 j- K
2 F: S" @* C$ I7 j3 }
+ i; t5 \- v% W0 U' W$ s I3.3 中断设置相关寄存器- D) k0 {; Q. F6 l( H! Z* T
与之相匹配的结构体:
[: t- f1 o) e$ x$ O) l/ r
7 W! k: Q1 \, @; E9 K, i
: ?- i8 s/ G% f3 Z; X, S
) k& O9 i; w3 L3 E! V__IO uint8_t IP[240]; //中断优先级控制的寄存器组,Interrupt Priority Registers
& ^) _ G$ k F# g" V) x' @# }# H' A3 M- J
240个8位寄存器,每个中断使用一个寄存器来确定优先级,STM32F40x系列一共82个可屏蔽中断,使用IP[81]~IP[0]。每个IP寄存器的高4位用来设置抢占和响应优先级(根据分组),低4位没有用到。 例如:NVIC->IP[37] = 0xf0; //对应将USART1的中断,设置位抢占2响应2.
- F o9 I0 {6 P* f4 U/ g4 L. X' A% V% _( D! |
这里的37是指中断向量表中的位置4 `9 ?4 H' ]& N3 s2 d% H
% _$ m' [. \4 m) V
- ^3 S- B% e$ _% n; K0 s2 l1 @- J
, d8 o4 l- ]3 ?( S7 K9 A3 D, h__IO uint32_t ISER[8]; //中断使能寄存器组
' ?" y% \" O* W# E( b6 k% S: q+ f
R7 y/ {& ?3 R7 r32位寄存器,每个位控制一个中断的使能。STM32F40x只有82个可屏蔽中断,所以只使用了其中的ISER[0]~ISER[2]。 ISER[0]的bit0~bit31分别对应中断0~31。ISER[1]的bit0~27对应中断32~63;ISER[2]的bit0~17对应中断64~81; 例如:NVIC->ISER[1] = 1<<(37%32); 6 z, B! k9 V# B1 [6 M
__IO uint32_t ICER[8]; //中断失能寄存器组,配置方法与ISER相同
: Q' @ x) e/ K" s- w. s! ?/ L__IO uint32_t ISPR[8]; //中断挂起寄存器组3 S- x/ u# ?6 M ]
__IO uint32_t ICPR[8]; //中断解挂寄存器组
# {$ h2 `- M& j+ U; Z6 b8 H- l__IO uint32_t IABR[8]; //中断激活标志位寄存器组,只读,为1时,说明中断正在执行。! g: P5 V7 W+ Z0 u- R) [
) X* J6 Y( G3 W; C- N3.3 中断优先级设置步骤 * o* t1 Q% t# u& r4 X$ M
一般情况下,系统代码执行过程中,只执行一次中断优先级分组。* f& x, P) r* l5 y
设置中断优先级分组9 z/ H5 Z& w2 P) p' _
针对每个中断,设置对应的抢占优先级和响应优先级
; o) A/ {/ K' O3 g# R) U3 o: [# I如果需要挂起和解挂,查看中断当前激活状态,分别调用相关函数。& a0 ^+ y3 r- O- ^# n( }) k
. n" Q9 Q. m0 [- }4 a3.4 USART相关的中断事件
: s/ p2 s2 c' p' e! i6 x+ r
) ^9 U' Q" K- r& O. A$ Q
4 ]4 m+ [2 M8 j' Z9 L# T+ H
* `, W3 d) B* V1 {/ Z) T v9 T* Y
$ J6 L: ~/ a# J! X
* I* Y: J \8 D- w1 q( A f; E; `实战演练
2 B8 o% P% q3 A0 _6 j一、设计规划. s7 n+ Z/ W# |4 r( B( r
1.1 实验目标 # a" c9 l2 U0 m2 J2 P3 x* \- |
实现如下功能: STM32F4 通过串口和上位机的对话,STM32F4 在收到上位机发过来的字符串后,原原本本的返回给上位机。& G2 Z2 s: j; l8 B+ j& V
$ y% }) c% f& _: G U, [9 ~. N
1.2 硬件资源" \# C/ t! y6 t8 L! Z$ F* t
(1)指示灯DS0;(2)串口19 u$ X5 e: N8 i/ X# v }0 |
本实验用到了串口1,但PCB上并没有与USB链接,需要使用跳线帽将其硬件连接。
+ q" ~1 ]6 O4 \
& O6 c( e2 f! a2 ^0 M6 I
F7 m3 T+ e. b) r
$ l6 H" K. T( }9 q3 x$ P6 ] m" A! E1 D二、程序设计
# t0 P( c# c. k U( ~' i2.1 建立工程7 L0 N7 m7 V' Q, q
为了更加深入的学习串口的配置,这里单独建立了USART1的配置文件,配置用来学习。! m4 v# \: a- ^
为什么要单独配置,在实际应用串口时,不仅仅只用串口1,但是正点原子只提供了USART1的配置文件,如果不深入只是走马观花而已。. w" G8 k- D! n- J& f$ ?
$ ]/ {$ d* N$ f; G3 ]+ L
t- f" a! t. `5 A
9 P: G% R8 w/ d5 Z0 H3 M2.2 串口配置讲解
1 F8 ]6 w( [1 r/ W8 _3 \! [: v/ g常用的串口相关寄存器:USART_SR(状态)、DR(数据)、BRR(波特率)、CR1~3(控制)
9 F& R! `0 ^! q; G8 ~设置步骤:9 [- l' j# b' h2 E0 w' @
1. 设置中断优先级分组(如果之前没有设置),这个最好一个程序里只在开头设置一次。
% F( {0 F- y0 c$ [2. 使能相关时钟:GPIO(PA9/10)、串口(USART1)。
' d: e, V* [2 ]3. 设置相关GPIO引脚为复用模式【MODE】,引脚的速度,方式。
: j8 { ]5 s) l5. 选择相关GPIO引脚的复用功能(【AFR】映射到USART1)。
& p# {0 _# E6 L3 \$ v3 T$ s6. 设置波特率【BRR】, 设置控制寄存器【CR1~3】。
3 x, w" U$ H9 q( y4 ?4 i n0 |$ b8. 如果要用到中断,设置USART中断优先级,使能USART中断。, g$ e0 p/ d4 v# R+ i/ {9 y4 M
10. 如果要用中断,编写中断服务函数(函数名是固定的)。
, m9 A" z+ y; B! `" _11. 中断服务函数里检查是哪个中断。
* g. |2 N% G0 Y4 a" c12. 编写相应服务程序。5 v+ a5 A) J3 L5 _8 x) l. M2 M
: [$ z. r* a+ E; P: Y; ^: |. T
对以上步骤进行总结:GPIO、USART、中断优先级、串口中断服务函数、主函数
3 @, f. g& l$ L) Z1 [1 L2 ?usart1.h
/ y4 |" ], q: X: R. ]" I- #ifndef __USART1_H$ z( P% {, X' k, W0 f! z
- #define __USART1_H 8 K f# @4 W% |7 ^" K3 u' k0 x& x
- #include "sys.h"' H7 P d. ]% D4 P/ K7 T7 f1 r8 L
- #include "stdio.h"
: K; C" b+ m8 v0 o7 x! s% l, ~! Q - #define USART1_MAX_REC_LEN 200
m6 r+ ]7 _, \0 \; H6 R( g3 K# r3 M - 4 |! j" ?" U8 h I) G; h
- extern u8 USART1_RX_BUF[USART1_MAX_REC_LEN]; //接收数据缓存区
O5 y' ~( m: b' @5 y - extern u8 RX_data_counter; //接收字节计数器
+ {# z% ^2 K7 N1 G/ X* c* E, m" | - extern u8 RX_stat_fin; //串口接收状态,1接收完成,0接收未完成
% }6 }7 }& E7 s' V6 _ -
; ^% s% A/ |* F5 l8 t# t - void usart1_init(u32 pclk2,u32 bound);
* J9 S3 W- K' O+ o. m8 O( {% w - #endif
复制代码 & P, r0 j4 N7 j. K" P
4 D$ z, f4 e& N: Iusart1.c' b8 z$ l1 E8 s3 b
- #include "usart1.h"
% N a% |7 k7 m8 g) J% g- R - #include "sys.h"! r. z$ j" Z. p6 X+ Y* Y* |
- ) F. M6 g, ? t9 k& d) v/ o: L
- u8 USART1_RX_BUF[USART1_MAX_REC_LEN];
8 p: P. W$ K, U4 s2 ?: f; a - u8 RX_data_counter=0;
' g7 d: \' ^+ z8 m8 [# \3 c0 h - u8 RX_stat_fin=0;
! s* ]" p0 t* U& w& v8 t - //USART1中断服务函数
5 q7 x# a: z4 q0 ^ - void USART1_IRQHandler(void)
% k- |1 a$ [0 B$ i, _ - {
. U# }' _8 q# z& T4 G - if(USART1->SR & (1<<5)) //判断是否接收完成1 \! E3 W* x2 _" m, H
- {
& ?* n) Q4 ^6 S2 K - USART1_RX_BUF[RX_data_counter] = USART1->DR;
; e/ N# @& H/ l b# c - RX_data_counter++;
6 x: G7 ^$ y0 n& ^8 g, w$ h2 m, b5 _ - if(USART1_RX_BUF[RX_data_counter-1] == 0X0D) //0X0D:结束标志,'\r'回车键 '\n'/ w4 n% \9 X& E9 `7 |2 b
- {
7 c; E; n7 F; u" F$ S! F - RX_data_counter = 0;. G3 f3 j) [4 Y- a7 A+ u+ P
- USART1->CR1 &= ~(1<<5); //清除中断使能, }4 [2 J! Y7 P. e
- RX_stat_fin = 1; //接收完成标志
. m2 |! D1 E0 d' V7 |' t, G - }
. z9 l( ?/ L; t& J - }
3 g, J3 I- D! P2 L6 p# U9 ~6 Q% c0 Z - }
: {) E. k4 T$ g y - , }1 w- h+ e- |& ^2 v
- //串口1初始化:pclk2:APB2的时钟 84M bound:波特率 115200+ h+ T" W/ ^4 r) O) A; U1 W. G
- void usart1_init(u32 pclk2,u32 bound)7 _0 ]& m8 g* m. g1 i
- {
2 a! B/ U5 ~3 A/ F/ U - //求除波特率对用的BRR相关位的值. i3 O% @/ E' d8 n8 m2 w/ Z
- float temp;7 U5 p1 F' E5 D4 ]* H
- u16 mantissa;
. q9 [& L# u5 w' [' n - u16 fraction;
6 `! O# a0 y, h0 Z H - temp=(float)(pclk2*1000000)/(bound*16);% m( t/ b9 I8 I
- mantissa=temp; 3 e' S: c1 T5 `* \
- fraction=(temp-mantissa)*16;
8 b5 ]- G6 |$ G J7 q' Q4 K; h/ N - mantissa<<=4;
' J9 A/ k: i. O, {) J& [/ E& G9 f9 b - mantissa+=fraction; " W! H; d0 ~5 u. i" R+ |( N
- //时钟使能
0 d8 M- D k0 k8 x- ?( K - RCC->AHB1ENR |= 1<<0; //GPIOA+ g6 Q) ?7 h& C* b/ ~
- RCC->APB2ENR |= 1<<4; //USART1 " J# {$ ~% \2 R: S2 ?
- //GPIO: AF PP 50M PU
2 D2 O7 `) W" ~8 B' l - GPIOA->MODER &= 0XFFC3FFFF;
1 L3 w0 ^5 u- F9 R; ~" v) \" @1 P) M/ i - GPIOA->MODER |= 0X00280000; //PA9/10 AF
E6 i* C- k6 j# W' S2 I' T - GPIOA->OSPEEDR &= 0XFFC3FFFF;4 k' r. ~, q/ ?0 W
- GPIOA->OSPEEDR |= 0X00280000; //PA9/10 50M
# b `' ~! F, ~) |5 m; v - GPIOA->PUPDR &= 0XFFC3FFFF;: G& H) w2 o: v& u q) x- D
- GPIOA->PUPDR |= 0X00140000; //PA9/10 PU
- ?" ~' x7 a9 ` - //GPIOA->AF(USART1)& [7 ?( {5 z' M7 `, m: P* y- g
- GPIOA->AFR[1] &= 0XFFFFF00F;
3 N8 ?$ ^5 ?. B - GPIOA->AFR[1] |= 0X00000770;: m& K4 \' ^; G% c
- //波特率寄存器设置
) L3 f( Z( Z8 }# \3 h; v3 J - USART1->BRR=mantissa;
9 Q3 ^/ c3 M0 z - USART1->CR1&=~(1<<15);
+ F0 C* T' S* L - //USART1控制6 C# C' I4 D! S- l7 M1 d
- USART1->CR1 |= 1<<3; //串口发送使能
# C* U# ~& N" D - USART1->CR1 |= 1<<2; //串口接收使能3 e) Y+ h$ ?; o2 e, Q; g
- USART1->CR1 |= 1<<5; //接收缓冲区非空中断使能,ORE=1或RXNE=1时,自动置为,生成中断
4 U9 i0 g% Z b9 ? - USART1->CR1 |= 1<<13; //串口使能' u1 m! K4 e6 H. N6 S; P9 x Z
- //中断优先级设置,这里未进行分组,将分组放到了主函数(分组最好只分一次)+ x8 ]1 m9 V; J" ]5 V
- NVIC->IP[37] = 0xf0; //相关寄存器配置请参考前面的理论学习部分; E7 O- `7 j! |9 t0 z
- NVIC->ISER[1] = 1<<(37%32); - c1 C' I# b5 n& M
-
0 v& y' J* u2 L8 d; u9 ~4 N v% `3 e! ?6 U -
复制代码 % x: u. G- K( n
这里注意时钟的使能:RCC->APB2ENR |= 1<<4; //USART1 ,外设是挂在再APB总线上。 R) ]& e; G5 w% o' a# h
! ^& k2 {3 A5 z) u6 X* Z
而不是AHB2ENR |= 1<<4,如过这里出错将无法往寄存器中写值。
& T' c9 d+ {* k- p( o. N) O% H' H( |1 e ~
" @+ J! z; a; ]( _$ ~) {' v
2.3 主函数text.c. r7 f( y% c8 |1 a( m* \
此时已经将串口配置完成,也声明了接收数据的变量。要将接收到的数据发送回去,就需要在主函数中进行发送即,将接收的数据重新写入到串口的DR寄存器中即可。& Y) M8 Q! x6 l/ k" w' c
7 I7 G# |: e; K9 I a( ]5 C这里说一下数据格式:串口中断服务函数,在接收数据时判断是否有回车键作为接收完成标志, //0X0D:结束标志,'\r'回车键 (在调试的时候会观察数据)。
; @3 }0 `9 s1 B# G3 }: h- #include "sys.h"+ O" @3 y7 w0 D9 B; v4 |0 k
- #include "delay.h"5 H) K6 }% r- t1 J: s7 g
- #include "usart1.h"
0 \* H5 s( C0 _% W - #include "led.h"
/ C3 z, h- @- S' u2 g1 K -
5 S" c3 N0 N m - int main(void)
" L5 V* l$ W+ V" E" f: H0 }8 g7 V - {
1 R8 w5 q: M! y8 g0 { - char TX_data_counter = 0; //发送计数器
8 w* f& p+ S! y - Stm32_Clock_Init(336,8,2,7);
$ s7 [6 e3 u/ C8 R5 G; d! G: { - delay_init(168); # G( z) ~% H) q
- SCB->AIRCR |= 0X05FA0000 | 0x500; //在这里设置中断组号
/ S! ]( i" u4 M. h1 B" Y7 t5 | - usart1_init(84,115200); ) B( C9 R: _4 h9 G# V
- LED_Init();3 u' @) k4 o$ K3 b0 b8 Q6 t
- 3 j: a- [; M9 o, X- `
- while(1)
; s- s# m2 A2 a5 M4 k$ s. Z - {
% b/ A$ t! Y% G) B* p - if(RX_stat_fin)# z: c/ T( D$ {* Y4 Y3 A2 y
- {5 \, H, O/ g, R# E8 u
- LED0 = 1;& P! ?* t3 k" _; Q$ D' h6 ?9 W1 T" d
- LED1 = 0; //嵌入式发送指示灯! d7 a6 O( G, G
- delay_ms(10); % P7 S, J2 H) \: D0 j
- //for(j=0;j<strlen((char*)USART3_RX_BUF);j++) //另一种判断数据发送结束方法* t, {& T& l5 w: d+ k }' ?/ A
- if(USART1->SR & (1<<7))
/ q& g8 d, ?- n' S2 [) k+ j% z9 a - {
1 q% z: X) ?" c - USART1->DR = USART1_RX_BUF[TX_data_counter];
; Q$ L! \2 v% e) P' l1 B - TX_data_counter++;
3 ?1 ?. ^! h' u$ s- V& | - if(USART1_RX_BUF[TX_data_counter] == '\r') //将回车键'r'传回
4 E2 `1 _1 V. o ^2 @ - {
4 f p1 L( M8 J1 k% m1 n - USART1->DR = USART1_RX_BUF[TX_data_counter];
G# [4 ^. u0 w8 W8 m4 l+ a' e) } - TX_data_counter = 0;8 |/ x$ j6 L# Q8 Y( z& W
- USART1->CR1 |= 1<<5;
3 I* m, O' m8 i) D& ?' x, b! t# r. v - RX_stat_fin = 0;: F9 a. B- x) f9 z; L# n6 u
- }
" a/ \0 r. M a7 w, L - } ; i( w( o/ ~# Y3 C* ^; K+ G. K3 @
- }5 o! {+ U" E: b
- else0 R6 ?& Z% ?* g
- {
% |0 \4 E" o# o! o, A1 V - LED0=0;
+ M8 I6 d: c2 B Q) } - LED1=1;, {, \3 M& j6 f
- }
, u3 z8 D4 Y" v- J - }
) J6 _% C. R9 } - }
复制代码 # O$ _- b. O8 w1 l& ]
三、在线调试$ b) {7 T" p, V
下载完成完成后,打开调试,点击运行,并调出RCC、GPIOA、USART1相关的寄存器,,添加变量USART1_RX_BUF观察接收的数据。1 N& d2 S' H S
5 ]9 C; e3 f0 V# S
- x4 H0 p6 \' `
4 h/ n" B f* A( s$ u4 [9 l- Q+ D 在串口初始化函数处打断点,并进入函数观察寄存器的变化,点击# U; X2 B b& [9 s$ p
6 r0 |5 H7 w7 L' T7 q( h# e7 d
2 U* G# @9 J M X+ s/ {1 Q4 W" a1 H1 Z7 k
点击进入串口初始化函数内部,并在函数内部结束处打一个断点观察寄存器的变化。: o1 t; r1 L6 q
3 \# r8 a0 Z5 P- }1 f r
1 b! u* K7 Q7 s7 B1 g& e% R4 i; k( M
时钟响应的位已经使能:, Z3 M- x3 O" J/ a: ~" e0 ~* `- j' g
) H% J/ m3 N. \ Q3 q6 f: Y! S
} R- w9 y1 z7 h S
: ]; T9 g9 X l( F3 |/ Y n5 W根据GPIOA相关位配置对照,也并无问题:
$ d# z7 D2 Q1 \7 c
; L5 f6 |. M( |, l/ W
% H* o* G! B n% T1 n% q3 k
`$ y9 H5 d4 [& X串口USART1相关的寄存器配置也并无问题:
3 I- p7 m; v" x5 ^& r2 w
3 M Y- }2 l' T4 s! \- H
+ n5 X4 j; B& H* `0 R0 ]. b. d
. H) [* n+ m2 E: O. V. c
观察接收变量:地址 名称 值
1 \ w6 K" M! D3 z) Y4 L
1 M0 q8 b; X* c9 P, k% [4 O
. K! v0 P& |& ~& [5 n# }
- Q0 |9 i1 O! y0 u2 n/ x8 V: T当打开串口调试助手向单片机发送4256可以观察到接收变量其值的变化
. h: K G6 C* U
. Z" Q+ i4 J# Z' `- M/ w0 M+ n
+ I7 a! D$ a5 n0 u8 y4 i* s
$ i# b q' s( H4 R M( k0 ^, `) t- T8 s, I1 f四、上板验证5 D. s+ v9 f% N5 [* E J( R! M
将程序编译并下载到开发板中
+ [, R1 N6 o* W8 d0 w) j
/ h% T) B6 I6 w: G
' n' M8 O/ |6 |2 J) n
9 M) W8 U7 m3 Q. Z7 G
打开串口调试助手4 f, s0 W! O( u% A3 b
/ V& Z% F& d; X7 V4 X
3 B' }* _( j3 [8 |3 C1 E
. ^3 u( G, z$ |5 b( L0 F3 q; R 向从串口调试助手向开发板发送4256,其也会返回4256的值。
! d# s( D$ B% B! u" _& u
6 ~+ a% R+ F- c+ L; w3 Z1 w8 W同时在串口助手向开发板发送数据时,也出出现DS0和DS1闪烁的现象。DS0常量表示静默状态(既不发送,也不接收)) W# E9 q w. z, {5 P- C: w) z' k
————————————————
+ n8 N6 S0 s) D8 M2 ^. j版权声明:追逐者-桥: Q( [. W9 W; W+ d( S' Z" W
如有侵权请联系删除! w2 H5 f# ~; {/ q/ |* r- \3 I5 f
( u; q. h. i0 A; j8 o( ~
|