⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 interfacing the serial - rs-232 port part 3-4.htm

📁 Parallel Port description of the communication port
💻 HTM
📖 第 1 页 / 共 4 页
字号:
outportb(0x20,0x20);
}
</PRE></FONT>
        <P>From the example above we check to see if there is a character to 
        receive and if their is we remove it from the UART and place it in a 
        buffer contained in memory. We keep on checking the UART, in case FIFO's 
        are enabled, so we can get all data available at the time of interrupt. 
        </P>
        <P>The last line contains the instruction <FONT 
        color=#400080><TT>outportb(0x20,0x20);</TT></FONT> which tells the 
        Programmable Interrupt Controller that the interrupt has finished. The 
        Programmable Interrupt Controller (PIC) is what we must go into now. All 
        of the routines above, we have assumed that everything is set up ready 
        to go. That is all the UART's registers are set correctly and that the 
        Programmable Interrupt Controller is set. </P>
        <P>The Programmable Interrupt Controller handles hardware interrupts. 
        Most PC's will have two of them located at different addresses. One 
        handles IRQ's 0 to 7 and the other IRQ's 8 to 15. Mainly Serial 
        communications interrupts reside on IRQ's under 7, thus PIC1 is used, 
        which is located at 0020 Hex. </P>
        <CENTER>
        <TABLE border=1 width="80%">
          <TBODY>
          <TR>
            <TD>
              <CENTER><B>Bit</B></CENTER></TD>
            <TD>
              <CENTER><B>Disable IRQ</B></CENTER></TD>
            <TD>
              <CENTER><B>Function</B></CENTER></TD></TR>
          <TR>
            <TD>
              <CENTER>7</CENTER></TD>
            <TD>
              <CENTER>IRQ7</CENTER></TD>
            <TD>Parallel Port</TD></TR>
          <TR>
            <TD>
              <CENTER>6</CENTER></TD>
            <TD>
              <CENTER>IRQ6</CENTER></TD>
            <TD>Floppy Disk Controller</TD></TR>
          <TR>
            <TD>
              <CENTER>5</CENTER></TD>
            <TD>
              <CENTER>IRQ5</CENTER></TD>
            <TD>Reserved/Sound Card</TD></TR>
          <TR>
            <TD>
              <CENTER>4</CENTER></TD>
            <TD>
              <CENTER>IRQ4</CENTER></TD>
            <TD>Serial Port</TD></TR>
          <TR>
            <TD>
              <CENTER>3</CENTER></TD>
            <TD>
              <CENTER>IRQ3</CENTER></TD>
            <TD>Serial Port</TD></TR>
          <TR>
            <TD>
              <CENTER>2</CENTER></TD>
            <TD>
              <CENTER>IRQ2</CENTER></TD>
            <TD>PIC2</TD></TR>
          <TR>
            <TD>
              <CENTER>1</CENTER></TD>
            <TD>
              <CENTER>IRQ1</CENTER></TD>
            <TD>Keyboard</TD></TR>
          <TR>
            <TD>
              <CENTER>0</CENTER></TD>
            <TD>
              <CENTER>IRQ0</CENTER></TD>
            <TD>System Timer</TD></TR></TBODY></TABLE><FONT size=-1>Table 15 : PIC1 
        Control Word (0x21)</FONT> </CENTER>
        <P>Multi-Comm ports are getting quite common, thus table 16 includes 
        data for PIC2 which is located at 0xA0. PIC2 is responsible for IRQ's 8 
        to 15. It operates in exactly the same way than PIC1 except that EOI's 
        (End of Interrupt) goes to port 0xA0 while the disabling (Masking) of 
        IRQ's are done using port 0xA1. </P>
        <CENTER>
        <TABLE border=1 width="80%">
          <TBODY>
          <TR>
            <TD>
              <CENTER><B>Bit</B></CENTER></TD>
            <TD>
              <CENTER><B>Disable IRQ</B></CENTER></TD>
            <TD>
              <CENTER><B>Function</B></CENTER></TD></TR>
          <TR>
            <TD>
              <CENTER>7</CENTER></TD>
            <TD>
              <CENTER>IRQ15</CENTER></TD>
            <TD>Reserved</TD></TR>
          <TR>
            <TD>
              <CENTER>6</CENTER></TD>
            <TD>
              <CENTER>IRQ14</CENTER></TD>
            <TD>Hard Disk Drive</TD></TR>
          <TR>
            <TD>
              <CENTER>5</CENTER></TD>
            <TD>
              <CENTER>IRQ13</CENTER></TD>
            <TD>Maths Co-Processor</TD></TR>
          <TR>
            <TD>
              <CENTER>4</CENTER></TD>
            <TD>
              <CENTER>IRQ12</CENTER></TD>
            <TD>PS/2 Mouse</TD></TR>
          <TR>
            <TD>
              <CENTER>3</CENTER></TD>
            <TD>
              <CENTER>IRQ11</CENTER></TD>
            <TD>Reserved</TD></TR>
          <TR>
            <TD>
              <CENTER>2</CENTER></TD>
            <TD>
              <CENTER>IRQ10</CENTER></TD>
            <TD>Reserved</TD></TR>
          <TR>
            <TD>
              <CENTER>1</CENTER></TD>
            <TD>
              <CENTER>IRQ9</CENTER></TD>
            <TD>IRQ2</TD></TR>
          <TR>
            <TD>
              <CENTER>0</CENTER></TD>
            <TD>
              <CENTER>IRQ8</CENTER></TD>
            <TD>Real Time Clock</TD></TR></TBODY></TABLE><FONT size=-1>Table 16 : 
        PIC2 Control Word (0xA1) </FONT></CENTER>
        <P>Most of the PIC's initiation is done by BIOS. All we have to worry 
        about is two instructions. The first one is <FONT 
        color=#400080><TT>outportb(0x21,(inportb(0x21) &amp; 0xEF);</TT></FONT> 
        which selects which interrupts we want to Disable (Mask). So if we want 
        to enable IRQ4 we would have to take 0x10 (16) from 0xFF (255) to come 
        up with 0xEF (239). That means we want to disable IRQ's 7,6,5,3,2,1 and 
        0, thus enabling IRQ 4. </P>
        <P>But what happens if one of these IRQs are already enabled and then we 
        come along and disable it? Therefore we input the value of the register 
        and using the &amp; function output the byte back to the register with 
        our changes using the instruction <FONT 
        color=#400080><TT>outportb(0x21,(inportb(0x21) &amp; 0xEF);</TT></FONT>. 
        For example if IRQ5 is already enabled before we come along, it will 
        enable both IRQ4 and IRQ5 so we don't make any changes which may affect 
        other programs or TSR's. </P>
        <P>The other instruction is <FONT 
        color=#400080><TT>outportb(0x20,0x20);</TT></FONT> which signals an end 
        of interrupt to the PIC. You use this command at the end of your 
        interrupt service routine, so that interrupts of a lower priority will 
        be accepted. </P><A name=33><FONT size=+1>UART Configuration</FONT><BR>
        <HR>
        </A>
        <P>Now we get to the UART settings (Finally) </P>
        <P>It's a good idea to turn off the interrupt generation on the UART as 
        the first instruction. Therefore your initialization can't get 
        interrupted by the UART. I've then chosen to set up our interrupt 
        vectors at this point. The next step is to set the speed at which you 
        wish to communicate at. If you remember the process, we have to set bit 
        7 (The DLAB) of the LCR so we can access the Divisor Latch High and Low 
        Bytes. We have decided to set the speed to 38,400 Bits per second which 
        should be find for 16450's and 16550's. This requires a divisor of 3, 
        thus our divisor latch high byte will be 0x00 and a divisor latch low 
        byte, 0x03. </P>
        <P>In today's standards the divisor low latch byte is rarely used but it 
        still pays us to write 0x00 to the register just in case the program 
        before us just happened to set the UART at a very very low speed. BIOS 
        will normally set UARTs at 2400 BPS when the computer is first booted up 
        which still doesn't require the Divisor Latch Low byte. </P>
        <P>The next step would be to turn off the Divisor latch access bit so we 
        can get to the Interrupt Enable Register and the receiver/transmitter 
        buffers. What we could do is just write a 0x00 to the register clearing 
        it all, but considering we have to set up our word length, parity as so 
        forth in the line control register we can do this at the same time. We 
        have decided to set up 8 bits, no parity and 1 stop bit which is 
        normally used today. Therefore we write 0x03 to the line control 
        register which will also turn off the DLAB for us saving one more I/O 
        instruction. </P>
        <P>The next line of code turns on the FIFO buffers. We have made the 
        trigger level at 14 bytes, thus bits 6 and 7 are on. We have also 
        enabled the FIFO's (bit 0). It's also good practice to clear out the 
        FIFO buffers on initialization. This will remove any rubbish which the 
        last program may of left in the FIFO buffers. Due to the fact that these 
        two bits are self resetting, we don't have to go any further and turn 
        off these bits. If my arithmetic is correct all these bits add up to 
        0xC7 or 199 for those people which still work in decimal. </P>
        <P>Then DTR, RTS and OUT 2 is taken active by the instruction <FONT 
        color=#400080><TT>outportb(PORT1 + 4,0x0B);</TT></FONT>. Some cards 
        (Both of Mine) require OUT2 active for interrupt requests thus I'm 
        normally always take it high. All that is left now is to set up our 
        interrupts which has be deliberately left to last as to not interrupt 
        our initialization. Our interrupt handler is only interested in new data 
        being available so we have only set the UART to interrupt when data is 
        received. </P><A name=34><FONT size=+1>Main Routine (Loop)</FONT><BR>
        <HR>
        </A>
        <P>Now we are left with, </P><FONT color=#400080><PRE>do {
    if (bufferin != bufferout){
                               ch = buffer[bufferout];
                               bufferout++;
                               if (bufferout == 1024) bufferout = 0;
                               printf("%c",ch);
                              }
    if (kbhit()){
                 c = getch();
                 outportb(PORT1, c);
                }
   } while (c !=27);
