PIC16F88 HSERIN to LCD Problem


Closed Thread
Results 1 to 10 of 10
  1. #1
    Join Date
    Jun 2009
    Posts
    4

    Default PIC16F88 HSERIN to LCD Problem

    Hello,

    I have been having problems with the HSERIN instruction on a 16F88 and after too many hours on Google I hope someone can help me.

    I have written a program that will take serial data and output it to an LCD. The program works at 1200 baud but doesn't work at any speed above this. Ideally I would like the baud rate to be 9600 but 1200 is too slow.

    Here is my code:

    Code:
    '-------------------------------------
    ' STARTUP CODE
    '-------------------------------------
    
    @ DEVICE PIC16F88,XT_OSC
    @ DEVICE PIC16F88,PROTECT_OFF
    @ DEVICE PIC16F88,WDT_OFF
    @ DEVICE PIC16F88,PWRT_ON
    @ DEVICE PIC16F88,MCLR_ON
    @ DEVICE PIC16F88,BOD_OFF
    @ DEVICE PIC16F88,LVP_OFF
    @ DEVICE PIC16F88,CPD_OFF
    @ DEVICE PIC16F88,DEBUG_OFF
    @ DEVICE PIC16F88,CCPMX_OFF
    
    ' *THIS SPEED DOESN'T WORK??
    'DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
    'DEFINE HSER_TXSTA 24h ' Enable transmit, BRGH = 1
    'DEFINE HSER_SPBRG 25  ' 9600 Baud @ 0.16%
    'DEFINE HSER_CLROERR 1 ' Clear overflow automatically
    
    ' *THIS SPEED DOES WORK
    DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
    DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 0
    DEFINE HSER_SPBRG 51  ' 1200 Baud @ 0.17%
    DEFINE HSER_CLROERR 1 ' Clear overflow automatically
    
    'Define the LCD
    Define LCD_DREG PORTA
    DEFINE LCD_DBIT 0
    DEFINE LCD_RSREG PORTB
    DEFINE LCD_RSBIT 0
    DEFINE LCD_EREG PORTA
    DEFINE LCD_EBIT 4
    DEFINE LCD_BITS 4
    DEFINE LCD_LINES 2
    'DEFINE LCD_COMMANDUS 1500
    'DEFINE LCD_DATAUS 44
    
    'Register setup
    ADCON1 = %00000111          ' Disable A/D converter
    ANSEL = %00000000           ' all analog pins to digital
    CCP1CON = %00000000         ' Disable CCP Module
    CMCON = %00000111           ' Turn off comparator
    INTCON = %00000000          ' Interrupts disabled
        
    'Clear the ports
    TRISA = %00000000           'All O/P's
    TRISB = %00001101           'All O/P's
    PORTA = 0                   'Zero PortA O/P's
    PORTB = 0                   'Zero PortB O/P's
     
    'Var for RS232 data
    RxData var byte
    
    '-------------------------------------
    ' SPLASH SCREEN
    '-------------------------------------
    SplashScreen:
    
    pause 60   'Power up delay
    
    'Display a splash screen for 2 seconds
    LCDOUT $FE,1,"RS232 to LCD"
    LCDOUT $FE,$C0,"Display Test"
    pause 2000
    
    'Now ready for COMMS...
    LCDOUT $FE,1,"Waiting for PC"
    LCDOUT $FE,$C0,"to send data..."
    
    '-------------------------------------
    ' RS232 TO LCD
    '-------------------------------------
    Main:
    
    
    high PORTB.7        'This is just a test for diagnostics
    hserin [RxData]     'Get the RS232 Data
    low PORTB.7         'This is just a test for diagnostics
    
    lcdout RxData       'Output the data to the LCD
    
    goto Main           'Loop forever

    I have looked at the RS232/LCD data with a digital logic probe and I have attached 2 screen shots from this. One shows 1200 baud and the other 9600 baud. At 1200 baud the timing looks ok but at 9600 it looks like there is not enought time to send the LCD data before another byte of data comes in.

    Does anyone have any ideas how to resolve this issue?

    Thanks,
    robbrownuk
    Attached Images Attached Images   

  2. #2
    Join Date
    Sep 2004
    Location
    montreal, canada
    Posts
    6,898


    Did you find this post helpful? Yes | No

    Default

    Yes, You change the way your receive your Bytes of data, and/or the way you transmit them.

    Knowing how much data you want to display, and how often you receive/refresh them would help.
    Steve

    It's not a bug, it's a random feature.
    There's no problem, only learning opportunities.

  3. #3
    Join Date
    Jun 2009
    Posts
    4


    Did you find this post helpful? Yes | No

    Default

    Hello mister_e,

    Changing how the data is transmitted (by the PC) would be the easiest thing to do but i would like to fix the problem at the receiving end.

    If the program could just handle 34 characters that would be good (16*2 lines and 2 bytes to move to the 2nd line). Currently if i transmit more that 2 bytes of data the LCD shows garbage.
    To demonstrait this as an example: If i send 2 bytes of data [chr("0xFE") & chr("0x01")] this clears the display without any problems. If i send 3 bytes of data [chr("0xFE") & chr("0x01") & "H"] the display clears but instead of displaying the character "H" it displays a garbage character.

    To me this problem seems to be caused by the Rx buffer overflowing, but shouldnt this just make some of the characters disappear. If i sent the text "Hello World" would it not display something like "Heo rl" ???

    Thanks,
    robbrownuk

  4. #4
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    The BIG problem with your particular app is that LCDOUT is just too darn slow to keep up with a continuous incoming stream of serial data at 9600 bps. And were's why...

    At 1200 baud it takes longer for the hardware USART FIFO buffer to fill. This gives you more time for LCDOUT to finish before the 3rd byte is clocked into the hardware USART, which causes a buffer overrun error, and the USART simply stops receiving data.

    At 9600 baud it takes less time to overrun - so you end up with missed characters at the higher baud rate.

    So - if your inbound serial data stream takes < time than it takes to output the string to your LCD, it's just not going to work.

    A couple of options might be to wait until a serial data input array is filled, then send whatever's in the buffer to your LCD, or setup an interrupt to receive characters in the background, then output to the LCD.

    Either way - you'll still want some control over the sending device so you have time to handle sending everything to your LCD, which is going to be a good deal slower than receiving serial data at 9600 bps.

    Check the Receive Overrun Error section of the data sheet for a full explanation.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  5. #5
    Join Date
    Aug 2006
    Location
    Look, behind you.
    Posts
    2,818


    Did you find this post helpful? Yes | No

    Default

    Ah Say, Ugh, Lookie Here !
    http://www.picbasic.co.uk/forum/showthread.php?t=4972 Darrel's post 16, you alter it to fit that 88 chip and you got it. Use a pullup resistor on the Rx line. Ring Buffer up to 64 bytes.
    Last edited by Archangel; - 3rd June 2009 at 03:15.
    If you do not believe in MAGIC, Consider how currency has value simply by printing it, and is then traded for real assets.
    .
    Gold is the money of kings, silver is the money of gentlemen, barter is the money of peasants - but debt is the money of slaves
    .
    There simply is no "Happy Spam" If you do it you will disappear from this forum.

  6. #6
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    Yep. The priority event with the hardware USART is to read or empty the FIFO buffer before it overruns. LCDOUT can handle being interrupted and never appear to miss a beat if you keep the int handler short & sweet.

    And, of course, DT ints make it all relatively painless for the newbie....;o}
    Last edited by Bruce; - 3rd June 2009 at 03:28.
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  7. #7
    Join Date
    Aug 2006
    Location
    Look, behind you.
    Posts
    2,818


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Bruce View Post
    And, of course, DT ints make it all relatively painless for the newbie....;o}
    Even for newbies into their 3rd year as a newbie . . .
    If you do not believe in MAGIC, Consider how currency has value simply by printing it, and is then traded for real assets.
    .
    Gold is the money of kings, silver is the money of gentlemen, barter is the money of peasants - but debt is the money of slaves
    .
    There simply is no "Happy Spam" If you do it you will disappear from this forum.

  8. #8
    Join Date
    Jul 2003
    Posts
    2,405


    Did you find this post helpful? Yes | No

    Default

    Even for newbies into their 3rd year as a newbie . . .
    Heck yes. I'm still a newbie myself....;o}
    Regards,

    -Bruce
    tech at rentron.com
    http://www.rentron.com

  9. #9
    Join Date
    Jun 2009
    Posts
    4


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Joe S. View Post
    Ah Say, Ugh, Lookie Here !
    http://www.picbasic.co.uk/forum/showthread.php?t=4972 Darrel's post 16, you alter it to fit that 88 chip and you got it. Use a pullup resistor on the Rx line. Ring Buffer up to 64 bytes.
    Thanks very much Joe,

    That code looks promising on "post 16", Iíll give it a try and let you know how it goes.

    Thanks,
    robbrownuk

  10. #10
    Join Date
    Jun 2009
    Posts
    4


    Did you find this post helpful? Yes | No

    Thumbs up Success!

    Thanks again Joe. That code worked very well and of course thanks to Darrel Taylor for his DT_INTS code.

    The final code is posted here should anyone need it:

    Code:
    '-------------------------------------
    ' STARTUP CODE
    '-------------------------------------
    
    'MPASM generates an warning because of tabs around the macro (this prevents it)
    @ errorlevel -207
    
    'Config settings for MPASM
    @ __CONFIG _CONFIG1, _HS_OSC & _CP_OFF & _WDT_OFF & _PWRTE_ON & _MCLR_ON & _BODEN_OFF & _LVP_OFF & _CPD_OFF & _DEBUG_OFF & _CCP1_RB0
    
    'Using a 20Mhz XTAL
    define OSC 20
    
    'Register setup
    ADCON1 = %00000111          ' Disable A/D converter
    ANSEL = %00000000           ' all analog pins to digital
    CCP1CON = %00000000         ' Disable CCP Module
    CMCON = %00000111           ' Turn off comparator
    INTCON = %00000000          ' Interrupts disabled
    
    'Setup & Clear the ports
    TRISA = %00000000           'All O/P's
    TRISB = %00001101           'All O/P's
    PORTA = 0                   'Zero PortA O/P's
    PORTB = 0                   'Zero PortB O/P's
    
    '-----------------------------------------------------------------------------
    INCLUDE "DT_INTS-14.bas"
    INCLUDE "ReEnterPBP.bas"     ; Include if using PBP interrupts
    
    ASM
        INT_LIST  macro   ; IntSource,  Label,          Type,       ResetFlag?
            INT_Handler    RX_INT,      _INT_Serin,     PBP,        no
        endm
        INT_CREATE               ; Creates the interrupt processor
    ENDASM
    
    @   INT_ENABLE   RX_INT     ; enable external (INT) interrupts
    '-----------------------------------------------------------------------------
    
    'Setup the hardware USART for 9600 baud
    DEFINE HSER_RCSTA 90h       ' Enable serial port & continuous receive
    DEFINE HSER_TXSTA 24h       ' Enable transmit, BRGH = 1
    DEFINE HSER_SPBRG 129       ' 9600 Baud @ 0.16%
    DEFINE HSER_CLROERR 1       ' Clear overflow automatically
    
    'Define the LCD
    Define LCD_DREG PORTA
    DEFINE LCD_DBIT 0
    DEFINE LCD_RSREG PORTB
    DEFINE LCD_RSBIT 0
    DEFINE LCD_EREG PORTA
    DEFINE LCD_EBIT 4
    DEFINE LCD_BITS 4
    DEFINE LCD_LINES 2
    DEFINE LCD_COMMANDUS 1500
    DEFINE LCD_DATAUS 50
    
    'Alias & Vars
    RCIF VAR PIR1.5             ' Receive  interrupt flag (1=full , 0=empty)
    TXIF VAR PIR1.4             ' Transmit interrupt flag (1=empty, 0=full)
    OERR VAR RCSTA.1            ' Alias OERR (USART Overrun Error Flag)
    CREN VAR RCSTA.4            ' Alias CREN (USART Continuous Receive Enable)
    BufMax CON 64               ' Sets the size of the ring buffer, set up from 32
    Buffer VAR BYTE[BufMax]     ' Array variable for holding received characters
    Ptr_in VAR BYTE             ' Pointer - next empty location in buffer
    Ptr_out VAR BYTE            ' Pointer - location of oldest character in buffer
    Bufchar VAR	BYTE            ' Stores the character retrieved from the buffer
    ErrFlag VAR	BYTE            ' Holds error flags
    ptr_in = 0                  ' Clear buffer pointer (in)
    ptr_out = 0                 ' Clear buffer pointer (out)
    Errflag = 0                 ' Clear error flag
    
    'Skip over the interupt handler & subroutines
    goto ShowSplash
    
    '-------------------------------------
    ' INTERUPT HANDLER
    '-------------------------------------
    
    INT_Serin:                  ' Serial Interrupt routine
    
    IF OERR Then usart_error	' Check for USART errors
    ptr_in = (ptr_in + 1)       ' Increment ptr_in pointer (0 to 63)
    IF ptr_in > (BufMax-1) Then ptr_in = 0	'Reset pointer if outside of buffer
    IF ptr_in = ptr_out Then Buffer_Error	' Check for buffer overrun
    HSerin [buffer[ptr_in]]	    ' Read USART and store data in next empty location
    IF RCIF Then INT_Serin		' Check for another character while we're here
    @ INT_RETURN   		        ; Return to program
    
    Buffer_Error:               ' Error - Run out of buffer space
    
    errflag.1 = 1               ' Set the error flag for software
    
    'Move pointer back to avoid corrupting the buffer.
    ' MIN insures that it ends up within the buffer.	
    ptr_in = (ptr_in - 1) MIN (BufMax - 1)	
    HSerin [buffer[ptr_in]]	    ' Overwrite the last data stored (clear the int.)
    
    USART_Error:                ' Error - USART has overrun (data too fast?)
    
    errflag.0 = 1               ' Set the error flag for hardware	
    @ INT_RETURN   		        ; Return to program
    
    
    '-------------------------------------
    ' Subroutines
    '-------------------------------------
    GetBuf:					    ' move the next character in buffer to bufchar
    
    @ INT_DISABLE  RX_INT       ; Dont want to interupt this, Disable interupts
    
    ptr_out = (ptr_out + 1)     ' Increment ptr_out pointer (0 to 63)                           
    IF ptr_out > (BufMax-1) Then ptr_out = 0  ' Reset pointer if outside of buffer	
    bufchar = buffer[ptr_out]   ' Read buffer location
    
    @ INT_ENABLE  RX_INT        ; All done, Enable interupts
    Return
    
        
    '-------------------------------------
    ' SPLASH SCREEN
    '-------------------------------------
    ShowSplash:
    
    pause 60   'Power up delay
    
    'Display a splash screen for 2 seconds
    LCDOUT $FE,1,"RS232 to LCD"
    LCDOUT $FE,$C0,"Display Test"
    pause 2000
    
    'Now ready for COMMS...
    LCDOUT $FE,1,"Waiting for PC"
    LCDOUT $FE,$C0,"to send data..."
    
    '-------------------------------------
    ' RS232 TO LCD
    '-------------------------------------
    MainLoop:
    
    IF errflag Then ErrorHandler	      ' Handle error if needed
    IF ptr_in = ptr_out Then MainLoop	  ' loop if nothing in buffer
    
    GoSub getbuf        ' Get a character from buffer (stored in bufchar)	        	
    LCDOut bufchar      ' Send the character to LCD	        
    
    goto MainLoop       'Loop forever
    
    '-------------------------------------
    ' Error Handler
    '-------------------------------------
    ErrorHandler:
    
    ' Display error message if buffer has overrun
    IF errflag.1 Then	                  ' Determine the error
        LCDOut $FE,$1,"Buffer Overflow"   ' Display buffer error
    Else
        LCDOut $FE,$1,"USART Overrun"	  ' Display usart error
    EndIF
    		
    errflag = 0			' Reset the error flag
    CREN = 0			' Disable continuous receive to clear overrun flag
    CREN = 1            ' Enable continuous receive
    
    GoTo MainLoop       ' Errors cleared, time to work.

Similar Threads

  1. Newbie? Problem with LCD
    By lew247 in forum mel PIC BASIC Pro
    Replies: 10
    Last Post: - 7th December 2009, 20:48
  2. RX TX modules - intermitent communication
    By ruijc in forum mel PIC BASIC Pro
    Replies: 13
    Last Post: - 11th June 2009, 01:13
  3. PIC HSERIN problem
    By shaiqbashir in forum mel PIC BASIC Pro
    Replies: 10
    Last Post: - 20th July 2008, 12:08
  4. LCD Problem
    By karenhornby in forum General
    Replies: 3
    Last Post: - 19th June 2008, 12:43
  5. Replies: 8
    Last Post: - 7th December 2006, 16:42

Members who have read this thread : 1

You do not have permission to view the list of names.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts