PDA

View Full Version : How to receive multiple bytes using the hardware usart in the PIC18F2550



PJALM
- 3rd July 2007, 20:26
Hi all,

I am trying to setup a RF connection between a PC and a PIC using the MaxStream ZigBee modules. If i send a single byte from the PC to the PIC everything is ok but how do I send more then one?

I am using hardware interrupts for the USART and the USART itself only has a 1 byte buffer.

I need a way to capture 10 bytes with the PIC into a buffer array and then process it afterwards.

skimask
- 3rd July 2007, 23:09
Hi all,

I am trying to setup a RF connection between a PC and a PIC using the MaxStream ZigBee modules. If i send a single byte from the PC to the PIC everything is ok but how do I send more then one?

I am using hardware interrupts for the USART and the USART itself only has a 1 byte buffer.

I need a way to capture 10 bytes with the PIC into a buffer array and then process it afterwards.

HSERIN uses the hardware UART, but uses it in a way that's more like the bit-banged method of SERIN. Use the STR modifier to get 10 bytes into an array.

PJALM
- 4th July 2007, 18:39
Thanks for the advise but at the time of interrupt there is only one byte to get because the buffer is only one byte in size.

I need a way to capture the data one byte at a time and put each byte into the array as it arrives. This means I need to track which byte I am on and know when to start capturing and when to stop.

I will put up some sample code I made to give you an idea of what I am trying to achieve.

PJALM
- 5th July 2007, 23:17
Ok here is a snippet from the code i am working on.

Maybe this will trigger some ideas.




DEFINE OSC 48
DEFINE LOADER_USED 1
DEFINE RESET_ORG 800h ' For Microchip USB Bootloader
DEFINE INTERRUPT_ORG 808h ' For Microchip USB Bootloader


'-------------------------------------------------------------------------------
' System Settings
'-------------------------------------------------------------------------------
ADCON1 = 15 ' Set all I/Os to Digital
INTCON2.7 = 1 ' Disable PortB Pullups
CMCON = 7 ' Disable Comparators

My_Address VAR BYTE
i VAR BYTE
ii VAR WORD

i = 0
ii = 0

My_Address = 0
'-------------------------------------------------------------------------------



'-------------------------------------------------------------------------------
' RF Settings
'-------------------------------------------------------------------------------
DEFINE HSER_BAUD 9600
DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 20h
'DEFINE HSER_SPBRG 25
DEFINE HSER_CLROERR 1

RF_ACK CON $01 ' Expected acknowledge char from RS-485
RF_STX CON $02 ' Start of Transmission Byte
RF_ETX CON $03 ' End of Transmission Byte
RF_POS CON $04

RF_To_Address VAR BYTE
RF_From_Address VAR BYTE
RF_Command VAR BYTE
RF_Parameter VAR WORD
RF_Data VAR BYTE
RF_Buffer VAR BYTE[7]
RF_Bytes_Sent VAR BYTE
RF_Bytes_Received VAR BYTE
RF_Sending_Data VAR BIT
RF_Receiving_Data VAR BIT
RF_Send VAR BIT
RF_ACK_Received VAR BIT
RF_PPP_Received VAR BIT
RF_POS_Received VAR BIT
RF_B0 VAR BYTE
RF_B1 VAR BYTE

RF_To_Address = 0
RF_From_Address = 0
RF_Command = 0
RF_Parameter = 0
RF_Send = 0
RF_Bytes_Received = 0
RF_Receiving_Data = 0
RF_ACK_Received = 0
RF_PPP_Received = 0
RF_POS_Received = 0
RF_B0 = 0
RF_B1 = 0
'-------------------------------------------------------------------------------



'-------------------------------------------------------------------------------
' Interrupt Settings
'-------------------------------------------------------------------------------
INTCON.6 = 1 ' Enable Peripheral Interrupts
INTCON.7 = 1 ' Enable Global Interrupt Handler
PIE1.4 = 0 ' Disable USART Transmit Interrupt
PIE1.5 = 1 ' Enable USART Receive Interrupt
'-------------------------------------------------------------------------------


PAUSE 500

My_Address = 18

ON INTERRUPT GOTO Main_Interrupt_Handler
ENABLE INTERRUPT



'-------------------------------------------------------------------------------
' Main Program Loop
'-------------------------------------------------------------------------------
MainLoop:
GOSUB Get_My_Address

