View Full Version : How to receive multiple bytes using the hardware usart in the PIC18F2550
PJALM
- 3rd July 2007, 19: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, 22: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, 17: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, 22: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, 05:17
Has anyone had any luck with this code yet or hav any sugestions?
PJALM
- 31st August 2007, 08: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, 09: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,
Powered by vBulletin® Version 4.1.7 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.