|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
一. 串口编程的硬件原理
4 w# \* i M, c' n$ n9 t9 M- i1 ?1. 串口特性:5 M( t. P! l' E4 S3 _' r
1>16字节接收FIFO和16字节发送FIFO
2 q$ Z% `& U" S# I9 ]7 x2>接收FIFO触发点可设置为1,4,8或14字节。1 A- y/ r' ^# @$ S& i1 c" i z' U
3>内置波特率发生器。% ^1 M8 j6 U" V- n+ p
2. UART0引脚:
$ M8 K8 v+ o5 S& {, T% [1>RxD0 引脚用于UART0接受数据,接受方式为串行输入。
7 j' m" @, @6 U* b ^2>TxD0引脚用于UART0发送数据,发送方式为串行发送数据。
- ]9 w f8 e. L7 Q( {7 b% F3. UART0的结构和工作方式
: u; a$ P5 q9 r9 t. n4 R3 d n0 w8 B9 E先看图在说明:& @4 L5 @1 l1 g, \ {$ [; {
) d/ D4 j$ R' z- K& a0 G8 r1> VPB总线提供CPU与UART0之间得的通信连接" n9 J* u% {8 g: }% b
(CPU内核通过VPB接口对UART0的寄存器进行读写访问.)- h- d2 x$ r1 m7 P
2> UART0 接收器模块监视串行输入线RxD0的有效输入。UART0 接收单元的移位寄存器(U0RSR)通过RxD0接收有效的字符。当U0RSR接受到一个有效字符时,它将该字符传送到UART0 接收单元缓冲寄存器FIFO中,等待CPU通过VPB接口进行访问。
& f6 m) D1 b; k% X% a3> UART0发送器模块接收CPU或主机写入的数据并将数据缓存到UART0 的FIFO或U0THR中,UART0发送模块中的移位寄存器(U0TSR)读取U0THR或FIFO中的数据并将数据通过串行输出到引脚TxD0发送。
8 b. M# I9 t. r/ q2 Q8 ~4> UART0的接收模块和发送模块的状态信息保存在U0LSR中。. _" R; R& K! ~/ f/ u
控制信息保存在U0LCR中。( }* C! S) X; U4 `$ {
5> UART0波特率发送器模块产生UART0 发送模块所使用的定时。波特率发生器模块时钟源为VPB时钟(pclk)。主时钟与U0DLL和U0DLM寄存器所定义的除数相除得到UART0 发送器模块使用的时钟,该时钟必须为波特率的16倍。
- {) ]9 N+ b7 m+ ]( a6> 中断接口包含寄存器U0IER和U0IIR。中断接口接收UART0发送模块和接收模块发出的单时钟宽度的使能信号。
6 B7 k7 F8 Q1 h9 D9 _4. UART0和ARM7 CPU之间的通信过程& V! P5 r5 A, n- Z
1>CPU通过UART0发送模块发送信息给外设* d: B: ]- y# c2 Z
l CPU发出信息通过AHB总线到AHB-VPB桥8 N7 b, T q* R0 t W& W
l 通过AHB-VPB桥把信息转换后发送给VPB总线。
9 s$ K) T4 ~( El UART0接收模块接受来自VPB总线的数据。并将数据缓存到U0THR寄存器中。
! f* ^. X4 \& ^3 o$ `l UART0接受模块的移位寄存器U0TSR读取U0THR中的数据 并将数据通过输出引脚TxD0发送
5 j8 Y0 I) r U) \1 m8 v' O+ V3 W, _8 V, u) W9 Q& t
2>外设通过UART0接收模块向ARM7 CPU发送信息
* ^( B5 i3 z$ E1 Nl UART0移位寄存器(U0RSR)通过引脚RxD0接收有效字符。
$ H! c* {- `( Z/ w; l0 p) ?; ~l 当UART0接收到一个有效字符后,通过读取U0RBR寄存器可以将FIFO中最早接收到的字节读出,当FIFO中不再包含有效数据时,该寄存器反映接收到的最后一个有效字节数据。接收的数据不足8位时,高位用0填充。0 p1 x) x6 U0 J! N% i% u
l VPB总线将缓冲寄存器(U0RBR)中的数据通过AHB-VPB桥传到AHB总线上3 Y. n1 ^- h5 e
l AHB总线将数据传送给ARM7 CPU
2 t% V; s# ]+ t* @: [9 C6 j1 j M7 h9 a! E6 _% |# o
二. 轮训方式的串口编程
- L0 f) z& E* m5 _# ^( s9 _9 t/ e- m1. 串口程序都有那几部分组成1 O: N2 h/ n: ~' w/ y
看图:; @+ V- F. r. c+ e
8 X) o! ^$ T1 [% K0 P% ~
1> 串口初速化
0 w$ T; q6 z) y4 @; U- I2 HA. 串口初始化的流程
9 i7 K- ~- i& Zl 设置I/O引脚连接到UART0
3 {% [, r8 U1 v3 C. F. {l 设置串口波特率3 M6 i: ]6 C! j8 ^7 o; T q* N
l 设置串口工作模式( _3 }; y7 r* P
B. 串口初始化需要设置的寄存器
% I; R% q9 R6 B4 C j3 E% q# A Nl U0LCR(控制寄存器):设置UART0的通信格式。
2 ^" k0 D9 S9 e# K( z3 dl U0DLL,U0DLM(寄存器):设置UART0的通信波特率。1 G; R1 F a& f/ b7 F5 s
C. 具体寄存器的设置$ x- a' d, G! c
(1) U0LCR(线控制寄存器)0 L- T' C0 `: m/ F/ @' z! \0 E5 n3 m
l 作用:设置通信格式(通信字符长度,停止位个数,奇偶校验位
/ |1 D# L" Z- A9 b5 ?' ?; @l 长度:8位寄存器1 g3 L6 B/ j7 v/ {* i( Z4 s8 x
l 各位寄存器的含义:9 [. ?( I' I, j+ ^5 s* a
第[1 ,0]位: 表示字长
( V6 d" {9 m2 k00:表示5位字长6 L# L6 Q4 I: I) I7 j8 a
01:表示6位字符长度
$ Q0 ~1 r3 @5 u% p. D10:表示7位字符长度/ d% z! H$ |" o& s* ^+ n1 v
11:表示8位字符长度
! g# Q+ v1 g# o: u第2位: 表示停止位选择' v9 ]; s" e+ E0 m
0:1个停止位
5 i7 C9 p$ Z1 B, M" ]7 W- [1:2个停止位
* g" b1 F9 F* H3 X- p- B5 ]3位:表示奇偶使能* P3 j% `4 m5 _# ]
0:禁止奇偶产生和校验* n/ x9 o. e1 c1 w- H1 ]8 D; V
1:使能奇偶产生和校验% n) z7 L1 j2 Q5 E- Y
注:奇偶使能:控制是否进行奇偶校验。如果使能,发送时将添加一位校验位。! ~8 V- L+ m8 p' h
第[5 4]位:表示奇偶选择位- ~1 o) E7 \( e+ |! Z
00:奇数(数据位+校验位=奇数)
) X/ s0 W" E# Y' @+ O2 _; m1 K01:偶数(数据位+校验位=偶数)$ [& |) q8 ^' B2 \4 ^2 ]% u
10:校验位强制为10 ^& m5 @; f* k, q
11:校验位强制为05 T2 h; N& r* _* W. G
注:奇偶选择主要是设置奇偶校验类型。6 R" s4 l- r0 _6 \& e; |. D
第6位:间隔控制- z- p- o3 P/ |1 Q3 P$ n. J& |. B1 t
0:禁止间隔发送
& U! ?- \' G" [7 b4 X1:使能间隔发送0 r: W& Y1 S: o
注:当该位为1时,输出引脚(TxD0)强制为逻辑0,可以引起通信对方产生间隔中断。在一些通信方式中,使用间隔中断作为通信的起始信号(eg IN Bus)4 Z& c/ a$ o" M
第7位:除数锁存访问位$ A P9 y l. h3 L! E3 W) c6 X
0:禁止访问除数锁存寄存器/ c+ `1 f8 C: T
1:始能访问除数锁存寄存器0 J3 P$ ~# ~# I$ |9 {" P
) M6 x" f5 K7 q i0 S( c4 A% f% C
(2) U0DLL,U0DLM(除数锁存寄存器)5 q7 {2 i6 ]( r5 Y) X1 f+ f, s
l 作用:U0DLL和U0DLM寄存器一起构成一个16位除数。- Y8 E- T: N9 k* i& W# T
l U0DLL和U0DLM都为8位寄存器。' L' Q) x& _1 d! D$ O) f5 \
l U0DLL:存放分频值的低8位4 ?# {& j1 \$ N: z3 t
l U0DLM:存放分频值的高8位。- Q9 i; P8 p' q& ]2 w% R T
注:& V( R! U+ G7 ?3 K) ?' G
Ø 1.使用U0DLL和U0DLM配置波特率之前,必须先计算分频值。- z2 u2 X5 d9 c8 l& T" J0 E
Fdiv=Fpclk/(16*baud)! i+ ^, J% U b- O+ x
Ø 2.使用U0DLL和U0DLM配置波特率之前必须把U0LCR控制寄存器的第8位置为1才能进行配置。配置完后要把U0LCR控制寄存器的第8位置位0。
. o$ g# u3 D- W2> 串口初始化化程序
2 _; x) g1 c+ X5 |- r# C* ~A方法一:
* z2 P0 E7 j, r6 k; B6 \* J* ^7 u* q7 Y/ z t4 X& W ~* U
void UART0_Init(uint32 bps)+ S7 `% t# T: J0 ?
{) k4 B& C& J3 s ?
6 X3 Y$ Q# g, o" `
uint16 Fdiv;
8 E% v! W; R1 u6 W2 q3 u8 q! A7 BPINSEL0=0x00000005; //设置串口引脚
& x; K7 p- k. O6 }U0LCR=0x83; //置为除数锁存位,进行配置
6 |" p: o# M: R2 F1 pFdiv=(Fpclk>>4)/UART0_BPS;
; G7 |) E6 N; W$ e! o- k0 `U0DLM=Fdiv>>8;' ?3 ]9 L! w8 }7 e7 Z6 _, J3 D$ F
U0DLL=Fdiv&0xff;
U' c J1 g6 NU0LCR=0x03; //清除除数锁存位,并设置工作模式+ @( w. F5 {: \9 c
}
7 `( t1 ~2 D$ | \9 ^B.方法二:2 B7 m9 t* u7 T5 K, H9 L: e; I( w
" i' b, f$ {4 |- M& v
6 n; u) [ w2 ]0 h' [, Ptypedef struct UartMode
- f# J4 |/ T5 M{ uint8 datab; // 字长度,5/6/7/8
) h. x3 b& j' H9 d$ F8 p5 _* Duint8 stopb; // 停止位,1/2) h2 z7 T! ` i4 l, B ~% \
uint8 parity; // 奇偶校验位,0为无校验,1奇数校验,2为偶数校验) {( I& X$ H2 C) V! q* |' Q! j
} UARTMODE;
( Z( j4 @! Z8 t9 y2 s0 n5 wuint8 UART0_Init(uint32 baud, UARTMODE set), y" G6 A; Q( E% i0 b4 J1 r2 ~& T
{ uint32 bak;
4 M. i% U8 [3 |+ T/ h V8 a
- D r+ X% k4 k3 ^# G- D
( J* z: y# ~' O$ Q0 x! @% kif( (0==baud)||(baud>115200) )
' ^- k) U7 t* W. [& H1 n{( d) _4 w; Y+ ^& c! f
return(0);
. c$ A0 g! B+ D: N- Q4 e6 A}
; L ?! ]( i; a1 Gif( (set.datab<5)||(set.datab>8) )# N) |& i5 J8 {' {
{
7 _+ j0 c" c. b! b1 W( Nreturn(0);
# l. r: L% [ u: S, G}
# L) S- | m: X _: Uif( (0==set.stopb)||(set.stopb>2) )
. L4 `2 c$ X# r% X; s) p8 o{/ @# }0 L* _" N$ F' `7 c
return(0);
7 i& x2 f j( P5 b6 U1 I* [. D- u}
- i' k# y) p0 A+ U4 jif( set.parity>4 )3 u# S6 ]+ g- Q' s: f
{. s3 D" O e- y' n
return(0);
1 C4 Z7 S: C: S}
( v% m6 _) x3 s% [) O
6 c) L% o) J% I' d |
|