PDA

View Full Version : Help understanding HSERIN/HSEROUT



jmbanales21485
- 8th September 2007, 06:49
Hello all,

I am trying to use the EUSART peripheral in the PIC16F688. I am using the 8Mhz internal oscillator and used Mister_e’s picMultiCalc to obtain the defines. I need help trying to understand how HSERIN works.

From what I understand, EUSART is a hardware peripheral embedded in the pic similar to hardware PWM. I know that in PWM I can specify a duty cycle and it can run in the background while I do other things in software. Is HSERIN/HSEROUT the same concept?

If I send a series of data bytes i.e.
HSEROUT [byte1, byte2, byte3]
how will the data be sent? Will it send the complete message first then proceed with the code, or will it initialize the transmission, the SW proceeds, and then finishes the transmission in the background?

Same question with HSERIN. How does it receive data packets? I know RCIE enables UART interrupt flag and RCIF sets the interrupt flag. How is it interrupted?
i.e an On-Change-Interrupt fires if a pin changes state, a timer interrupt fires at a timer overflow, or a comparator interrupt fires when it reaches a certain voltage. How would a HSERIN interrupt occur? Does it have some kind of buffer or something?

Thank you all for any input. Hopefully I get enough information so I can begin playing around with this peripheral.

Bruce
- 8th September 2007, 15:16
HSEROUT operates in a continuous loop until the last byte is sent.

First it tests the TXIF flag to see if the buffer is empty, when the buffer is empty, it then
loads the outbound byte into TXREG, and returns for the next byte until all bytes are sent.

After loading the last byte into TXREG and returning, depending on the baud rate, the PIC
can normally execute several thousand instructions while the last byte is still in the process
of being transmitted by the hardware UART. But it's still a continuous software loop until it
reaches the last byte, and passes it to the TXREG.

HSERIN is also a continuous software loop until all bytes have been received. RCIF is set
when the stop bit is received, and the new byte is transferred from the RSR register into
RCREG.

RCIF will remain set until all bytes have been read from RCREG, then RCIF is cleared in
hardware.

A receive interrupt only happens if you have the receive interrupt enabled. RCIF gets set
regardless, and can only be cleared by reading RCREG, and emptying the FIFO buffer.

jmbanales21485
- 9th September 2007, 04:47
Great! thank you for your reply,

let me get this straight.
-TXREG and RCREG is the buffer where a byte is stored whether it is going to be sent or received
-TXIF and RCIF determines whether the buffer is empty or full for tx and rx.
Also depending on whether i have an interrupt enabled (TXIE or RCIE) it will fire but both get set regardless.
-HSERIN/HSEROUT does not run in the background

my question is now, how does this compare to serin2/serout2. what does UART have special that i can't do in software with serin2/serout2 (which i can use any pin by the way)?

if i want to synch a message with a character will i not use:
HSERIN [wait("a"), dat]
but if i use this the SW will be hung at this line waiting for that character, where as if i use
serin2[wait("a"), dat]
is the same.

Bruce
- 9th September 2007, 15:35
It doesn't really matter if you're using HSERIN or SERIN2 with the WAIT option. Both are
going to stall and WAIT for the character you're WAITing for before moving on.

The hardware UART on most PICs has a 2-byte FIFO first-in, first-out buffer that will
buffer up to 2-bytes. This doesn't require any software over-head. These 2-bytes of data
are automatically stashed in the buffer, in the background, by the hardware UART.

Just enable the UART for continuous receive, test RCIF for new characters, check for over-
runs, etc.

Below is a simple example.


' ** // PIC16F877A, 20MHz crystal

' ** // Buffers up to 80 characters using the hardware
' ** // USART. Buffering ends when the EOM "~" character
' ** // is received.
' ** // Uses RCIF bit polling for new characters

DEFINE OSC 20
SPBRG = 129 ' 20MHz=129, 4MHz=25 to set baud rate at 9600
RCSTA = $90 ' Enable USART receive
TXSTA = $24 ' Set USART parameters
GP VAR byte ' GP variable
BytesIn VAR byte[80] ' Up to 80 bytes
ByteCnt VAR byte ' Indicates number of bytes in buffer
EOM CON "~" ' EOM = "End Of Message" marker
OERR VAR RCSTA.1 ' Alias USART over-run bit
CREN VAR RCSTA.4 ' Alias USART continuous receive enable bit
RCIF VAR PIR1.5 ' Alias USART received character interrupt flag bit
INTCON = 0 ' Disable interrupts
ByteCnt = 0 ' Zero counter
ADCON1 = 7 ' A/D off, all digital

