• AVR Freaks

Helpful ReplyEUSART read and write using MCC 3.26.2 and PIC16F1778

Author
PStechPaul
Super Member
  • Total Posts : 2973
  • Reward points : 0
  • Joined: 2006/06/27 16:11:32
  • Location: Cockeysville, MD, USA
  • Status: offline
2017/03/01 16:30:40 (permalink)
0

EUSART read and write using MCC 3.26.2 and PIC16F1778

I am trying to use the EUSART of the PIC16F1778 with interrupts to avoid time delays for transmitting strings, and polling for receiving characters. Here is the code generated by MCC:
(In interrupt_manager.c)    else if(INTCONbits.PEIE == 1 && PIE1bits.TXIE == 1 && PIR1bits.TXIF == 1)
    {
        EUSART_Transmit_ISR();
    }
    else if(INTCONbits.PEIE == 1 && PIE1bits.RCIE == 1 && PIR1bits.RCIF == 1)
    {
        EUSART_Receive_ISR();
    }

(In eusart.c)
static uint8_t eusartTxHead = 0;
static uint8_t eusartTxTail = 0;
static uint8_t eusartTxBuffer[EUSART_TX_BUFFER_SIZE];
volatile uint8_t eusartTxBufferRemaining;

static uint8_t eusartRxHead = 0;
static uint8_t eusartRxTail = 0;
static uint8_t eusartRxBuffer[EUSART_RX_BUFFER_SIZE];
volatile uint8_t eusartRxCount;

uint8_t EUSART_Read(void)
{
    uint8_t readValue  = 0;
    
//    while(0 == eusartRxCount)  // This seems to be a place where it could get stuck
//    {
//    }

    readValue = eusartRxBuffer[eusartRxTail++];
//    rxChar = readValue;  // This was a global variable I added - the code reacts to any non-zero char and sets it to zero
    if(sizeof(eusartRxBuffer) <= eusartRxTail)
    {
        eusartRxTail = 0;
    }
    PIE1bits.RCIE = 0;
    eusartRxCount--;
    PIE1bits.RCIE = 1;

    return readValue;
}

void EUSART_Write(uint8_t txData)
{
//    while(0 == eusartTxBufferRemaining)  //This is where it got stuck
//    {
//    }

    if(0 == PIE1bits.TXIE)
    {
        TX1REG = txData;
    }
    else
    {
        PIE1bits.TXIE = 0;
        eusartTxBuffer[eusartTxHead++] = txData;
        if(sizeof(eusartTxBuffer) <= eusartTxHead)
        {
            eusartTxHead = 0;
        }
        eusartTxBufferRemaining--;
    }
    PIE1bits.TXIE = 1;
}

void EUSART_Transmit_ISR(void)
{

    // add your EUSART interrupt custom code
    if(sizeof(eusartTxBuffer) > eusartTxBufferRemaining)
    {
        TX1REG = eusartTxBuffer[eusartTxTail++];
        if(sizeof(eusartTxBuffer) <= eusartTxTail)
        {
            eusartTxTail = 0;
        }
        eusartTxBufferRemaining++;
    }
    else
    {
        PIE1bits.TXIE = 0;
    }
}

void EUSART_Receive_ISR(void)
{

    if(1 == RC1STAbits.OERR)
    {
        // EUSART error - restart

        RC1STAbits.CREN = 0;
        RC1STAbits.CREN = 1;
    }

    // buffer overruns are ignored
    eusartRxBuffer[eusartRxHead++] = RC1REG;
    if(sizeof(eusartRxBuffer) <= eusartRxHead)
    {
        eusartRxHead = 0;
    }
    eusartRxCount++;
}

I had made a function for writing to the EUSART, but it seemed to hang up using the simulator, until I used alternate code:
void    putsUSART( char* s ) {
    int i;
    int tmo=500;
    for( i = 0; i < strlen(s); i++ ) {
       while(!TX1STAbits.TRMT && tmo>0)
           tmo--;
       if(TX1STAbits.TRMT)
           TX1REG=s[i];
       tmo = 500;
    }
//        EUSART_Write(s[i]);  // This was the original code that got stuck
}

