1. gzyueqian
      13424082685
      首頁 > 新聞中心 > > 正文

      用軟件仿真串口

      更新時間: 2007-01-23 16:11:24來源: 粵嵌教育瀏覽量:1419

      ;*******************************************************************************

      ; Duplex UART Routines for the 8xC751 and 8xC752 Microcontrollers

      ;*******************************************************************************

       

      ; This is a demo program showing a way to perform simultaneous RS-232

      ; transmit and receive using only one hardware timer.

      ; The transmit and receive routines divide each bit time into 4 slices to

      ; allow synchronizing to incoming data that may be out of synch with outgoing

      ; data.

      ; The main program loop in this demo processes received data and sends it

      ; back to the transmitter in hexadecimal format. This insures that we can

      ; always fill up the receiver buffer (since the returned data is longer than

      ; the received data) for testing purposes. Example: if the letter "A" is

      ; received, we will echo "A41 ".

      ;*******************************************************************************

       

      ;$Title(Duplex UART Routines for the 751/752)

      ;$Date(8/20/92)

      ;$MOD751

       

      ;*******************************************************************************

      ; Definitions

      ;*******************************************************************************

       

      ; Miscellaneous

      TxBitLen EQU -4 + 1 ; Timer slices per serial bit transmit.

      RxBitLen EQU -4 + 1 ; Timer slices per serial bit receive.

      RxHalfBit EQU (RxBitLen / 4) + 1 ; Timer slices for a partial bit time.

      ; Used to adjust the input sampling

      ; time point.

      ; Note: TxBitLen and RxBitLen are kept separate in order to facilitate the

      ; possibility of having different transmit and receive baud rates. The timer

      ; would be set up to give four slices for the fastest baud rate, and the

      ; BitLen for the slower channel would be set longer for the slower baud rate.

      ; BitLen = -4 + 1 gives four timer interrupts per bit. BitLen = -8 + 1 would

      ; give 8 slices, BitLen = -16 + 1 would give 16 slices, etc.

      TxPin BIT P1.0 ; RS-232 transmit pin (output).

      RxPin BIT P3.2 ; RS-232 receive pin (input).

      RTS BIT P1.3 ; RS-232 request to send pin (output).

      CTS BIT P1.6 ; RS-232 clear to send pin (input).

      ; Note: P1.1 and P1.2 are used to input the baud rate selection.

       

      ; RAM Locations

      Flags DATA 20h ; Miscellaneous bit flags (see below).

      TxOn BIT Flags.0 ; Indicates transmitter is on (busy).

      RxOn BIT Flags.1 ; Indicates receiver is on (busy).

      TxFull BIT Flags.2 ; Transmit buffer (1 byte only) is full.

      RxFull BIT Flags.3 ; Receiver buffer is full.

      RxAvail BIT Flags.4 ; RX buffer is not empty.

      OverrunErr BIT Flags.6 ; Overrun error flag.

      FramingErr BIT Flags.7 ; Framing error flag.

      BaudHigh DATA 21h ; High byte timer value for baud rate.

      BaudLow DATA 22h ; Low byte timer value for baud rate.

      TxCnt DATA 23h ; RS-232 byte transmit bit counter.

      TxTime DATA 24h ; RS-232 transmit time slice count.

      TxShift DATA 25h ; Transmitter shift register.

      TxDat DATA 26h ; Transmitter holding register.

      RxCnt DATA 27h ; RS-232 byte receive bit counter.

      RxTime DATA 28h ; RS-232 receive time slice count.

      RxShift DATA 29h ; Receiver shift register.

      RxDatCnt DATA 2Ah ; Received byte count.

      RxBuf DATA 2Bh ; Receive buffer (3 bytes long).

      Temp DATA 2Fh ; Temporary holding register.

      RTH DATA 40H

      RTL DATA 41H

       

      ;*******************************************************************************

      ; Interrupt Vectors

      ;*******************************************************************************

      ORG 00h ; Reset vector.

      AJMP RESET

       

      ORG 03h ; External interrupt 0

      AJMP Intr0 ; (received RS-232 start bit).

       

      ORG 0Bh ; Timer 0 overflow interrupt.

      AJMP Timer0 ; (4X the RS-232 bit rate).

       

      ORG 13h ; External interrupt 1.

      RETI ; (not used).

      ORG 1Bh ; Timer I interrupt.

      RETI ; (not used).

      ORG 23h ; I2C interrupt.

      RETI ; (not used).

       

      ;*******************************************************************************

      ; Interrupt Handlers

      ;*******************************************************************************

       

      ; External Interrupt Int0.

      ; RS-232 start bit transition.

      Intr0: PUSH ACC ; Save accumulator,

      PUSH PSW ; and status.

      CLR IE.0 ; Disable more RX interrupts.

      SETB RxOn ; Set receive active flag.

      MOV RxCnt,#11h ; Set bit counter to expect a start.

      MOV A,#RXHALFBIT

      MOV RxTime,#RxHalfBit ; First sample is at a partial bit time.

      JB TxOn,I0TimerOn ; If TX active then timer is on.

      MOV RTH,BaudHigh ; Set up timer for selected baud rate.

      MOV RTL,BaudLow

      MOV TH0,BaudHigh

      MOV TL0,BaudLow

      SETB TR0 ; Start timer 0.

      I0TimerOn: MOV A,RxDatCnt ; Check for buffer about to be full:

      CJNE A,#2,Int0Ex ; one space left and a byte starting.

      SETB RTS ; If so, tell whoever is on the

      ; other end to wait.

      Int0Ex: POP PSW ; Restore status,

      POP ACC ; and accumulator.

      RETI

       

      ; Timer 0 Interrupt

      ; This is used to generate time slices for both serial transmit and receive

      ; functions.

      Timer0: PUSH ACC ; Save accumulator,

      PUSH PSW ; and status.

      JNB TxTime.7,RS232TX ; Is this an active time slice

      ; for an RS-232 transmit?

      JNB TxOn,CheckRx ; If transmit is active,

      INC TxTime ; increment the time slice count.

      CheckRx: JNB RxTime.7,RS232RX ; Is this an active time slice

      ; for an RS-232 receive?

      JNB RxOn,T0Ex ; If receive is active, increment

      INC RxTime ; the time slice count.

      MOV A,RXTIME

      T0Ex: POP PSW ; Restore status,

      POP ACC ; and accumulator.

      ;MOV P3,Flags ; For demo purposes, output status

      ; on an extra port.

      RETI

       

       

      ;*******************************************************************************

      ; RS-232 Transmit Routine

      ;*******************************************************************************

       

      RS232TX: JNB TxCnt.4,TxData ; Go if data bit.

      JNB TxCnt.0,TxStop ; Go if stop bit.

       

      ; Send start bit and do buffer housekeeping.

      TxStart: JB CTS,TxEx1 ; Is CTS asserted (low) so can we send?

      ; If not, try again after 1 bit time.

      CLR TxPin ; Set start bit.

      MOV TxShift,TxDat ; Get byte to transmit from buffer.

      CLR TxFull

      MOV TxCnt,#08h ; Init bit count for 8 bits of data.

      ; (note: counts UP).

      TxEx1: MOV TxTime,#TxBitLen ; Reset time slice count.

      SJMP CheckRx ; Restore state and exit.

       

      ; Send Next Data Bit.

      TxData: MOV A,TxShift ; Get un-transmitted bits.

      RRC A ; Shift next TX bit to carry.

      MOV TxPin,C ; Move carry out to the TXD pin.

      MOV TxShift,A ; Save bits still to be TX'd.

      INC TxCnt ; Increment TX bit counter

      MOV TxTime,#TxBitLen ; Reset time slice count.

      SJMP CheckRx ; Restore state and exit.

       

      ; Send Stop Bit and Check for More to Send.

      TxStop: SETB TxPin ; Send stop bit.

      JB TxFull,TxEx2 ; More data to transmit?

      CLR TxOn ; If not, turn off TX active flag, and

      CLR RTS ; make sure that whoever is on the

      ; other end knows it's OK to send.

      JB RxOn,TxEx2 ; If receive active, timer stays on,

      CLR TR0 ; otherwise turn off timer.

      TxEx2: MOV TxCnt,#11h ; Set TX bit counter for a start.

      MOV TxTime,#TxBitLen-1 ; Reset time slice count, stop bit

      ; > 1 bit time for synch.

      SJMP CheckRx ; Restore state and exit.

       

       

      ;*******************************************************************************

      ; RS-232 Receive Routine

      ;*******************************************************************************

       

      RS232RX: MOV C,RxPin ; Get current serial bit value.

      JNB RxCnt.4,RxData ; Go if data bit.

      JNB RxCnt.0,RxStop ; Go if stop bit.

       

      ;Verify start bit.

      RxStart: JC RxErr ; If bit=1, then not a valid start.

      MOV RxCnt,#08h ; Init counter to expect data.

      MOV A,#RXBITLEN

      MOV RxTime,#RxBitLen ; Reset time slice count.

      SJMP T0Ex ; Restore state and exit.

       

      ; Get Next Data Bit.

      RxData: MOV A,RxShift ; Get partial received byte.

      RRC A ; Shift in new received bit.

      MOV RxShift,A ; Store partial result in buffer.

      INC RxCnt ; Increment received bit count.

      MOV RxTime,#RxBitLen ; Reset time slice count.

      SJMP T0Ex ; Restore state and exit.

       

      ; Store Data Byte, "push"ing it into the FIFO buffer.

      RxStop: CLR EA ; Don't interrupt the following.

      MOV A,RxBuf ; "PUSH" the receive buffer.

      XCH A,RxBuf+1

      XCH A,RxBuf+2

      MOV RxBuf,RxShift ; Add just completed data to buffer.

      INC RxDatCnt ; Increment the received byte count.

      SETB EA ; Re-enable interrupts.

      SETB RxAvail ; There is data in the RX buffer.

      PUSH PSW ; Save Carry (received bit)for later.

      MOV A,RxDatCnt ; Check receiver buffer status.

      CJNE A,#4,RxChk1 ; Is RX buffer overrun?

      SETB OverrunErr ; Set status reg overrun error flag.

      MOV RxDatCnt,#3 ; Re-set buffer counter to "full".

      RxChk1: CJNE A,#3,RxChk2 ; Is RX buffer full?

      SETB RxFull ; Set buffer full status.

      RxChk2: POP PSW ; Retrieve last received bit in Carry.

      JC RxEx ; If bit=0, then not a valid stop.

      RxErr: SETB FramingErr ; Remember bad start or stop status.

      RxEx: JB TxOn,RxTimerOn ; If transmit active, timer stays on,

      CLR TR0 ; otherwise turn timer off.

      RxTimerOn: CLR RxOn ; Turn off receive active.

      SETB RxTime.7 ; Set bit for no service to

      ; RX Time Slice Branches.

      SETB IE.0 ; Re-enable RS-232 receive interrupts.

      AJMP T0Ex ; Restore state and exit.

       

      ;*******************************************************************************

      ; Subroutines

      ;*******************************************************************************

       

      ; BaudRate - Determine and set the baud rate from switches.

      ; Note: if the baud rate is altered, the actual change will only occur when

      ; a transmit or receive is begun while the timer was not already running

      ; (i.e.: not already busy transmitting or receiving).

      BaudRate: MOV DPTR,#BaudTable ; Set pointer to baud rate table.

      ANL A,#03h ; Limit displacement for lookup.

      RL A ; Double the table index since these

      ; are 2 byte entries.

      PUSH ACC ; Save the table index for second byte.

      MOVC A,@A+DPTR ; Get first byte, and save as the high

      MOV BaudHigh,A ; byte of the baud rate timer value.

      POP ACC ; Get back the table index.

      INC A ; Advance to next table entry.

      MOVC A,@A+DPTR ; Get second byte, and save as the low

      MOV BaudLow,A ; byte of the baud rate timer value.

      RET

       

      ; Entries in BaudTable are for a timer setting of 1/4 of a bit time at the given

      ; baud rate. The two values per entry are the high and low bytes of the value

      ; respectively.

      ; Values are calculated as follows:

      ; Osc Frequency

      ; 1/4 Bit cell time (in machine cycles) = -----------------

      ; Baud Rate * 48

      ; Example for 9600 baud with a 16MHz crystal:

      ; 16,000,000 / 9600 * 48 = 34.7222... machine cycles per quarter bit time.

      ; Rounded, this is 35. The hexadecimal value for 35 is 23.

      ; 10000 hex - 23 hex (truncated to 16 bits) = FFDD. Thus, the BaudTable entry

      ; for 9600 baud is FF, DD hex.

      BaudTable: DB 0FEh,0EAh ; 1200 baud.

      DB 0FFh,75h ; 2400 baud.

      DB 0FFh,0BBh ; 4800 baud.

      DB 0FFh,0DDh ; 9600 baud.

       

      ; TxSend - Initiate RS-232 Transmit.

      TxSend: JB TxFull,$ ; Make sure TX buffer is free.

      SETB TxFull ; Reserve the buffer for our use.

      MOV TxDat,A ; Put character in buffer.

      JB TxOn,TSTimerOn ; Exit if transmitter already running.

      SETB TxOn ; Transmit active flag set.

      MOV TxCnt,#11h ; Init bit counter to expect a start.

      MOV TxTime,#TxBitLen ; Reset time slice count.

      JB RxOn,TSTimerOn ; Exit if receiver already active.

      MOV RTH,BaudHigh ; Set up timer for selected baud rate.

      MOV RTL,BaudLow

      MOV TH0,BaudHigh

      MOV TL0,BaudLow

      SETB TR0 ; Start up the bit timer.

      TSTimerOn: RET

       

      ; PrByte - Output a byte as ASCII hexadecimal format.

      PrByte: PUSH ACC ; Print ACC contents as ASCII hex.

      SWAP A

      ACALL HexAsc ; Print upper nibble.

      ACALL TxSend

      POP ACC

      ACALL HexAsc ; Print lower nibble.

      ACALL TxSend

      RET

       

      ; HexAsc - Convert a hexadecimal nibble to its ASCII character equivalent.

      HexAsc: ANL A,#0Fh ; Make sure we're working with only

      ; one nibble.

      CJNE A,#0Ah,HA1 ; Test value range.

      HA1: JC HAVal09 ; Value is 0 to 9.

      ADD A,#7 ; Value is A to F, needs pre-adjustment.

      HAVal09: ADD A,#'0' ; Adjust value to ASCII hex.

      RET

       

      ; GetRx - Retrieve a byte from the receive buffer, and return it in A.

      GetRx: CLR EA ; Make sure this isn't interrupted.

      DEC RxDatCnt ; Decrement the buffer count.

      MOV A,RxDatCnt ; Get buffer count.

      JNZ GRX1 ; Test for empty receive buffer.

      CLR RxAvail ; If empty, clear data available status.

      GRX1: ADD A,#RxBuf ; Create a pointer to end of buffer.

      MOV Temp,R0 ; Save R0.

      MOV R0,A ; Put pointer where we can indirect.

      MOV A,@R0 ; Get last buffer data.

      MOV R0,Temp ; Restore R0.

      CLR RxFull ; Buffer can't be full anymore.

      SETB EA ; Re-enable interrupts.

      RET

       

      ;*******************************************************************************

      ; Reset

      ;*******************************************************************************

      Reset: MOV SP,#50h ; Initialize stack start.

      MOV TCON,#0 ; Set timer off, INT0 to level trigger.

      MOV P2,#0H ; Turn off all status outputs.

      CLR P3.2 ; MY ADD

      ; For this demo, we only set up the baud rate once at reset:

      MOV A, P1 ; Read baudrate bits from P1.

      RR A ; The switches are on bits 2 and 1.

      ACALL BaudRate ; Set up the selected baud rate.

      MOV FLAGS,#0 ; Init all status flags.

      MOV RxDatCnt,#0 ; Clear buffer count.

      MOV IE,#93h ; Turn on timer 0 interrupt and

      ; external interrupt 0.

      CLR RTS ; Assert RTS so we can receive.

       

      ; The main program loop processes received data and sends it back to the

      ; transmitter in hexadecimal format. This insures that we can always fill

      ; up the receiver buffer (since the returned data is longer than the

      ; received data) for testing purposes. Example: if the letter "A" is

      ; received, we will echo "A41 ".

      MainLoop: JNB RxAvail,$ ; Make sure an input byte is available.

      ACALL GetRx ; Get data from the receiver buffer.

      ACALL TxSend ; Echo original character.

      ACALL PrByte ; Output the char in hexadecimal format,

      MOV A,#20h ; followed by a space.

      ACALL TxSend

      SJMP MainLoop ; Repeat.

      END

      免費預約試聽課

      亚洲另类欧美综合久久图片区_亚洲中文字幕日产无码2020_欧美日本一区二区三区桃色视频_亚洲AⅤ天堂一区二区三区

      
      

      1. 又紧又大又爽精品一区二区 | 日本A级免费看片 | 亚洲v日韩v欧美高清在线观看 | 午夜在线视频国产五月天 | 一级日本大片免费 | 日本在线中文字幕第一视频 |