Main:
IF RCIF THEN ' If RCIF=1 there's a new character in RCREG
BytesIn[ByteCnt]=RCREG ' Yes. Store new char in array
IF BytesIn[ByteCnt]=EOM THEN OutMsg ' End of message?
ByteCnt=ByteCnt+1 ' No. Increment array index pointer
IF ByteCnt >=80 THEN OutMsg ' Test for software buffer over-run
ENDIF
IF !OERR THEN Main ' If OERR=0 no over-run
CREN = 0 ' Over-run so disable receive
CREN = 1 ' Re-enable & clear OERR "over-run" flag
GOTO Main

OutMsg:
HSEROUT [13,10,dec ByteCnt," bytes received",13,10]
HSEROUT [str BytesIn\ByteCnt,13,10] ' Echo characters received
FOR GP=0 to ByteCnt ' Clear array bytes 0 to ByteCnt
BytesIn[GP]=0 '
NEXT '
ByteCnt=0 ' Reset index pointer back to first element
WHILE RCIF ' Trash anything received after the EOM marker
GP=RCREG ' by reading RCREG until RCIF is cleared.
WEND
GOTO Main

END
With HSERIN or SERIN2 and the WAIT modifier, you would be stuck in a continuous loop
waiting for your special character to show up. Of course, you can also use the TIMEOUT
LABEL options to exit HSERIN or SERIN2, but if there's noise on the RX pin, the timeout
period gets reset, and you're stuck again in a nasty continuous loop.

Even if the timout/label option works, you're still wasting a boat-load of instruction cycles
doing absolutely nothing.

By just monitoring flag bits, and doing a little house-keeping, you have tons of time to do
other things while the hardware UART buffers inbound data for you.

That's the big difference. Even a command like HSERIN, that uses a hardware peripheral
like the UART, can slow things down. Learning how to use the hardware by itself opens up
a lot of options you don't have when using a software command to control the hardware.

Another example is HPWM. You have limitations with the HPWM command that you don't
when you learn how to setup/use the hardware yourself.

jmbanales21485
- 15th September 2007, 22:46
sorry for the long delay, but had to take care of other things.

i see .... you implemented a recieve routine without HSERIN, by polling RCIF flag bit to see if it set, and if it did set, it emptied its register RCREG into an arrouy of bytes. Now, i'm guessing this can be done by interrupts also by enabling the RCIE bit and now we don't need to poll the flag bit, rather we just do whatever we need in code, then when the buffer fills the flag will be set, and we go to the interrupt routine, then we check for overruns etc. it makes sense.


is this the same way with transmitting a byte. if we store a byte into TXREG will that automatically be sent serially, (the moment it gets stored to TXREG) or how does it transmit? i'm guessing the TXIF flag is enabled when it finishes sending a byte correct?


I was able to get the PIC16F688 to talk to my PC (hyperterminal) via serial communication with its hardware USART using HSEROUT/HSERIN. I tried it at different baud rates and it worked perfectly! The only thing that i didn't like is that to do this i needed the MAX232 IC for voltage leveling, i was unable to communicate directly from the PIC. Is there any way of accomplishing this? i'v searched and i know it can be done, but it didn't work for me. any ideas?

by the way thank you bruce for your responses, they've been very helpful

flotulopex
- 7th March 2021, 17:11
By just monitoring flag bits and doing a little house-keeping, you have tons of time to do other things while the hardware UART buffers inbound data for you...

Hello there,

I've been spending some hours on searching information about using HSERIN with its interrupt, RCIF (PIR1.5), and found an interresting info in one of Bruce's posts. It wasn't about the interrupt but he explained and other way around very clearly.

My project is about a 3G monitoring system and receiving SMS messages is crucial (= it is crucial not to miss any incoming SMS).

Why do I search for unsing interrupts? Because, IMO, it's the only way to make sure I will not miss any incoming SMS.

Am I right or not, I don't know and maybe one of you can tell. But in the doubt, I'd like to give the best chances to my program not to oversee any SMS.

Bruce states that there are tons of time to do whatever you need but in my case, where among others I'm controlling four latching relays, setting them and checking their states takes at least 0.5 seconds added to the rest.