Here is the main code that reads the EUSART or writes to it:
        if(eusartRxCount > 0)
            rxChar = EUSART_Read();
        if( rxChar == '?' )
            id();
        if( rxChar == 'I') {
            break; }
        if( rxChar != 0 ) {
            readCommand();
            rxChar = 0; }
...
putsUSART((const char*)" Error\r\n");

I don't know why the write function got stuck, although I think perhaps the TXIE and/or TXEN were disabled. I think it would be better to remove the possibly endless loops from the read and write functions, or add a timeout mechanism, especially for transmit (write), where a true/false result could be returned based on success or failure.

 
#1
qhb
Superb Member
  • Total Posts : 9999
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: offline
Re: EUSART read and write using MCC 3.26.2 and PIC16F1778 2017/03/01 16:41:44 (permalink)
0
Your alternate code isn't using interrupts for transmit at all.
At first glance, the MCC code looks ok to me.
It is correctly handling disabling TXIE when there's nothing to send, and enabling it when required.
Where exactly is it getting hung up in the simulator?
 
 
#2
coffee critic
Super Member
  • Total Posts : 394
  • Reward points : 0
  • Status: offline
Re: EUSART read and write using MCC 3.26.2 and PIC16F1778 2017/03/01 16:55:04 (permalink)
0
It's possible but unlikely that the duplicate byte errata (1.1) could be causing your issue.  You might try padding your writes with a nop as a quick test.

n_*$
#3
qhb
Superb Member
  • Total Posts : 9999
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: offline
Re: EUSART read and write using MCC 3.26.2 and PIC16F1778 2017/03/01 17:12:27 (permalink)
4 (1)
The suggested workaround is to get the UART TX ISR to block until TRMT is set.
That would destroy the advantage of using interrupts, as it would spent most of its time stuck in the ISR.
I'd be returning those chips quick smart if I required TX interrupts.
 
#4
PStechPaul
Super Member
  • Total Posts : 2973
  • Reward points : 0
  • Joined: 2006/06/27 16:11:32
  • Location: Cockeysville, MD, USA
  • Status: offline
Re: EUSART read and write using MCC 3.26.2 and PIC16F1778 2017/03/01 17:57:36 (permalink)
0
Well, I found a couple problems. First, INTCONbits.PEIE was not set, so the original call to EUSART_Write() got hung up in while(0 == eusartTxBufferRemaining). But I had that commented out. When I fixed the PEIE problem, the ISR got hung up on the TMR2_ISR, which I don't need, because I'm using it for PWM. But the PWM is 200 kHz, so the ISR used up all the processor time with a 14.7456 MHz crystal.
 
Now it "sort of" works, but transmit seems to lose characters. I'll check the errata to see if that's the problem.
 
Thanks.

 
#5
PStechPaul
Super Member
  • Total Posts : 2973
  • Reward points : 0
  • Joined: 2006/06/27 16:11:32
  • Location: Cockeysville, MD, USA
  • Status: offline