'IF RF_Receiving_Data = 0 THEN
' IF RF_Command != 0 THEN
' IF RF_To_Address = My_Address THEN
' GOSUB RF_Process_Command
' ENDIF
' ENDIF
'ENDIF

PAUSE 50

GOTO MainLoop
'-------------------------------------------------------------------------------





'-------------------------------------------------------------------------------
' Send RF data
'-------------------------------------------------------------------------------
RF_Send_Data:
RF_From_Address = My_Address

RF_Ack_Received = 0
RF_PPP_Received = 0

RF_Buffer(1) = RF_STX 'Start
RF_Buffer(2) = RF_To_Address + 4 'To Address
RF_Buffer(3) = RF_Command 'Command
RF_Buffer(4) = RF_Parameter.HighByte + 4 'Parameter High Byte
RF_Buffer(5) = RF_Parameter.lowbyte + 4 'Parameter Low Byte
RF_Buffer(6) = RF_From_Address + 4 'From Address
RF_Buffer(7) = RF_ETX 'End

FOR i = 1 TO 25
PAUSE 10
NEXT

FOR i = 1 to 7
RF_Data = RF_Buffer(i)
HSEROUT [RF_Data] 'Send the Data Byte
PAUSE 25
NEXT

FOR i = 1 TO 25
PAUSE 10
NEXT

FOR i = 1 TO 7
RF_Buffer(i) = 0
NEXT

RF_To_Address = 0
RF_From_Address = 0
RF_Command = 0
RF_Parameter = 0

RETURN
'-------------------------------------------------------------------------------



'-------------------------------------------------------------------------------
' Interrupt Handler
'-------------------------------------------------------------------------------
DISABLE INTERRUPT ' No interrupts past this point
Main_Interrupt_Handler:

'---------------------------------------------------------------------------
' USART Receive Interrupt
'---------------------------------------------------------------------------
IF PIR1.5 = 1 THEN
PAUSE 50

HSERIN [RF_B0]

SELECT CASE RF_B0
CASE RF_STX
RF_Bytes_Received = 1
RF_Receiving_Data = 1
RF_Bytes_Received = 0

FOR i = 2 TO 7
RF_Buffer[i] = 0
NEXT

RF_Bytes_Received = RF_Bytes_Received + 1
RF_Buffer(RF_Bytes_Received) = RF_B0

CASE RF_ETX
RF_Bytes_Received = RS485_Bytes_Received + 1
RF_Buffer(RF_Bytes_Received) = RF_B0

RF_Receiving_Data = 0

RF_To_Address = RF_Buffer(2) - 4
RF_Command = RF_Buffer(3) - 4
RF_Parameter.HighByte = RF_Buffer(4) - 4
RF_Parameter.LowByte = RF_Buffer(5) - 4
RF_From_Address = RF_Buffer(6) - 4

CASE ELSE
IF RF_Receiving_Data = 1 THEN
RF_Bytes_Received = RF_Bytes_Received + 1
RF_Buffer(RF_Bytes_Received) = RF_B0
ENDIF
END SELECT
PIR1.5 = 0
ENDIF
'---------------------------------------------------------------------------



'---------------------------------------------------------------------------
' USB Interrupt
'---------------------------------------------------------------------------
IF PIR2.5 = 1 THEN
DEBUG 13, 10, "[ INTERRUPT ] USB Interrupt", 13, 10
PIR2.5 = 0
ENDIF
'---------------------------------------------------------------------------


IntDone:
RESUME ' Return to main program
ENABLE INTERRUPT
'-------------------------------------------------------------------------------

END

PJALM
- 20th July 2007, 06:17
Has anyone had any luck with this code yet or hav any sugestions?

PJALM
- 31st August 2007, 09:50
Has anyone at all had any experience with this? I still cannot successfully receive more then 1 byte without problems. ANy help at all would be greatly apreciated.

Thanks

Darrel Taylor
- 31st August 2007, 10:31
When using ON INTERRUPT the interrupts don't get handled until the currently executing PBP statement has finished.

At 9600 baud it only takes 1.04ms per byte. With the USARTS 2 byte buffer, the longest that any statement can take is 2.08ms. Anything taking longer will cause the buffer to overflow. Then with [DEFINE HSER_CLROERR 1] the program never even knows it lost data.

With PAUSE 50 in the MainLoop, you could easily loose 15-20 bytes at a time.

If you were using ASM interrupts, that wouldn't be a problem.

HTH,