I never had the case up to now but I imagine I could receive to SMS within 0.5 seconds (but, as said, I'm not sure).

Anyway, I have posted here under just a piece of my full code where the principle of the RX EUSART interrupt should be tested. Unfortunately, it doesn't work and I can't find why.


' ====== FUSES 16F690 ================================================== ===========================
#CONFIG
__config _FCMEN_OFF &_IESO_OFF &_CPD_OFF &_WDT_OFF &_INTRC_OSC_NOCLKOUT &_BOR_OFF &_CP_OFF &_PWRTE_OFF &_MCLRE_OFF
#ENDCONFIG
@ ERRORLEVEL -306

' ====== REGISTERS ================================================== ===============================
OSCCON = %01110000 ' Internal RC set to 8Mhz - Register not to be used with XTal
OPTION_REG = %10000000 ' PORT A&B Pull-Ups (look WPUA & WPUB)
ADCON0 = %00000000 ' A/D Module
ANSEL = %00000000 ' Select analog inputs Channels 0 to 7
ANSELH = %00000000 ' Select analog inputs Channels 8 to 11

' ====== EUSART SETTINGS ================================================== ========================
' Interrupts registers
PIE1.5 = 1 ' Enable interrupt on EUSART
INTCON.7 = 1 ' PEIE peripheral interrupt
INTCON.6 = 1 ' GIE global interrupt

' Hardware EUSART registers (RX = PORTB.5, TX = PORTB.7)
RCSTA = %10010000 ' Enable serial port & continuous receive
TXSTA = %00100000 ' Enable transmit, BRGH = 0
SPBRG = 12 ' 9600 Baud @ 8MHz, 0.16%

' ====== DEFINES ================================================== ================================
Define OSC 8
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE NO_CLRWDT 1 ' Forces manual use of CLRWDT

' ====== VARIABLES ================================================== ==============================
LED1 VAR PORTC.4
LED2 VAR PORTC.5
Counter VAR BYTE ' ...a counter
RxBuffer VAR BYTE(18)' maximum SMS length (in characters)

' ====== PROGRAM ================================================== ================================
ON INTERRUPT GOTO INCOMING_SMS

WAITING_LOOP:
TOGGLE LED1
PAUSE 1000
GOTO WAITING_LOOP

MAIN:
' Do whatever needs to be done and go back to waiting loop
LED2 = 1
GOTO WAITING_LOOP

END

' ====== ISR ================================================== ====================================
DISABLE
INCOMING_SMS:
WHILE PIR1.5
RxBuffer(Counter) = RCREG
Counter = Counter +1
WEND
RESUME MAIN
ENABLE

Ioannis
- 7th March 2021, 18:45
I think there is no point in hunting down the incoming SMS as they are available in the GSM module.

You can once your MCU wants or is available to ask for the new messages, and select the most recent or decide from the list which one you want to read, deleted etc. Your GSM module may receive also messages from the Network operator, messages by error from someone that typed wrong number or ads. So you better check the list and see who sent it, then process it.

In this case you do not need Interrupts. Maybe if you want to raise a flag that a new SMS has arrived, but anyway, it is not necessary.

Also On Interrupts are slow by default! I think I never used them.

Ioannis

richard
- 7th March 2021, 23:40
My project is about a 3G monitoring system and receiving SMS messages is crucial (= it is crucial not to miss any incoming SMS).




the problem as i see it is that you are mixing up receiving a SMS message notification with receiving serial data without losing characters.


the question really is
how can i receive serial data as a background process with out data loss ?
how can i signal foreground process that a message has been received and not lose messages?


a workable solution is a interrupt driven ringbuffer for serial reception
that signals the foreground with a flag on completion of notification message.


the ringbuffer must be large enough to allow processing without data loss
the chip must have adequate speed and resources [not a 690, more like 16f1829]
hserin is not in the solution , its not flexible enough to be useful for this sort of task


you will find ringbuffer examples on both forums

Ioannis
- 8th March 2021, 08:17
Richard,

I think what you propose is the best solution and ultimately, Roger may follow it.

But it may be too complicated at the moment to have such an advanced data handling. Or not?

Ioannis

richard
- 8th March 2021, 09:18
its like trying to remove the head off a motor with a shifting spanner.9027
anyone who is serious about these things has a socket wrench in their toolkit
9028
with proper tools things are easy, if your serious you make the investment.
not only that when you have some isr driven serial tools in your kit all sorts of
tasks become possible opening up a whole new vista

Ioannis
- 8th March 2021, 14:19
Totally agree, but Roger is still using On Interrupts...!

Ioannis

flotulopex
- 9th March 2021, 07:47
Hi,

I don't need to stick to interrupts; I just thought this would be a good idea....

The thing is, I don't know the right (or best) "tool" to use and I appreciate your help and comments to take the correct path for my project :wink:

"Ring buffer" is new to me so I'll first have to spend some hours of reading and searching to get more info. My monitor prototype is already in the field and every immediate improvement, the one I may have the skills to make immediately, is the always the best.

So, because of my lack of knowledge (but it is getting better every day), these are the tools I will rely on for now:

9029:D




I think there is no point in hunting down the incoming SMS as they are available in the GSM module.
Having a routine checking the received message list every 5 seconds or so will allow me to start to improve the reliability of my monitor asap.

Richard is right: I'm mixing up things and tracking incoming serial data is actually not that crucial. For any reason, I was focusing on the wrong target....