Re: EUSART read and write using MCC 3.26.2 and PIC16F1778 2017/03/01 21:52:57 (permalink)
0
I read the errata and it seems to only cause duplicate characters to be sent (and adding the NOP didn't help).
 
http://ww1.microchip.com/downloads/en/DeviceDoc/80000676A.pdf
 
I used the non-interrupt version of transmit and it works fine. The EUSART_Write functions occur in loops where a time delay is not critical. It takes about 1.9 mSec for each character at 9600 baud. That is according to the simulator, which seems to work correctly, sending the first character to TX1REG immediately and the remaining characters via the ISR. So perhaps this is a silicon error?

 
#6
qhb
Superb Member
  • Total Posts : 9999
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: offline
Re: EUSART read and write using MCC 3.26.2 and PIC16F1778 2017/03/01 22:36:58 (permalink)
0
If it's not time critical, then there's no point using interrupts.
 
I'd clean up your routine a little.
void putsUSART( char * s ) {
    int tmo=500;
    while (*s)
    {
        if (tmo-- == 0)
            return; //abort if timeout
        if (PIR1bits.TXIF)
        {
            tmo = 500;    //restart timeout, and also handle errata 1.1
 
            TX1REG=*s++;
        }
    }
}

Ideally there should be a short delay inside the main while loop, so you know roughly how long 500 loops will take for your timeout. 
For that sort of timeout, I usually have a 1 millisecond timer interrupt running, and get the ISR to decrement the timeout variable every millisecond if it's non-zero.
Note I'm using TXIF, not TRMT. That's much more efficient. Reloading the timeout before writing to TX1REG handles the errata requirement for a short delay.
post edited by qhb - 2017/03/01 22:44:54
#7
swmcl
Super Member
  • Total Posts : 273
  • Reward points : 0
  • Joined: 2014/05/10 13:54:42
  • Location: Queensland
  • Status: offline
Re: EUSART read and write using MCC 3.26.2 and PIC16F1778 2017/04/18 02:27:34 (permalink)
0
I'm trying to use the same chip and its UART also.  I'm a little more of a noob though.
Can I ask if there has been a final resolution to the problems?
 
#8
PStechPaul
Super Member
  • Total Posts : 2973
  • Reward points : 0
  • Joined: 2006/06/27 16:11:32
  • Location: Cockeysville, MD, USA
  • Status: offline
Re: EUSART read and write using MCC 3.26.2 and PIC16F1778 2017/04/18 14:54:39 (permalink)
0
I have it working reasonably well. Here is the code:
void EUSART_Write(uint8_t txData)
{
    while(0 == eusartTxBufferRemaining)   // removed PES 3/1/17
    {
    }

    if(0 == PIE1bits.TXIE)
    {
        NOP();
        TX1REG = txData;
    }
    else
    {
        PIE1bits.TXIE = 0;
        eusartTxBuffer[eusartTxHead++] = txData;
        if(sizeof(eusartTxBuffer) <= eusartTxHead)
        {
            eusartTxHead = 0;
        }
        eusartTxBufferRemaining--;
    }
    PIE1bits.TXIE = 1;
}

void    putsUSART( char* s ) {
    int i;
    for( i = 0; i < strlen(s); i++ )
        EUSART_Write(s[i]);
    }
 
// (In main code)
          putsUSART((const char*)" Error\r\n");

I have put this project aside for a while, but will soon return. The interrupt code might need some work. my putsUSART function might be better if it just pushed the characters into a circular queue (LIFO buffer) and then the interrupt could "pop" the characters from the queue and send them whenever the transmit buffer of the USART is empty (TXIF).

 
#9
CinziaG
die fucking humans
  • Total Posts : 3145
  • Reward points : 0
  • Joined: 2016/12/07 14:20:36
  • Location: Wien
  • Status: offline
Re: EUSART read and write using MCC 3.26.2 and PIC16F1778 2017/04/18 15:07:27 (permalink) ☄ Helpfulby swmcl 2017/04/19 12:35:28
0
optimized that:
void    putsUSART( char* s ) {

    while(*s)
        EUSART_Write(*s++);
    }

[:D]

in 2018 you signed for your annihilation. in 2019 it will come ;) I promise
my most wonderful creations here
https://www.youtube.com/c...dPFRvtwsbSTXp6Sk6azGOQ
#10
swmcl
Super Member
  • Total Posts : 273
  • Reward points : 0
  • Joined: 2014/05/10 13:54:42
  • Location: Queensland
  • Status: offline
Re: EUSART read and write using MCC 3.26.2 and PIC16F1778 2017/04/19 12:36:54 (permalink)
3 (1)
Smartie !
#11
Jump to:
© 2020 APG vNext Commercial Version 4.5