</PRE></FONT>
        <P>which keeps repeating until c = 27. This occurs when the ESC key is 
        hit. </P>
        <P>The next <I>if</I> statement checks to see if a key has been hit. 
        (<FONT color=#400080><TT>kbhit()</TT></FONT>) If so, it gets the 
        character using the <FONT color=#400080><TT>getch()</TT></FONT> 
        statement and outputs it to the receiver buffer. The UART then transmits 
        the character to the modem. What we have assumed here, is that the 
        person using the Communications Program can't type as fast as the UART 
        can send. However if the program wishes to send something, then a check 
        should be made to see if BIT 5 of the Line Status Register is set before 
        attempting to send a byte to the transmitter register. </P>
        <P>
        <CENTER><I>For more information on Interrupts, try <A 
        href="http://www.beyondlogic.org/interrupts/interupt.htm">"Interfacing 
        the PC : Using Interrupts"</A></I></CENTER>
        <P></P>
        <P><A name=35></A><FONT size=+1>Determining the type of UART via 
        software</FONT><BR>
        <HR>

        <P></P>
        <P>The type of UART you have installed in your system can be determined 
        without even needing a screwdriver in most cases. As you can see from <A 
        href="http://www.beyondlogic.org/serial/serial.htm#9">Types of 
        UART's</A> each UART has minor differences, all we have to do it test 
        these. </P>
        <P>The first procedure we do is to set bit 0 to '1' in the FIFO control 
        register. This tries to enable the FIFO buffers. Then we read bits 6 and 
        7 from the interrupt identification register. If both bits are '1' then 
        the FIFO buffers are enabled. This would mean the UART is a 16550a. If 
        the FIFO's were enabled but not usable then it would be a 16550. If 
        there is no FIFO buffer enabled it is most likely to be a 16450 UART, 
        but could be a 8250, 8250A or 8250B on very old systems. </P>
        <P>AT's have a fast bus speed which the 8250 series of UART can't handle 
        to well thus it is very unlikely to be found in any AT. However if you 
        wish to test for them as well you can follow the same test as above to 
        distinguish 16550's or 16550A's from the rest. If no FIFOs are enabled 
        then a possible UART is the 16450, 8250, 8250A or 8250B. Once it is 
        established the it could be one of these four chips, try writing a byte 
        to the scratch register and then read it back and compare the results. 
        If the results match then you must have a scratch register, if they 
        don't you either don't have a scratch register, or it doesn't work to 
        well. </P>
        <P>From the descriptions of the UART above if you read back your byte 
        from the scratch register then the UART must be a 16450 or 8250A. (Both 
        have scratch registers) If you don't read back your byte then it's 
        either a 8250 or 8250B. </P>
        <P>The 16750 has 64 byte FIFO's, thus the easiest way to test for it's 
        presence is to enable the 64 byte buffer using the FIFO Control Register 
        and then read back the status of the Interrupt Identification Register. 
        However I have never tested this. </P></UL><A name=Part4></A>
      <HR>
      <I><FONT size=+2>Part 4 : Interfacing Devices to RS-232 Ports</FONT></I> 
      <HR>

      <P></P>
      <UL><A name=40><FONT size=+1>RS-232 Waveforms</FONT><BR>
        <HR>
        </A>
        <P>So far we have introduced RS-232 Communications in relation to the 
        PC. RS-232 communication is asynchronous. That is a clock signal is not 
        sent with the data. Each word is synchronized using it's start bit, and 
        an internal clock on each side, keeps tabs on the timing. </P>
        <CENTER>
        <P><IMG alt="Serial Waveforms - Logic Levels" border=0 
        src="Interfacing The Serial - RS-232 Port Part 3-4_files/serwave1.gif"> 
        <BR><FONT size=-1>Figure 4 : TTL/CMOS Serial Logic Waveform</FONT> 
        </CENTER>
        <P>The diagram above, shows the expected waveform from the UART when 
        using the common 8N1 format. 8N1 signifies 8 Data bits, No Parity and 1 
        Stop Bit. The RS-232 line, when idle is in the Mark State (Logic 1). A 
        transmission starts with a start bit which is (Logic 0). Then each bit 
        is sent down the line, one at a time. The LSB (Least Significant Bit) is 
        sent first. A Stop Bit (Logic 1) is then appended to the signal to make 
        up the transmission. </P>
        <P>The diagram, shows the next bit after the Stop Bit to be Logic 0. 
        This must mean another word is following, and this is it's Start Bit. If 
        there is no more data coming then the receive line will stay in it's 
        idle state(logic 1). We have encountered something called a "Break" 
        Signal. This is when the data line is held in a Logic 0 state for a time 
        long enough to send an entire word. Therefore if you don't put the line 
        back into an idle state, then the receiving end will interpret this as a 
        break signal. </P>
        <P>The data sent using this method, is said to be <I>framed</I>. That is 
        the data is <I>framed</I> between a Start and Stop Bit. Should the Stop 
        Bit be received as a Logic 0, then a framing error will occur. This is 
        common, when both sides are communicating at different speeds. </P>
        <P>The above diagram is only relevant for the signal immediately at the 
        UART. RS-232 logic levels uses +3 to +25 volts to signify a "Space" 
        (Logic 0) and -3 to -25 volts for a "Mark" (logic 1). Any voltage in 
        between these regions (ie between +3 and -3 Volts) is undefined. 
        Therefore this signal is put through a "RS-232 Level Converter". This is 
        the signal present on the RS-232 Port of your computer, shown below. 
</P>
        <CENTER>
        <P><IMG alt="RS-232 Waveforms" border=0 
        src="Interfacing The Serial - RS-232 Port Part 3-4_files/serwave2.gif"> 
        <BR><FONT size=-1>Figure 5 : RS-232 Logic Waveform</FONT> </CENTER>
        <P>The above waveform applies to the Transmit and Receive lines on the 
        RS-232 port. These lines carry serial data, hence the name Serial Port. 
        There are other lines on the RS-232 port which, in essence are 
        <I>Parallel</I> lines. These lines (RTS, CTS, DCD, DSR, DTR, RTS and RI) 
        are also at RS-232 Logic Levels. </P>
        <P><A name=41><FONT size=+1>RS-232 Level Converters</FONT><BR>
        <HR>
        </A>
        <P></P>
        <P>Almost all digital devices which we use require either TTL or CMOS 
        logic levels. Therefore the first step to connecting a device to the 
        RS-232 port is to transform the RS-232 levels back into 0 and 5 Volts. 
        As we have already covered, this is done by RS-232 Level Converters. 
</P>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -