Hi Ian,
It's indeed a RFID reader module, but comes from Itead Studio. May be the very same as yours :)
Two years ago I wrote a routine called My_buffered_serial_in to fix another problem: I didn't preserve R23 in the (all) interrupt routines and the AVR was a modern one with extended IO :oops: That caused a lot of headaches, because most of the time it DID work. Bascom magic ;)
Since I tested My_buffered_serial_in thoroughly, I simply implemented it in the current program. And it works fine :)
I haven't written the checksum routine yet. I'd be delighted to use your code for that. Thanks !
Nard
PS For those who could use my routine:
Initialize:
[code:1:1bd0a2e909]'################## Serial communication #################
'Using compiler default is another option, but this works even when the default settings are odd
Config Com1 = 9600 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config Serialout = Buffered , Size = 45
'No more Config Serialin = Buffered , Size = 40 , Bytematch = 3 since Input requires a CR LF, see Help on Config Input
'Thanks to laborratte and Evert @ Bascom forum
'Using my own BufferedSerialIn routine, since it has been thoroughly tested. And can handle ETX :P
'MySerialIn variables:
Dim My_si_terminator As Byte 'define here on what ASCII-value the MySerialInFlag must be set
My_si_terminator = 3 '<ETX>
'My_si_status has a triple function: bit7 is used as readyflag, bit6 as overrunflag and pointer uses the other bits
Dim My_si_status As Byte
My_si_readyf Alias My_si_status.7
My_si_overrunf Alias My_si_status.6
Dim My_si_buffer As String * 40 'length of inputbuffer, max 62
Dim My_si_bufsize As Byte
My_si_bufsize = 40
Dim Buffered_input_str As String * 40 'the workcopy
Dim Length As Byte
On Urxc My_si_handler Nosave
Enable Urxc
'End of ################## Serial communication #################[/code:1:1bd0a2e909]
Note: Don't forget to [b:1bd0a2e909]enable Global interrupts[/b:1bd0a2e909] !
Interrupt handler:
[code:1:1bd0a2e909]'My buffered Serial In handler
My_si_handler:
$asm
push xl
in xl,sreg
push xl
push xh
push zl
push zh
push r25
' push r23 'Just for AVR's with extended IO
'Overrun can occur when:
'1. the string was already terminated, and new characters pop in before the string is handled by main (and bits are cleared)
'2. there was no terminator yet, but the buffer is full
lds r25,{My_si_status} 'get the pointer including the flags
bst r25,7 'move readyflag to T
brtc test_for_overrun 'if set, the entered string was already ....
'.... ready-flag already set, so there is an overrun
bld r25,6 'doing this will cause a brach to si_handler_exit
Test_for_overrun:
bst r25,6 'overrunbit to T
brtc We_are_fine 'if bit6 is set (overrun), then ignore further received characters
andi r25,192 'Clear pointer but preserve flags
sts {My_si_status},r25
rjmp si_handler_exit
We_are_fine:
Loadadr My_si_buffer , Z 'get the startaddress of the buffer
add zl,r25 'add pointer to zl; we know that bit6 and 7 are 0
brcc z_holds_buffer_pointer
inc zh 'carry set? Then inc zh
Z_holds_buffer_pointer:
in xh,udr 'read UART data register
st z,xh 'store data from UDR in buffer
lds xl,{My_si_terminator}
cp xl,xh 'was this the terminator ?
brne no_terminator 'nope ... more to come
Close_buffer:
'that was the terminator, so put a 0 as string-end-marker in the next location
'set My_si_readyf (bit7 of My_si_status)
clr xh 'mark end of string with 0
st z,xh 'and store in buffer
sbr r25,128 'set bit7==readyflag
andi r25,192 'Clear pointer but preserve flags
sts {My_si_status},r25
rjmp Si_handler_exit 'we're done, so exit
No_terminator:
'now check if the buffersize has been reached
lds xh,{My_si_bufsize}
cp r25,xh
breq buffer_full
inc r25
sts {My_si_status},r25
rjmp Si_handler_exit
Buffer_full:
sbr r25,64 'set bit6==overrunflag
rjmp close_buffer
Si_handler_exit:
' pop r23 'Just for AVR's with extended IO
pop r25
pop zh
pop zl
pop xh
pop xl
Out Sreg , Xl
pop xl
$end Asm
Return[/code:1:1bd0a2e909]
And in the Main Loop you use it like this:
[code:1:1bd0a2e909]'RFID message handler
'Recover from comm error
If My_si_overrunf = 1 Then
Disable Interrupts
Reset Ucsrb.rxen 'to clear errorflags, a possible RxC-flag and flush the buffer
My_si_buffer = ""
My_si_status = 0
Set Ucsrb.rxen
Enable Interrupts
End If
'This the the normal operation-block: a command or question has come in
If My_si_readyf = 1 And My_si_overrunf = 0 Then
Disable Interrupts
Buffered_input_str = My_si_buffer 'make a copy to work with
My_si_status = 0 'and be ready for the next command
Enable Interrupts
Length = Len(buffered_input_str)
Decr Length
If Length > 127 Then Length = 0 'Length is a byte, and if 0, the Decr sets bit7 and we don't want that
'and here the rest of the handler
Buffered_input_str = Mid(buffered_input_str , 2 , Length) 'strip the STX at the start of the message
#if My_debug.1 = 1
Print Buffered_input_str
#endif
'Blip the fiber twice
Set Red_fibre
Set Grn_fibre
Waitms 300
Reset Red_fibre
Reset Grn_fibre
Waitms 300
Set Red_fibre
Set Grn_fibre
Waitms 300
Reset Red_fibre
Reset Grn_fibre
End If[/code:1:1bd0a2e909]
Enjoy !
↧