Escrito originalmente por Abago
He hecho las pertinentes modificaciones al código, para que en teoría... (y digo en teoría, porque no lo he simulado en hard)...
el led se quede parpadeando cada 500 ms
y el buffer se descargue mediante hserout por el pin tx
a groso modo, el rx lo gestiona la interrupción de la usart, y el tx lo gestiona el comando hserout...
será algo así como un echo de lo que escribas en la pantalla del hiperterminal...
Codigo:
" Define interrupt handler
DEFINE INTHAND myint
" Configure internal registers
DEFINE HSER_RCSTA 90H
DEFINE HSER_TXSTA 20H
DEFINE HSER_BAUD 9600
LED VAR PORTB.0 " Alias LED to PORTD.0
CREN VAR RCSTA.4 " Alias CREN (Serial receive enable)
"Variables for saving state in interrupt handler
wsave VAR BYTE $70 system " Saves W
ssave VAR BYTE bank0 system " Saves STATUS
psave VAR BYTE bank0 system " Saves PCLATH
fsave VAR BYTE bank0 system " Saves FSR
buffer_size CON 32 " Sets size of ring buffer
buffer VAR BYTE[buffer_size] " Array variable for holding received characters
index_in VAR BYTE bank0 " Pointer - next empty location in buffer
index_out VAR BYTE bank0 " Pointer - location of oldest character in buffer
errflag VAR BYTE bank0 " Error flag
bufchar VAR BYTE " Stores the character retrieved from the buffer
i VAR BYTE " Loop counter
GoTo start " Skip around interrupt handler
" Assembly language INTERRUPT handler
Asm
myint
; Uncomment the following if the device has less than 2k of code space
;movwf wsave ; Save W
;swapf STATUS, W ; Swap STATUS to W (swap avoids changing STATUS)
;clrf STATUS ; Clear STATUS
;movwf ssave ; Save swapped STATUS
;movf PCLATH, W ; Move PCLATH to W
;movwf psave ; Save PCLATH
; Save the FSR value for later
movf FSR, W ; Move FSR to W
movwf fsave ; Save FSR
; Check for hardware overrun error
btfsc RCSTA,OERR ; Check for usart overrun
GoTo usart_err ; jump to assembly error routine
; Find in which bank the compiler put buffer, and set IRP
IF (_buffer > 0FFh) ; Find the bank where buffer is located
bsf STATUS,IRP ; If bank 2 or 3 set IRP
Else
bcf STATUS,IRP ; If bank 0 or 1 clear IRP
EndIF
; Test for buffer overrun
incf _index_in, W ; Increment index_in to W
subwf _index_out, W ; Subtract indexes to test for buffer overrun
btfsc STATUS,Z ; check for zero (index_in = index_out)
GoTo buffer_err ; jump to error routine if zero
; Increment the index_in pointer and reset it if it"s outside the ring buffer
incf _index_in, F ; Increment index_in to index_in
movf _index_in, W ; Move new index_in to W
sublw _buffer_size-1 ; Subtract index_in from buffer_size-1
btfss STATUS,C ; If index_in => buffer_size
clrf _index_in ; Clear index_in
; Set FSR with the location of the next empty location in buffer
movlw Low _buffer ; Get the location of buffer[0]
addwf _index_in, W ; Add index_in to point to next empty slot
movwf FSR ; Store pointer in FSR
; Read and store the character from the USART
movf RCREG, W ; Read the received character
movwf INDF ; Put the received character in FSR location
; Restore FSR, PCLATH, STATUS and W registers
finished
movf fsave, W ; retrieve FSR value
movwf FSR ; Restore it to FSR
movf psave, W ; Retrieve PCLATH value
movwf PCLATH ; Restore it to PCLATH
swapf ssave, W ; Retrieve the swapped STATUS value (swap to avoid changing STATUS)
movwf STATUS ; Restore it to STATUS
swapf wsave, F ; Swap the stored W value
swapf wsave, W ; Restore it to W (swap to avoid changing STATUS)
retfie ; Return from the interrupt
; Error routines
buffer_err ; Jump here on buffer error
bsf _errflag,1 ; Set the buffer flag
usart_err ; Jump here on USART error
bsf _errflag,0 ; Set the USART flag
movf RCREG, W ; Trash the received character
GoTo finished ; Restore state and return to program
EndAsm
start:
" Initialize variables
index_in = 0
index_out = 0
errflag = 0
INTCON = %11000000 " Enable interrupts
PIE1.5 = 1 " Enable interrupt on USART
" Main program starts here - blink an LED at 1Hz
loop:
High LED " Turn on LED connected to PORTD.0
Pause 500 " Pause 500mS
Low LED " Turn off LED connected to PORTD.0
Pause 500 " Pause 500mS
display: " dump the buffer to the LCD
IF errflag Then error " Goto error routine if needed
IF index_in = index_out Then loop " loop if nothing in buffer
GoSub getbuf " Get a character from buffer
hserout [bufchar,10,13] " Send the character to LCD
GoTo display " Check for more characters in buffer
" Get a character from the buffer
getbuf: " Move the next character in buffer to bufchar
intcon = 0 " Disable interrupts while reading buffer
index_out = index_out + 1 " Increment index_out pointer (0 to 63)
IF index_out => buffer_size Then index_out = 0 " Reset pointer if outside buffer
bufchar = buffer[index_out] " Read buffer location(index_out)
INTCON = %11000000 " Enable interrupts
Return
" Display an error
error: " Display error message
INTCON = 0 " Disable interrupts while in the error routine
IF errflag.1 Then
hserout ["Buffer Overrun",10,13]
Else
Hserout ["USART Overrun",10,13]
EndIF
errflag = 0 " Reset the error flag
CREN = 0 " Disable continuous receive to clear hardware error
CREN = 1 " Enable continuous receive
INTCON = %11000000 " Enable interrupts
GoTo display " Carry on
End
Estimado Abago,
El código que me has mostrado anteriormente, hace lo mismo que éste que te pongo acontinuación, Es decir cuando llega algo por el Rx sale la interrupción, y el tx hace eco de lo que le he mandado con la interrupción. Eso me lo hace, lo que quiero es ver como puedo gestionar el bufchar para ir a etiquetas y que hagan algo: como poner un puerto a nivel alto, poder guardar en la epromm datos para luego gestionar estos, etc...
***********************************************
"Mi código: parpadea el led, y genera interrución por puerto serie mostrando en pantalla el texto que escribes.
INCLUDE "bs2defs.bas"
DEFINE LOADER_USER 1
DEFINE OSC 20
DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 24h
DEFINE HSER_BAUD 9600
ADCON1 = 6 " Set PortA to digital operation
RCIF VAR PIR1.5 " Alias RCIF (USART Receive Interrupt Flag)
OERR VAR RCSTA.1 " Alias OERR (USART Overrun Error Flag)
CREN VAR RCSTA.4 " Alias CREN (USART Continuous Receive Enable)
LED VAR PORTB.7 " Alias LED to PORTB.7
buffer_size CON 32 " Sets the size of the ring buffer
buffer VAR BYTE[buffer_size] " Array variable for holding received characters
index_in VAR BYTE " Pointer - next empty location in buffer
index_out VAR BYTE " Pointer - location of oldest character in buffer
bufchar VAR BYTE " Stores the character retrieved from the buffer
i VAR BYTE " loop counter
cont var byte
errflag VAR BYTE " Holds error flags
" Initialize variables
index_in = 0
index_out = 0
i = 0
INTCON = %11000000 " Enable interrupts
On INTERRUPT GoTo serialin " Declare interrupt handler routine
PIE1.5 = 1 " Enable interrupt on USART
" Main program starts here - blink an LED at 1Hz
Loop:
High LED " Turn on LED connected to PORTD.0
For i = 0 To 250 " Delay for .5 seconds (250*2mS)
Pause 2 " Use a short pause within a loop
Next i " instead of one long pause
Low LED " Turn off LED connected to PORTD.0
For i = 0 To 250 " Delay for .5 seconds (250*2mS)
Pause 2 " Use a short pause within a loop
Next i
hserout[BUFCHAR]
goto Loop
display:
IF errflag Then error
If index_in = index_out Then Loop " loop if nothing in buffer
"gosub getbuf ":
"leemos buffer hasta encontrar las primeras "
gosub getbuf ""
write cont , bufchar
GoTo display " Check for more characters in buffer
" Subroutines
Disable " Don"t check for interrupts in this section
getbuf: " move the next character in buffer to bufchar
index_out = (index_out + 1) " Increment index_out pointer (0 to 63)
If index_out > (buffer_size - 1) Then index_out = 0 " Reset pointer if outside of buffer
bufchar = buffer[index_out] " Read buffer location
Return
error: " Display error message if buffer has overrun
IF errflag.1 Then error1 " Determine the error
error1:
hserout["Buffer Overrun"] " Display buffer error on line-2
"Else
hserout["USART Overrun"] " Display usart error on line-2
"End If
"LCDOut $fe,2 " Send the LCD cursor back to line-1 home
"For i = 2 To col " Loop for each column beyond 1
"LCDOut $fe,$14 " Move the cursor right to the right column
"Next i
errflag = 0 " Reset the error flag
CREN = 0 " Disable continuous receive to clear overrun flag
CREN = 1 " Enable continuous receive
GoTo display " Carry on
" Interrupt handler
disable
serialin:
HIGH PORTB.3
" Buffer the character receive
If OERR Then usart_error " Check for USART errors
index_in = (index_in + 1) " Increment index_in pointer (0 to 63)
If index_in > (buffer_size - 1) Then index_in = 0 "Reset pointer if outside of buffer
If index_in = index_out Then buffer_error " Check for buffer overrun
HSerin [buffer[index_in]]
LOW PORTB.3
IF RCIF then serialin " Read USART and store character to next empty locationIf RCIF Then serialin " Check for another character while we"re here
Resume
enable " Return to program
buffer_error:
errflag = 1 " Set the error flag for software
" Move pointer back to avoid corrupting the buffer. MIN insures that it ends up within the buffer.
index_in = (index_in - 1) MIN (buffer_size - 1)
HSerin [buffer[index_in]] " Overwrite the last character stored (resets the interrupt flag)
usart_error:
errflag = 1 " Set the error flag for hardware
Resume " Return to program
End
**********************************************
Este el código.