การ Interface กับ Serial Port (Part IV)
UART จะมีวงจร Baud rate generator อยู่ภายใน ซึ่งจะเชื่อมโยงกับภาคส่งของ
UART โดยตรง และควบคุมโดยใช้ Crystal แต่ทางด้านภาครับจะต้องต่อจากขา 15 ซึ่งเป็น
Baud output มาเข้าที่ขา 9 ซึ่งเป็น Receiver clock input โดยความถี่ของ Clock
มีค่าเป็น 16 เท่าของ Baud rate สูงสุด ดังนั้นเราจึงมักจะพบ Crystal ที่มีค่าความถี่
1.8432 MHz หรือ 18.432 MHz อยู่บน I/O Card เสมอ
Type of UARTs
Type of UARTS (For PC’s)
UART
|
Note
|
8250
|
First UART in this series. It contains no scratch register. Terminal
speed of 19.2Kbps.
|
8250A
|
This UART is faster than the 8250 on the bus side. Looks exactly the
same to software than 16450.
|
8250B
|
Very similar to that of the 8250 UART.
|
16450
|
Used in AT's (Improved bus speed over 8250's). Operates comfortably
at terminal speed of 38.4Kbps. Still quite common today.
|
16550
|
This was the first generation of buffered UART. It has a 16 byte buffer,
however it doesn't work and is replaced with the 16550A.
|
16550A
|
Is the most common UART use for high speed communications eg. Terminal
speed of 115.2Kbps. They made sure the FIFO buffers worked on this UART.
|
16650 (TL16C650)
|
Very recent breed of UART. Contains a 32 byte FIFO, Programmable Xon
/ Xoff characters and supports power management. Terminal speed of 230.4Kbps.
|
16750 (TL16C750)
|
Produced by Texas Instruments. Contains a 64 byte FIFO.
|
Serial Port Registers
Port Addresses and IRQ’s
Table 3. Standard Port Addresses.
Name
|
Address
|
IRQ
|
COM1
|
3F8
|
4
|
COM2
|
2F8
|
3
|
COM3
|
3E8
|
4
|
COM4
|
2E8
|
3
|
Table 3. แสดง Address และ IRQ ของ Serial Port หรือ COM Port ที่ใช้ในเครื่อง
PC ส่วนใหญ่ แต่ถ้าไม่แน่ใจเราก็สามารถหาข้อมูลเหล่านี้ได้ โดยอ่านจาก BIOS ตาม
Address ที่แสดงใน Table 4. ข้างล่างนี้
Table 4. COM Port Address in
the BIOS Data Area.
Start Address
|
Function
|
0000 : 0400
|
COM1’s Base Address
|
0000 : 0402
|
COM2’s Base Address
|
0000 : 0404
|
COM3’s Base Address
|
0000 : 0406
|
COM4’s Base Address
|
ตัวอย่างต่อไปนี้เป็นตัวอย่าง Program ภาษา C แสดงการอ่านข้อมูล Address ของ COM
Port จาก BIOS Data Area
#include <stdio.h>
#include <dos.h>
void main(void)
{
unsigned int far *ptraddr; /* Pointer to location of Port Addresses */
unsigned int address; /* Address of Port */
int a;
ptraddr=(unsigned int far *)0x00000400;
for (a = 0; a < 4; a++)
{
address = *ptraddr;
if (address == 0)
printf("No port found for COM%d \n",a+1);
else
printf("Address assigned to COM%d is %Xh\n",a+1,address);
*ptraddr++;
}
}
Table of Registers
Table 5. แสดงถึง Address ของ Register ต่าง ๆ
Table 5. Table of Registers.
Base Address
|
DLAB
|
Read / Write
|
Abbr.
|
Register Name
|
+0
|
=0
|
Write
|
-
|
Transmitter Holding Buffer
|
=0
|
Read
|
-
|
Receiver Buffer
|
=1
|
Read / Write
|
-
|
Divisor Latch Low Byte
|
+1
|
=0
|
Read / Write
|
IER
|
Interrupt Enable Register
|
=1
|
Read / Write
|
-
|
Divisor Latch High Byte
|
+2
|
-
|
Read
|
IIR
|
Interrupt Identification Register
|
-
|
Write
|
FCR
|
FIFO Control Register
|
+3
|
-
|
Read / Write
|
LCR
|
Line Control Register
|
+4
|
-
|
Read / Write
|
MCR
|
Modem Control Register
|
+5
|
-
|
Read
|
LSR
|
Line Status Register
|
+6
|
-
|
Read
|
MSR
|
Modem Status Register
|
+7
|
-
|
Read / Write
|
-
|
Scratch Register
|
DLAB?
DLAB ใช้ควบคุม register บางตัวให้สามารถทำหน้าที่ต่างออกไปได้ จึงทำให้ register
ที่มีอยู่จริงเพียง 8 ตัว สมารถทำงานเสมือนว่ามี register อยู่ 12 ตัว DLAB ย่อมาจาก
Divisor Latch Access Bit
เมื่อ DLAB ถูก set ให้มีค่าเป็น 1 โดย set ที่ Line Control Register จะทำให้เราสามารถเข้าถึง
register 2 ตัวที่ทำหน้าที่กำหนด speed ของการสื่อสาร ซึ่งมีหน่วยเป็น bit per
second (bps)
ตัว UART จะมี oscillator ความถี่เป็น 16 เท่าของ speed สูงสุดในการสื่อสาร ถ้าเราต้องการ
speed สูงสุดที่ 115,200 bps ก็ต้องใช้ความถี่ oscillator ที่ 1.8432 MHz และจาก
speed สูงสุดที่ 115,200 bps เมื่อหารต่อไปด้วยค่าตัวหาร 48 ก็จะทำให้ได้ speed
ที่ 2400 bps ซึ่งตัว Baud Rate Generator จะเป็นตัวทำหน้าที่นี้ โดยมี register
2 ตัวทำหน้าที่เก็บค่าตัวหาร (divisor) นี้ ซึ่ง register ทั้ง 2 จะถูกควบคุมโดย
DLAB ค่าของตัวหารสามารถเป็นเท่าใดก็ได้ที่ไม่เกิน 16 bit (0 ถึง 65,535) และเนื่องจาก
UART มี data bus เพียง 8 bit จึงต้องใช้ register 2 ตัว โดยเมื่อ set ค่า DLAB
ให้มีค่าเป็น 1 ตัว register ตัวแรกซึ่งมี address อยู่ที่ base+0 จะเก็บค่า Divisor
Latch Low Byte ส่วน register ตัวที่สองซึ่งมี address อยู่ที่ base+1 จะเก็บค่า
Divisor Latch High Byte Table 6. แสดงถึงค่าตัวหารเป็นเลขฐาน 16 ที่ใช้กันทั่วไป.
Table 6. Commonly Used Baud
rate Divisors.
Speed (bps)
|
Divisor (Dec.)
|
Divisor Latch High Byte
|
Divisor Latch Low Byte
|
50
|
2304
|
09h
|
00h
|
300
|
384
|
01h
|
80h
|
600
|
192
|
00h
|
C0h
|
2400
|
48
|
00h
|
30h
|
4800
|
24
|
00h
|
18h
|
9600
|
12
|
00h
|
0Ch
|
19200
|
6
|
00h
|
06h
|
38400
|
3
|
00h
|
03h
|
57600
|
2
|
00h
|
02h
|
115200
|
1
|
00h
|
01h
|
Interrupt Enable Register (IER)
Table 7. แสดงหน้าที่ของ bit ต่าง ๆ ใน Interrupt Enable Register
Table 7. Interrupt Enable Register.
Bit
|
Note
|
7
|
Reserved
|
6
|
Reserved
|
5
|
Enable Low Power Mode (16750)
|
4
|
Enable Sleep Mode (16750)
|
3
|
Enable Modem Status Interrupt
|
2
|
Enable Receiver Line Status Interrupt
|
1
|
Enable Transmitter Holding Register Empty Interrupt
|
0
|
Enable Receiver Data Available Interrupt
|
ถ้า bit0 ถูกกำหนดให้เป็น “1” หรือ “high” จะเป็นการ enable ตัว receiver data
available interrupt ซึ่งจะทำให้เกิด interrupt ขึ้นเมื่อมีข้อมูลใน FIFO buffer
ของภาครับเพื่อรอให้ CPU อ่าน ส่วน bit1 ถ้าถูกกำหนดเป็น “1” หรือ “high” จะเป็นการ
enable ตัว transmitter holding register empty interrupt ซึ่งจะ interrupt ไปให้
CPU เมื่อ buffer ของภาคส่งว่าง (empty) สำหรับ bit2 ทำหน้าที่ enable การ interrupt
ของ receiver line status ซึ่งจะทำให้ UART ส่ง interrupt ไปยัง CPU เมื่อมีการเปลี่ยนแปลงสภาวะที่
receiver line เกิดขึ้น และ bit3 เป็นตัว enable การ interrupt ของ modem status
bit4 ถึง bit7 สำรองไว้ไม่ได้ใช้ใน UART เบอร์ 8250, 16550A และ 16650