' ========================================================================= ' ' File...... Serial Interrupt.SXB ' Purpose... Performs Serial Send & Receive via interrupt ' Author.... Hitt Consulting ' E-mail.... terry@hittconsulting.com ' Started... Nov 10, 2006 ' Updated... ' ' ========================================================================= ' ------------------------------------------------------------------------- ' Device Settings ' ------------------------------------------------------------------------- DEVICE SX28, OSCHS2, TURBO, STACKX, OPTIONX FREQ 50_000_000 ' ------------------------------------------------------------------------- ' IO Pins ' ------------------------------------------------------------------------- SerialIn PIN RA.0 INPUT ' Whatever pin you want SerialOut PIN RA.1 OUTPUT ' Whatever pin you want ' ------------------------------------------------------------------------- ' Constants ' ------------------------------------------------------------------------- BAUD_RATE CON 31250 ' Set to desired baud rate BAUD_RATE3 CON "93750" ' Set to BAUD_RATE * 3 (cannot use computed constant) ZERO_STATE CON 1 ' Inverted serial mode, change to 0 for True serial mode ONE_STATE CON 0 ' Inverted serial mode, change to 1 for True serial mode SEND_IDLE CON 40 ' Value of serSendCnt when idle ' ------------------------------------------------------------------------- ' Variables ' ------------------------------------------------------------------------- ' Main code variables char VAR Byte ' Temporary variable for main code cnt VAR Byte ' Interrupt receive variables serRecvCnt VAR Byte ' This keeps track of the interrupt sample count serRecvData VAR Byte ' This holds the completly received data byte serRecvWork VAR Byte ' This holds the data byte as it is being received serRecvFlag VAR Bit ' This is set to 1 when a byte has been received ' Interrupt send variables serSendCnt VAR Byte ' This keeps track of which bit we are sending serSendData VAR Byte ' This holds the value we are sending ' ------------------------------------------------------------------------- ' INTERRUPT ROUTINE (IDLE CLOCKS = 42; MAX CLOCKS = 82) ' ------------------------------------------------------------------------- INTERRUPT NOPRESERVE BAUD_RATE3 ' Sample at 3x the baud rate ' Are we waiting for the stop bit ? IF serRecvCnt = 0 THEN IF SerialIn = ONE_STATE THEN ' Got stop bit serRecvCnt = 1 serRecvWork = 0 ENDIF ELSE DJNZ serRecvCnt,RecvDone IF serRecvWork = 0 THEN ' Waiting for start bit IF SerialIn = ZERO_STATE THEN ' Got start bit serRecvWork.7 = 1 ' Prime value serRecvCnt = 4 ' Get 1st data bit 1.333 bit-times from now ELSE ' Didn't get start bit, so check next interrupt serRecvCnt = 1 ENDIF ELSE ' Getting data bits serRecvCnt.0 = serRecvWork.0 ' Keep value of last bit to see if we are done. \ RR serRecvWork ' Shift bits in value, used because ">>" operator uses __PARAM1 IF SerialIn = ONE_STATE THEN serRecvWork.7 = 1 ELSE serRecvWork.7 = 0 ENDIF ' Check if this was the last data bit IF serRecvCnt.0 = 1 THEN serRecvData = serRecvWork ' Copy data byte serRecvFlag = 1 ' Indicate that we have recieved a data byte serRecvCnt = 0 ' Indicate that we have to wait for stop bit next time serRecvWork = 0 ' Clear data byte to indicate start bit has not been received yet ELSE serRecvCnt = 3 ' Get next data bit 1 bit-time from now ENDIF ENDIF ENDIF RecvDone: IF serSendCnt < SEND_IDLE THEN ' Are we sending ? IF serSendCnt.0 = 0 THEN ' Only send when bit 0 and 1 are zero (every 4 counts) IF serSendCnt.1 = 0 THEN IF serSendCnt = 0 THEN ' If count is zero we need to send the start bit ' Send start bit SerialOut = ZERO_STATE ' Start bit is a "0" ELSEIF serSendCnt < 36 THEN ' If count is < 36 then we are sending data bits ' Send data bits IF serSendData.0 = 0 THEN ' Send bit value that is in bit position zero SerialOut = ZERO_STATE ELSE SerialOut = ONE_STATE ENDIF \ RR serSendData' ' Used because ">>" operator uses __PARAM1 ELSE ' Send stop bit SerialOut = ONE_STATE ' Stop bit is a "1" ENDIF INC serSendCnt ' Bump count because we want to send a bit every 3 interrupts, but it easier to detect every 4 counts ENDIF ENDIF INC serSendCnt ENDIF RETURNINT ' ------------------------------------------------------------------------- ' Subroutine Declarations ' ------------------------------------------------------------------------- WaitForByte FUNC 1,0 SendByte SUB 1 ' ========================================================================= PROGRAM Start ' ========================================================================= ' ------------------------------------------------------------------------- ' Program Code ' ------------------------------------------------------------------------- Start: ' Initialize serial variables serRecvFlag = 0 serRecvCnt = 1 serSendCnt = SEND_IDLE SerialOut = ONE_STATE DO FOR cnt = 0 TO 255 ' Send a byte SendByte cnt ' This will wait for a byte before returning char = WaitForByte NEXT ' This will check if a character has been received ' IF serRecvFlag = 1 THEN ' char = serRecvData ' serRecvFlag = 0 ' ENDIF LOOP ' ------------------------------------------------------------------------- ' Subroutine Code ' ------------------------------------------------------------------------- WaitForByte: DO LOOP UNTIL serRecvFlag = 1 serRecvFlag = 0 RETURN serRecvData SendByte: DO LOOP UNTIL serSendCnt = SEND_IDLE serSendData = __PARAM1 serSendCnt = 0 RETURN