EDA365电子论坛网

标题: ARM7串口编程要点 [打印本页]

作者: zxcvbvbnmn    时间: 2021-6-22 14:32
标题: ARM7串口编程要点
一. 串口编程的硬件原理/ }3 k7 Q( [  u! h* o
1. 串口特性:7 H4 s8 T& l% c( r: W
1>16字节接收FIFO和16字节发送FIFO
7 `* d+ w( p* ?2>接收FIFO触发点可设置为1,4,8或14字节。4 i- c) n7 {* U& Z& X% d
3>内置波特率发生器。) X& y: o8 x( M; `  c6 F
2. UART0引脚:- g- V: O/ s& V
1>RxD0 引脚用于UART0接受数据,接受方式为串行输入。
: S6 F$ Q; R/ F2>TxD0引脚用于UART0发送数据,发送方式为串行发送数据。5 Y( N& S8 f0 Q6 }) {: m) z; F
3. UART0的结构和工作方式' U- K* z1 L* t/ G3 N5 x
先看图在说明:
+ L9 k6 p" h6 g* Q3 v$ p
5 _. H) z: Z3 `) N& Y
1> VPB总线提供CPU与UART0之间得的通信连接
8 J% L+ N' J; X/ \7 U# B(CPU内核通过VPB接口对UART0的寄存器进行读写访问.)
" z4 ]  ?& D+ G3 P# E8 H, ^, W2> UART0 接收器模块监视串行输入线RxD0的有效输入。UART0 接收单元的移位寄存器(U0RSR)通过RxD0接收有效的字符。当U0RSR接受到一个有效字符时,它将该字符传送到UART0 接收单元缓冲寄存器FIFO中,等待CPU通过VPB接口进行访问。& R  l# w, S, X9 t
3> UART0发送器模块接收CPU或主机写入的数据并将数据缓存到UART0 的FIFO或U0THR中,UART0发送模块中的移位寄存器(U0TSR)读取U0THR或FIFO中的数据并将数据通过串行输出到引脚TxD0发送。9 K, u0 ^2 W" w
4> UART0的接收模块和发送模块的状态信息保存在U0LSR中。
3 I& q. M! m: [; m: H; w控制信息保存在U0LCR中。
! [/ p. o+ s& F) G4 z% Q# P5> UART0波特率发送器模块产生UART0 发送模块所使用的定时。波特率发生器模块时钟源为VPB时钟(pclk)。主时钟与U0DLL和U0DLM寄存器所定义的除数相除得到UART0 发送器模块使用的时钟,该时钟必须为波特率的16倍。
( J' B( y; O% G5 A6> 中断接口包含寄存器U0IER和U0IIR。中断接口接收UART0发送模块和接收模块发出的单时钟宽度的使能信号。5 L" c! i  `4 ~. h: [* g, }
4. UART0和ARM7 CPU之间的通信过程8 t& ]6 P8 D8 \7 o
1>CPU通过UART0发送模块发送信息给外设8 Y; W$ x( ~4 {4 ~
l CPU发出信息通过AHB总线到AHB-VPB桥  N3 v: {& s& U; p0 o
l 通过AHB-VPB桥把信息转换后发送给VPB总线。
3 ^1 I0 b0 U3 b  U( A7 w+ Pl UART0接收模块接受来自VPB总线的数据。并将数据缓存到U0THR寄存器中。
& N8 o6 N9 H2 wl UART0接受模块的移位寄存器U0TSR读取U0THR中的数据 并将数据通过输出引脚TxD0发送
. e* s) t8 d3 A) P

, N4 N+ p# s3 t* R( i* y2>外设通过UART0接收模块向ARM7 CPU发送信息
* |  u3 `5 c* h# z0 ml UART0移位寄存器(U0RSR)通过引脚RxD0接收有效字符。
' ^: \. D+ @/ _' h) n. Wl 当UART0接收到一个有效字符后,通过读取U0RBR寄存器可以将FIFO中最早接收到的字节读出,当FIFO中不再包含有效数据时,该寄存器反映接收到的最后一个有效字节数据。接收的数据不足8位时,高位用0填充。! v: S  V) s  w: O1 I
l VPB总线将缓冲寄存器(U0RBR)中的数据通过AHB-VPB桥传到AHB总线上
% v1 |1 u9 _; w7 ~6 Q3 F! E( \$ Fl AHB总线将数据传送给ARM7 CPU% X9 M9 q" _5 b7 A/ _% M

8 G& i8 r8 F4 t+ |二. 轮训方式的串口编程
: {1 I6 P' K- d; V  V1. 串口程序都有那几部分组成
. A" J: e, _% q1 H/ |5 ~" R看图:: h. j/ N' m! I! Z" N% I

  r' p  B" i" @; f) b# t1> 串口初速化$ B. ~# F6 C8 J3 j* a
A. 串口初始化的流程& {; ^$ w) R& p! ?) H- [
l 设置I/O引脚连接到UART0
5 g- ?4 R- Z" {) I( ^l 设置串口波特率) H. K: s: s8 m/ k
l 设置串口工作模式0 j4 M% n) D1 V  V' n
B. 串口初始化需要设置的寄存器# \; K) x9 F( z: Z3 M4 ~
l U0LCR(控制寄存器):设置UART0的通信格式。
% H) n- ?- J9 bl U0DLL,U0DLM(寄存器):设置UART0的通信波特率。% [/ j3 J) D* ~7 _- ~, ?
C. 具体寄存器的设置/ C( |. l. I. U4 h8 N( p& I/ q
(1) U0LCR(线控制寄存器)8 W  F9 R: u( R2 G7 H: |0 r
l 作用:设置通信格式(通信字符长度,停止位个数,奇偶校验位
( w2 u7 i( h8 C7 sl 长度:8位寄存器6 v! Q; a# o/ M; v- I3 |2 _
l 各位寄存器的含义:
8 O: s  U4 @1 q2 j8 o" C第[1 ,0]位: 表示字长) X. Z# o& _0 `- M! a
00:表示5位字长
7 o; ]+ t+ g& L+ K5 g+ x+ V8 Z01:表示6位字符长度8 M9 M3 x, T) q# \, `4 ~
10:表示7位字符长度0 V1 b' V: w: V0 C* D
11:表示8位字符长度1 s4 P7 |5 R4 ?; X& x6 O1 M3 r
第2位: 表示停止位选择
/ k# j  W- L8 h7 w$ x$ N; x0 y, }0:1个停止位
/ w' F- H/ p; j7 C8 c( s2 _1:2个停止位0 X+ V, s8 G+ j
3位:表示奇偶使能
" M- h4 Y( R$ n* _0:禁止奇偶产生和校验  ?) J) e. r3 ]9 P% Z
1:使能奇偶产生和校验
$ f! C$ S& t- F4 Y* G8 n注:奇偶使能:控制是否进行奇偶校验。如果使能,发送时将添加一位校验位。1 H6 I& v$ S# P  p2 D( }
第[5 4]位:表示奇偶选择位, E$ x3 S; }8 n. @: E+ n$ T
00:奇数(数据位+校验位=奇数)
* l# w+ F) ~0 i' M01:偶数(数据位+校验位=偶数)
$ E& L% c, |- L9 W10:校验位强制为1
# U# |# ?1 N6 K" m/ d9 Q# ]" J. c0 k11:校验位强制为06 J0 x) I! [1 w6 E
注:奇偶选择主要是设置奇偶校验类型。
7 Z& Z3 q: a; U! E第6位:间隔控制: _' ?. ]: }0 O2 c4 g
0:禁止间隔发送- O0 L7 g7 y  G9 _
1:使能间隔发送) x" R& o* y4 ^3 u+ h
注:当该位为1时,输出引脚(TxD0)强制为逻辑0,可以引起通信对方产生间隔中断。在一些通信方式中,使用间隔中断作为通信的起始信号(egIN Bus)
. t4 S6 s, w8 g第7位:除数锁存访问位
1 `+ Y( E7 g# o! z0:禁止访问除数锁存寄存器
8 }( v, w! B, b" M1:始能访问除数锁存寄存器
9 S; d/ @. P6 B: R( @( ?
( R4 y" V/ a6 w. h& z3 C" ~
(2) U0DLL,U0DLM(除数锁存寄存器)
- a0 y+ Q( E! X4 a6 p& {l 作用:U0DLL和U0DLM寄存器一起构成一个16位除数。
; |  k2 U% I$ E+ i; |" Dl U0DLL和U0DLM都为8位寄存器。; V6 C! H0 s% Y6 {0 s* G9 u9 Q. _
l U0DLL:存放分频值的低8位' H) j; f7 t$ N& U9 p! B, H' ]$ x
l U0DLM:存放分频值的高8位。
: Y, I3 s! F# v1 J) Q注:
& n# @/ O2 d) n, F0 L+ r9 s# z! rØ 1.使用U0DLL和U0DLM配置波特率之前,必须先计算分频值。
- W4 f  r# x6 R7 c  |% qFdiv=Fpclk/(16*baud); E. ~+ ^! H8 G& h  M/ O0 X# y
Ø 2.使用U0DLL和U0DLM配置波特率之前必须把U0LCR控制寄存器的第8位置为1才能进行配置。配置完后要把U0LCR控制寄存器的第8位置位0。
, k/ ~- s* l: w2> 串口初始化化程序3 ?; E; S! @" `5 v  @
A方法一:
$ R7 c% S. e0 l1 c$ B8 z  F5 W# W' G( ~
void UART0_Init(uint32 bps)
3 @  P& x0 |* |* e4 q{
3 F' T2 t9 N" }. v; v$ X+ s9 }7 d4 q4 l7 L7 ~3 U
uint16 Fdiv;3 @" p* b: G! \0 O
PINSEL0=0x00000005; //设置串口引脚
  k3 Q+ I* G6 `4 \U0LCR=0x83; //置为除数锁存位,进行配置% _, z8 _) ~6 R5 \6 V
Fdiv=(Fpclk>>4)/UART0_BPS;/ [/ i; L4 m/ c5 G0 }) C5 J" b
U0DLM=Fdiv>>8;
+ r: f- X9 ~. SU0DLL=Fdiv&0xff;7 |2 u- d. x. w6 I4 t( I* o' |
U0LCR=0x03; //清除除数锁存位,并设置工作模式
9 T, z8 p6 y+ z2 d}* w+ P# Y1 B# V# g
B.方法二:
- a+ x4 T& z4 n% l$ s; a/ J* J8 m' f: T* e

2 I. K* l8 r% ~3 btypedef struct UartMode+ ]  }! g+ _# X+ B+ ?1 I
{ uint8 datab; // 字长度,5/6/7/8
) F0 s, ^4 h" H$ |1 Euint8 stopb; // 停止位,1/2
+ v0 ?0 t# G5 z+ v; l3 C4 Q; |uint8 parity; // 奇偶校验位,0为无校验,1奇数校验,2为偶数校验3 t2 U, Y/ b/ t: {) \& i8 c
} UARTMODE;* [! D5 ^" T- f/ a1 Y: m
uint8 UART0_Init(uint32 baud, UARTMODE set)
* @3 q- N0 x; j  J  V6 H{ uint32 bak;" ^8 ^0 A5 s( N) N6 b

, x4 |3 u% P) v, [4 W8 b/ B2 F2 f5 b* P# g/ F% Q% l
if( (0==baud)||(baud>115200) )" L* S# N( @) Q
{
3 u* q+ M2 |! U# Y* A4 {return(0);
9 m( C, ^6 |& |# w% ^9 y}
$ r  R' K+ l) V  Sif( (set.datab<5)||(set.datab>8) )
) n# Q- f% H: R; C8 e# H3 M{" E9 c% t% z/ k) e
return(0);
  W3 d/ t5 k# j) Q* J6 n}
9 K5 u( Y) p* T  b& F1 \4 Aif( (0==set.stopb)||(set.stopb>2) )) v9 c! x0 Y+ L
{
( M0 E  F& H. A9 l. P4 K; O' _return(0);
0 U+ \0 a& ~3 R}
7 e% R7 t8 t7 _2 o: d. M* Kif( set.parity>4 )
8 c/ ~0 r5 N  ^$ K5 m0 [{
4 p, z1 `( e1 u* q. f4 G: ?return(0);
1 Y0 H5 S' Y$ u" r* F( V0 X}
3 {# _, y+ d) l
3 k4 e3 z: c, w$ L4 E" F5 Y" v: l
作者: nevadaooo    时间: 2021-6-22 15:36
VPB总线提供CPU与UART0之间得的通信连接
作者: shapeofyou888    时间: 2021-6-22 17:22
RxD0 引脚用于UART0接受数据,接受方式为串行输入。
作者: shapeofyou888    时间: 2021-6-22 17:23
TxD0引脚用于UART0发送数据,发送方式为串行发送数据




欢迎光临 EDA365电子论坛网 (https://bbs.eda365.com/) Powered by Discuz! X3.2