串口(Serial UART), 全称是通用异步收发口universal asynchronous receiver/transmitter.
主要用于计算机之间的串行通信任务。UART主要完成时序和奇偶校验等功能。而在通信时
需要附加的设备是TTL电平与RS232电平的转换设备。
对于TTL电平,规定+5V为逻辑“1”, 0V为逻辑“0”
对于RS232电平,规定+3V到+12V为逻辑“1”, -12V到-3V为逻辑"0"
当要使用UART进行通信之前,通常要对UART的相关寄存器进行正确的配置,才能进行正常的通信。
可能大家都有过在单片机或者ARM,DSP上使用串口的经历。串口配置起来的确简单,好用。但我这里要写的主要是针对PC机上的串口寄存器配置。如果是要在ARM或者是单片机上使用串口,可能下面要讲到的寄存器会不适用。不过大致的原理却是一致的。
我们知道,串口都有相应的接收寄存器和发送寄存器,当有数据到来的时候,我们可以从接收寄存器中去读取,当要发送数据的时候,我们会向发送寄存器写数据,然后剩下来的一切就交给硬件去做吧。当然,在我们能进行正常的读写之前,有一点很重要,就是要配置好波特率,也就是说发送方和接收方的波特率必须要保持一致,不然就算是你能收到数据,到时候也只是一堆乱码而已。
对于编程而言,串口的工作模式有两种:
第一种是查询模式,也就是CPU不停地检测接收寄存器,看有没有数据到达
第二种是中断模式,CPU可以去做别的事,有数据到的时候会有相应的中断,然后CPU再跳转过去处理数据。
这两种模式可以根据实际的情况来使用,在此不细说。
还是回到讲PC的串口的寄存器的主题上来:
在PC上,串口的寄存器是要占用相应的IO空间的,也就是说我们可以通过向相应的IO口写值来改变寄存器的配置。如表1-1所示:
Default I/O addresses and IRQ's on a PC system |
||
COM1 |
0x3F8 - 0x3FF |
4 |
COM2 |
0x2F8 - 0x2FF |
3 |
COM3 |
0x3E8 - 0x3EF |
4 |
COM4 |
0x2E8 - 0x2EF |
3 |
上面这张表是默认的串口默认使用的I/O地址和中断向量号,在一些特定的系统上,这些值有可能会变动。
接下来要讲的是串口所使用的寄存器了。
对于每一个UART来说,有8个字节的I/O用于其寄存器的访问。如表1-2所示:表中的DLAB是LCR寄存器的Bit7,位于base+3处。
UART register to port conversion table |
||||
|
DLAB = 0 |
DLAB = 1 |
||
I/O port |
Read |
Write |
Read |
Write |
base |
RBR |
THR |
DLL divisor latch LSB |
|
base + 1 |
IER |
IER |
DLM divisor latch MSB |
|
base + 2 |
IIR |
FCR |
IIR |
FCR |
base + 3 |
LCR line control |
|||
base + 4 |
MCR modem control |
|||
base + 5 |
LSR |
– |
LSR |
– |
base + 6 |
MSR |
– |
MSR |
– |
base + 7 |
SCR scratch |
下面将详细地介绍每一个寄存器。
RBR在FIFO未开启的时候,只包含当前接收到的一个Byte。当FIFO被启用的时候,每一次的读操作都会返回FIFO头部的一个数据,直到FIFO空为止。当FIFO为空时LSR的Bit 0会由1变为0。
THR主要用于缓冲输出数据,当FIFO未被启用的时候,只能缓冲一个Byte的数据,当FIFO启用时,可以缓冲多个Byte的数据,当LSR的Bit 1为“1”时表示缓冲器为空,此时可以写入数据,但是没有一个寄存器可以表示当前FIFO中的有效数据个数。
IER是中断使能寄存器,在使用串口通信时使用中断方式无疑是高效的。使用中断可以不必定时地去查询寄存器的状态,UART会自动地向处理器发起中断信号。除非UART被配置成中断模式,否则中断是不会自动产生的。
IER : Interrupt enable register |
|
Bit |
Description |
0 |
Received data available |
1 |
Transmitter holding register empty |
2 |
Receiver line status register change |
3 |
Modem status register change |
4 |
Sleep mode (16750 only) |
5 |
Low power mode (16750 only) |
6 |
reserved |
7 |
当UART的状态改变的时候会产生中断,但具体是哪种状态的改变产生的中断呢?如果软件在中断产生时想要识别当前的状态改变信息,如何办呢?这个时候,IIR就派上用场了。
IIR : Interrupt identification register |
|||||
Bit |
Value |
Description |
Reset by |
||
0 |
0 |
Interrupt pending |
– |
||
1 |
No interrupt pending |
– |
|||
1,2,3 |
Bit 3 |
Bit 2 |
Bit 1 |
|
|
0 |
0 |
0 |
Modem status change |
MSR read |
|
0 |
0 |
1 |
Transmitter holding register empty |
IIR read or THR write |
|
0 |
1 |
0 |
Received data available |
RBR read |
|
0 |
1 |
1 |
Line status change |
LSR read |
|
1 |
1 |
0 |
Character timeout (16550) |
RBR read |
|
4 |
0 |
Reserved |
– |
||
5 |
0 |
Reserved (8250, 16450, 16550) |
– |
||
1 |
64 byte FIFO enabled (16750) |
– |
|||
6,7 |
Bit 7 |
Bit 6 |
|
|
|
0 |
0 |
No FIFO |
– |
||
1 |
0 |
Unusable FIFO (16550 only) |
– |
||
1 |
1 |
FIFO enabled |
– |
FCR主要用于控制UART的FIFO动作。
FCR : FIFO control register |
|||
Bit |
Value |
Description |
|
0 |
0 |
Disable FIFO's |
|
1 |
Enable FIFO's |
||
1 |
0 |
– |
|
1 |
Clear receive FIFO |
||
2 |
0 |
– |
|
1 |
Clear transmit FIFO |
||
3 |
0 |
Select DMA mode 0 |
|
1 |
Select DMA mode 1 |
||
4 |
0 |
Reserved |
|
5 |
0 |
Reserved (8250, 16450, 16550) |
|
1 |
Enable 64 byte FIFO (16750) |
||
6,7 |
Bit 7 |
Bit 6 |
Receive FIFO interrupt trigger level |
0 |
0 |
1 byte |
|
0 |
1 |
4 bytes |
|
1 |
0 |
8 bytes |
|
1 |
1 |
14 bytes |
LCR,线控寄存器,主要用于配置stop bit的位数,奇偶校验以及DLL和DLM寄存器的可访问性。DLL和DLM这些寄存器与RBR, THR和IER寄存器一样被映射同样的IO口上。它们只有在串口初始化的时候才会被配置。
常用的串口配置有:
l 8个数据位,1个停止位,无奇偶校验
l 7个数据位,1个停止位,偶校验
LCR : line control register |
||||
Bit |
Value |
Description |
||
0,1 |
Bit 1 |
Bit 0 |
Data word length |
|
0 |
0 |
5 bits |
||
0 |
1 |
6 bits |
||
1 |
0 |
7 bits |
||
1 |
1 |
8 bits |
||
2 |
0 |
1 stop bit |
||
1 |
1.5 stop bits (5 bits word) |
|||
3,4,5 |
Bit 5 |
Bit 4 |
Bit 3 |
|
x |
x |
0 |
No parity |
|
0 |
0 |
1 |
Odd parity |
|
0 |
1 |
1 |
Even parity |
|
1 |
0 |
1 |
High parity (stick) |
|
1 |
1 |
1 |
Low parity (stick) |
|
6 |
0 |
Break signal disabled |
||
1 |
Break signal enabled |
|||
7 |
0 |
DLAB : RBR, THR and IER accessible |
||
1 |
MCR主要用于控制Modem。这个不多说。
MCR : Modem control register |
|
Bit |
Description |
0 |
Data terminal ready |
1 |
Request to send |
2 |
Auxiliary output 1 |
3 |
Auxiliary output 2 |
4 |
Loopback mode |
5 |
Autoflow control (16750 only) |
6 |
Reserved |
7 |
Reserved |
LSR这个寄存器很有用,它作为状态寄存器反映了当前通信的状态。
LSR : Line status register |
|
Bit |
Description |
0 |
Data available |
1 |
Overrun error |
2 |
Parity error |
3 |
Framing error |
4 |
Break signal received |
5 |
THR is empty |
6 |
THR is empty, and line is idle |
7 |
Errornous data in FIFO |
其中bit 0用于接收数据状态,bit 5用于发送数据状态。
MSR反映了Modem的状态信息,这个也不多说。
MSR : Modem status register |
|
Bit |
Description |
0 |
change in Clear to send |
1 |
change in Data set ready |
2 |
trailing edge Ring indicator |
3 |
change in Carrier detect |
4 |
Clear to send |
5 |
Data set ready |
6 |
Ring indicator |
7 |
Carrier detect |
这个寄存器也用得很少,在此不多讲。
这两个寄存器合起来用于配置分频器,以得到合适的波特率。一般而言,在pc上用于串口通信的晶体的频率为:1.8432MHz。用这个频率除以16后用作串口的最大频率。所以一般串的最大传输速率为:1.8432 * 10^6 / 16= 115200bps。但有的modem使用24MHz的晶体作为初始频率,因此最大的传输速率可以达到1.5Mbps。
DLL and DLM : Divisor latch registers |
|||
Speed (bps) |
Divisor |
DLL |
DLM |
50 |
2,304 |
0x00 |
0x09 |
300 |
384 |
0x80 |
0x01 |
1,200 |
96 |
0x60 |
0x00 |
2,400 |
48 |
0x30 |
0x00 |
4,800 |
24 |
0x18 |
0x00 |
9,600 |
12 |
0x0C |
0x00 |
19,200 |
6 |
0x06 |
0x00 |
38,400 |
3 |
0x03 |
0x00 |
57,600 |
2 |
0x02 |
0x00 |
115,200 |
1 |
0x01 |
0x00 |