$SEGMENTED ; directive needed for all memory models, except TINY $CASE ; CASE sensitive mode, required for interface to C $MOD167 ; Code for extended devices (161/163/164/165/167) $INCLUDE (REG167.INC) ; include CPU definition file (for example, C167xx) MAXSERIALIN equ 256 ;maximale groesse des empfangsbuffers MAXSERIALOUT equ 256 ;maximale groesse des sendebuffers public SerialInit0,SerialClearInBuffer0,SerialClearOutBuffer0 public SerialReadChar0,SerialCharCount0 public SerialWriteChar0 ?XD0?Serial section XDATA word 'XDATA0' SerialInInPtr dsb 2 SerialInOutPtr dsb 2 SerialInCnt dsb 2 SerialOutInPtr dsb 2 SerialOutOutPtr dsb 2 SerialOutCnt dsb 2 SerialInBuffer dsb MAXSERIALIN SerialOutBuffer dsb MAXSERIALOUT ?XD0?Serial ends ?BI0?Serial section BIT BIT 'BIT0' IntEnFlag dbit 1 ?BI0?Serial ends assume DPP1:?XD0?Serial assume DPP2:?PR?Serial ?PR?Serial section code word 'FCODE' ;------------------------------------------------------------------------------------------------- ; ; void SerialInit0(word Baudrate) ; ; Initialisiert die serielle schnittstelle 0 mit Baudrate Baud , 8 Bit , No parity ; ;------------------------------------------------------------------------------------------------- SerialInit0 proc far scxt word dpp1,#PAG(SerialInInPtr) ;Page laden scxt word dpp2,#PAG(S0BG) ;Page laden bclr S0RIE ;interrupt aus bclr S0TIE bset P3.10 ;set port P3.10 outputlatch bset DP3.10 ;set direction (TXD) bclr DP3.11 ;set direction (RXD) movb S0TIC,#00001000b ;Interrupt level setzen TRN Interrupt movb S0RIC,#00001001b ;Interrupt level setzen REC Interrupt shl r8,#1 ;ohne assume dpp2 gibt das hier eine warning (assembler macke ?) extp #PAG(BaudrateTab),#1 movw r4,[r8+#BaudrateTab] ;baudrate divisor in R4 movw dpp2:S0BG,r4 movw S0CON,#1000000000010001b ;Mode der seriellen schnittstelle 8Bit 1 Stop no Parity movw r4,#SOF(SerialInBuffer) ;offset setzen empfangsbuffer movw SerialInInPtr,r4 movw SerialInOutPtr,r4 movw SerialInCnt,ZEROS ;CNT = 0 movw r4,#SOF (SerialOutBuffer) ; offset setzen sende buffer movw SerialOutInPtr,r4 movw SerialOutOutPtr,r4 movw SerialOutCnt,ZEROS ; CNt = 0 bset S0RIE ;interrupt REC freigeben pop dpp2 pop dpp1 rets SerialInit0 endp ;BaudrateTab: dw 416,207,103,51,25,12,8 ;(4Mhz quarz) 1200,2400,4800,9600,19200,38400,56400 Baud BaudrateTab: dw 520,258,128,63,31,15,10 ;(5Mhz quarz) 1200,2400,4800,9600,19200,38400,56400 Baud ;------------------------------------------------------------------------------------------------- ; ; void SerialClearInBuffer0(void) ; void SerialClearOutBuffer0(void) ; loescht Empfangs , SendeBuffer ; ;------------------------------------------------------------------------------------------------- SerialClearInBuffer0 proc far scxt dpp1,#PAG(SerialInInPtr) ;page laden bmov IntEnFlag,S0RIE ;zustand speichern bclr S0RIE ;interrupt aus movw r4,#SOF(SerialInBuffer) ;offset laden movw SerialInInPtr,r4 movw SerialInOutPtr,r4 movw SerialInCnt,ZEROS ;cnt = 0 bmov S0RIE,IntEnFlag ;interrupt ein pop dpp1 rets SerialClearInBuffer0 endp SerialClearOutBuffer0 proc far scxt dpp1,#PAG(SerialOutInPtr) ;page laden bmov IntEnFlag,S0TIE bclr S0TIE ;interrupt aus movw r4,#SOF(SerialOutBuffer) ;offset laden movw SerialOutInPtr,r4 movw SerialOutOutPtr,r4 movw SerialOutCnt,ZEROS ;cnt = 0 bmov S0TIE,IntEnFlag ;interrupt ein pop dpp1 rets SerialClearOutBuffer0 endp ;------------------------------------------------------------------------------------------------- ; ; char SerialReadChar0(void) ; zeichen aus dem empfangsbuffer holen ; ;------------------------------------------------------------------------------------------------- SerialReadChar0 proc far scxt dpp1,#PAG(SerialInInPtr) ;page laden nop WaitReadChar: movw r4,SerialInCnt ;test auf zeichen im Buffer jmpr cc_Z,WaitReadChar ;wenn null dann warten bmov IntEnFlag,S0RIE bclr S0RIE ;interrupt aus movw r4,#1 subw SerialInCnt,r4 ;CNT-- movw r5,SerialInOutPtr ;ptr laden extp #PAG(SerialInBuffer),#1 movb rl4,[r5+] ;zeichen laden + Ptr++ cmpw r5,#SOF(SerialInBuffer+MAXSERIALIN) ;Ptr wrap around ? jmpr cc_ULT,WaitRead1 movw r5,#SOF(SerialInBuffer) ;wenn ja ptr neu laden WaitRead1: movw SerialInOutPtr,r5 ;ptr speichern bmov S0RIE,IntEnFlag ;interrupt ein pop dpp1 rets SerialReadChar0 endp ;------------------------------------------------------------------------------------------------- ; ; word SerialCharCount0(void) ; gibt die anzahl der zeichen im empfangsbuffer zurueck ; ;------------------------------------------------------------------------------------------------- SerialCharCount0 proc far scxt dpp1,#PAG(SerialInCnt) nop movw r4,SerialInCnt pop dpp1 rets SerialCharCount0 endp ;------------------------------------------------------------------------------------------------- ; ; void SerialWriteChar0(byte char) ; ein zeichen ausgeben ; ;------------------------------------------------------------------------------------------------- SerialWriteChar0 proc far scxt dpp1,#PAG(SerialOutInPtr) nop WriteChar0: movw r5,SerialOutCnt ;noch platz im Buffer ? cmpw r5,#MAXSERIALOUT jmpr cc_UGE,WriteChar0 ;wenn nicht dann warten movw r5,SerialOutInPtr ;ptr laden movw r4,r8 ;zeichen ist in R8 extp #PAG(SerialOutBuffer),#1 movb [r5],rl4 ;zeichen speichern in Buffer addw r5,#1 ;ptr ++ cmpw r5,#SOF(SerialOutBuffer+MAXSERIALOUT) ;Ptr wrap around ? jmpr cc_ULT,WriteChar1 movw r5,#SOF(SerialOutBuffer) ;wenn ja ptr neu laden WriteChar1: movw SerialOutInPtr,r5 ;ptr speichern movw r5,#1 addw SerialOutCnt,r5 ;cnt++ jb S0TIE,WriteChar2 ;wenn Interrupt noch aktiv ist nicht neu starten bset S0TIE ;nicht aktiv -> dann interrupt frei bset S0TIR ;und ersten Interruptrequest anfordern WriteChar2: pop dpp1 rets SerialWriteChar0 endp ;------------------------------------------------------------------------------------------------- ; ; Receive interrupt service routine ; ;------------------------------------------------------------------------------------------------- RecService PROC INTERRUPT = 02bh push r5 push r4 scxt dpp1,#PAG(SerialInInPtr) scxt dpp3,#PAG(S0RBUF) nop movw r4,dpp3:S0RBUF ;zeichen einlesen movw r5,SerialInCnt ;test ob buffer voll ist cmpw r5,#MAXSERIALIN jmpr cc_UGE,NoRecChar movw r5,SerialInInPtr ;ptr laden extp #PAG(SerialInBuffer),#1 movb [r5],rl4 ;zeichen speichern addw r5,#1 ;Ptr++ cmpw r5,#SOF(SerialInBuffer+MAXSERIALIN) ;Ptr wrap around ? jmpr cc_ULT,RecService1 movw r5,#SOF(SerialInBuffer) ;wenn ja ptr neu laden RecService1: movw SerialInInPtr,r5 ;ptr speichern movw r4,#1 addw SerialInCnt,r4 ;Cnt ++ NoRecChar: pop dpp3 pop dpp1 pop r4 pop r5 reti RecService ENDP ;------------------------------------------------------------------------------------------------- ; ; Transmit interrupt service routine ; ;------------------------------------------------------------------------------------------------- TrnService PROC INTERRUPT = 02ah push r5 push r4 scxt dpp1,#PAG(SerialOutOutPtr) scxt dpp3,#PAG(S0TBUF) nop movw r4,SerialOutCnt ;check ob noch zeichen im buffer sind jmpr cc_Z,TrnStop movw r4,#1 subw SerialOutCnt,r4 ;cnt -- movw r5,SerialOutOutPtr ;ptr laden extp #PAG(SerialOutBuffer),#1 movb rl4,[r5+] ;zeichen aus buffer holen Ptr++ movb dpp3:S0TBUF,rl4 ;und ausgeben cmpw r5,#SOF(SerialOutBuffer+MAXSERIALOUT) ;ptr wrap around jmpr cc_ULT,TrnService1 movw r5,#SOF(SerialOutBuffer) ;wenn ja ptr neu laden TrnService1: movw SerialOutOutPtr,r5 ;ptr speichern jmpr cc_UC,TrnServiceEnd TrnStop: bclr S0TIE ;interrupt ausschalten wenn buffer leer TrnServiceEnd: pop dpp3 pop dpp1 pop r4 pop r5 reti TrnService ENDP ?PR?Serial ends end