crucial error in a 90% working hardware uart


Closed Thread
Results 1 to 5 of 5
  1. #1
    Join Date
    Mar 2007
    Posts
    8

    Red face crucial error in a 90% working hardware uart

    Hi guys. Thanks to all that bother reading my question.
    After huge amount of work i wrote the following program (4MHz pic16f876a).Although i can see MessageA and MessageB (when portb.7 is 5volts), and
    HSerout [DEC B0,",",DEC B1,",",DEC B2,13,10] the problem is always tha the latter seems to stop the microcontroller. Although i can see HSerout [DEC B0,",",DEC B1,",",DEC B2,13,10] for a couple of times about in the 4th giving of data i take no response from microcontroller.With a reset everything is fine until another 3-4 giving of data.Has anything to do with overrun buffers? but i have included DEFINE HSER_CLOERR 1 ' automatic clear overrun error . Thanks anyway.....



    INCLUDE "MODEDEFS.BAS"
    DEFINE OSC 4

    B0 VAR WORD
    B1 VAR WORD
    B2 VAR WORD
    B3 VAR WORD
    B4 VAR WORD

    TRISC = %10000000 ' PORTC.7 is the RX input
    ' PORTC.6 is the TX output
    ' Serial communication definition
    ' ===============================
    ' Using internal USART and MAX232 to interface to PC
    '
    DEFINE HSER_RCSTA 90h ' enable serial port,
    ' enable continuous receive

    DEFINE HSER_TXSTA 24h ' enable transmit,
    ' BRGH=1

    DEFINE HSER_BAUD 9600
    DEFINE HSER_CLOERR 1 ' automatic clear overrun error


    RCIF VAR PIR1.5 ' Receive interrupt flag (1=full , 0=empty)
    TXIF VAR PIR1.4 ' Transmit interrupt flag (1=empty, 0=full)

    Pause 10 ' safe start-up delay
    B0=0 '(duty cycle pwm)

    HSerout ["Hi"]
    main:

    IF PORTB.7=1 Then
    GoSub MessageA
    EndIF

    HSerout ["MessageB",13,10]
    HPwm 1,B0,1000
    High PORTB.5
    Pause 1000
    Low PORTB.5
    Pause 1000
    IF (RCIF) AND (PORTB.7=0) Then ' incomming data?
    HSerin [WAIT ("d"),DEC B0,DEC B1,DEC B2]
    HSerout [DEC B0,",",DEC B1,",",DEC B2,13,10] ' send it
    EndIF
    GoTo main

    GoTo main
    MessageA:
    HSerout ["MessageA",13,10]
    HSerout ["MessageA",13,10]
    HSerout ["MessageA",13,10]
    Pause 1000
    HPwm 1,127,1000
    GoTo main
    End

  2. #2
    Join Date
    Sep 2005
    Location
    Campbell, CA
    Posts
    1,107


    Did you find this post helpful? Yes | No

    Default

    It looks like your send routine takes up so much time that it doesn't get back to HSERIN before the receive buffer overflows. Your CLOERR define clears the overflow error, but that also dumps the buffer. As a result, you are losing characters.

    It looks like you need an interrupt-driven receive routine.

    Are the characters coming in continuously, or in bursts?
    Charles Linquist

  3. #3
    Join Date
    Mar 2007
    Posts
    8


    Did you find this post helpful? Yes | No

    Default

    thanx for replying! my characters come continuously.actually one thinks it works excellent but after a while it does nothing! i am desperate.have you any idea how to look to inerrupts uart?

  4. #4
    Join Date
    Sep 2005
    Location
    Campbell, CA
    Posts
    1,107


    Did you find this post helpful? Yes | No

    Default

    If the data really comes in continuosly, at full speed with no breaks, then you are in real trouble, since eventually you will overflow any size buffer you put in your PIC (which is limited by RAM size).

    Is there some way you could send at a baud rate higher (like 2X) than you are receiving? They you would have a chance.

    It would help a bit if you would run a faster oscillator as well (20MHz). And *WHY* are you not using an 18F series part?
    Charles Linquist

  5. #5
    Join Date
    Nov 2005
    Location
    Bombay, India
    Posts
    966


    Did you find this post helpful? Yes | No

    Default

    Charles is right. You are not looking at the serial port while your code is sending MessageA thrice and then pausing for 1000 ms. During that time, whatever comes in is bound to overflow the receive register. Cloerr will mitigate the problem to an extent, but imagine, you just received your "d" and are waiting for the decimal values for B0, B1 or B2. During that time if the input packet has already finished, you're in trouble. That's because the DEC modifier parses numbers only. If it doesn't find a number, either your number read is wrong or it will end up waiting indefinitely on the "d".

    Ideal solution, put in an interrupt routine to capture the incoming serial characters. Catch them to a circular buffer and read that buffer often. How to do it? This is how I would do it....

    Code:
    ' These variables are used to save the machine state on interrupt
    wsave       var byte    $20     SYSTEM          ' location for W if in bank0
    wsave1      var byte    $A0     SYSTEM          ' location for W if in bank1
    wsave2      var byte    $120    SYSTEM          ' location for W if in bank2
    wsave3      var byte    $1A0    SYSTEM          ' location for W if in bank3
    ssave       var byte    BANK0   SYSTEM          ' location for STATUS register
    psave       var byte    BANK0   SYSTEM          ' location for PCLATH register
    fsave       var byte    BANK0   SYSTEM          ' location for FSR register
    intR0       var byte    BANK0   SYSTEM          ' interrupt temporary variables
    intR1       var byte    BANK0   SYSTEM
    
    ' Receive buffer
    RxBuf           var     byte[16]    ' buffer holding received chars
    WrPtr           var     byte        ' write index
    RdPtr           var     byte        ' write index
    
    ' define the interrupt handler
    define      INTHAND     _IntHandler
    
               goto OverInterrupt
    IntHandler:
    '*******************************************************************************
    ' Interrupts can be from a number of sources.  See INTCON p25
    ' We use the following
    ' RBIF - interrupt on RB change
    ' T0IF - Timer0 overflow interrupt
    IntHandler:
    asm   ; identify the interrupt source
          movf  FSR,w
          movwf fsave         ; save the fsr
    
          btfss PIE1,RCIE     ; if enabled and
          goto  EndInt
          btfss PIR1, RCIF    ; receive interrupt?
          goto  EndInt
    RxISR
          movlw   6
          andwf   RCSTA,w           ;FERR(4) + OERR(2)
          btfss   STATUS,Z          ;not set
          bcf     RCSTA,CREN        ;clear errors
          bsf     RCSTA,CREN        ;by putting CREN=0,1
          ;
          movf    _WrPtr, W
          addlw   low (_RxBuf)
          movwf   FSR
          movf    RCREG,w
          movwf   INDF              ;RxBuf[WrPtr]=RCREG
          ;
          incf    _WrPtr
          movlw   0fh
          andwf   _WrPtr
    EndInt
          movf  fsave,w       ;restore the FSR
          movwf FSR
          movf  psave,w       ;restore PCH
          movwf PCLATH
          swapf ssave, W      ;restore STATUS
          movwf STATUS
          swapf wsave, F
          swapf wsave, W      ;restore W
          retfie
    ENDASM
    
    
    ' initialize the serial buffer
    Ser_Init:
      RCSTA=$90             ' Enable serial port & continuous receive
      TXSTA=$20             ' Enable transmit, BRGH = 0
      SPBRG=25              ' 2400 Baud @ 4MHz, 0.0%
      RdPtr=0
      WrPtr=0
      return
    
    ' read a serial character
    Ser_Getc:
      while RdPtr=WrPtr:wend
      gr[0]=RxBuf[RdPtr]
      RdPtr=RdPtr+1
      RdPtr=RdPtr & $0f
      return
    
    ' read the value of a hex digit to gr[0]
    Ser_GetHex:
      gosub Ser_Getc
      if gr[0]>"9"then gr[0]=gr[0]-7
      gr[0]=gr[0]-"0"
      return
    
    ' read the value of 2 hex digits to gr[0]
    Ser_GetHex2:
      gosub Ser_GetHex
      gr[1]=gr[0]<<4
      gosub Ser_GetHex
      gr[0]=gr[1]+gr[0]
      return
    
    ProcessRX:
      while RdPtr <> WrPtr
        gosub Ser_GetC
        if gr[0]="d" then ProcRX10  ' Proceed only after we get the "d"
      wend
      return
    ProcRX10:
    ' process the data here
    This is just a framework and is incomplete. Use it at your own risk.

    Jerson
    Last edited by Jerson; - 23rd September 2008 at 17:11.

Similar Threads

  1. Hardware SPI with MAX3111E
    By KHsu in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 8th August 2007, 01:42

Members who have read this thread : 0

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

Posting Permissions

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