Question

I'm trying to realize the communication of the PC (linux) with a PIC18F4620 for rs232. The Transmition (PIC -> to PC is fine). However, when I try to pass somenthing from the PC to PIC the PIR1bits.RCIF flag is never set and the interrupt does NOT occurs.

That is my (PIC18f) code (one version):

/*
 * sdcc --use-non-free -mpic16 -p18f4620 test_lcd_serial.c
 * stty -F /dev/ttyUSB0 9600
*/

#include <pic18fregs.h>
#include <pic18f4620.h>
#include <delay.h>
#include <stdio.h>
#include <usart.h>
#include "lcd.c"

//__code char __at 0x300000   _conf0 = 0x00;
//~ __code char __at __CONFIG1H _conf1 = 0x06;// oscilador HS-PLL
__code char __at __CONFIG1H _conf1 = 0x02;// oscilador HS
__code char __at __CONFIG2L _conf2 = 0x1e;
__code char __at __CONFIG2H _conf3 = 0x1e;
__code char __at 0x300004   _conf4 = 0x00;
__code char __at __CONFIG3H _conf5 = 0x01;
__code char __at __CONFIG4L _conf6 = 0x81;
__code char __at 0x300007   _conf7 = 0x00;
__code char __at __CONFIG5L _conf8 = 0x0f;
__code char __at __CONFIG5H _conf9 = 0xc0;
__code char __at __CONFIG6L _confA = 0x0f;
__code char __at __CONFIG6H _confB = 0xe0;
__code char __at __CONFIG7L _confC = 0x0f;
__code char __at __CONFIG7H _confD = 0x40;

char buf[255];

void main(void)
{
    unsigned char count;
    unsigned char caracter;

    lcd_init( FOURBIT_MODE );
    lcd_home();lcd_puts("Start Test"); delay_s(1);
    lcd_home();lcd_puts("Start Test."); delay_s(1);
    lcd_home();lcd_puts("Start Test.."); delay_s(1);
    lcd_home();lcd_puts("Start Test..."); delay_s(1);

    INTCONbits.GIE  = 1;
    INTCONbits.PEIE = 1; 

    usart_open(
        USART_TX_INT_OFF & //0x7f
        USART_RX_INT_ON &  //0xff
        USART_BRGH_HIGH &  //0xff
        USART_EIGHT_BIT & // 0xfd
        USART_ASYNCH_MODE, //0xfe
        129 // 9600 at 20MHz
    );
    stdout = STREAM_USART;   

    count = 1;

    while(1){ //This works fine :)
        printf("To PC: %i\r", count);
        sprintf( buf, "Sent: %i", count );
        //even if I print (in LCD) the PIR1bits.RCIF is always 0
        // sprintf( buf, "Sent: %i,%i", count, PIR1bits.RCIF );
        lcd_home();lcd_puts( "                " );
        lcd_home();lcd_puts( buf );
        delay_ms(500);        
        count++;
    } 
}

void printrx(){
    unsigned char pnt = 0;
    while(PIR1bits.RCIF){
        buf[ pnt++ ] = RCREG;

        // clear CREN
        // RCSTAbits.CREN = 0;
        // RCSTAbits.CREN = 1;
    }
    if( pnt ){
        sprintf( buf, "GOT1 %s", buf );
        lcd_home();lcd_puts( "                " );
        lcd_home();lcd_puts( buf );
        delay_ms(1000);
    }
}

void receive_intr1() interrupt 1 { //this is never call
    if( PIR1bits.RCIF )  // serial received
        printrx();
}
void receive_intr2() interrupt 2 {
    if( PIR1bits.RCIF )  // serial received
        printrx();
}

In PC I did:

>cat /dev/ttyUSB
To PC: 1
To PC: 2
To PC: 3
To PC: 4
To PC: 5
To PC: 6
To PC: 7
To PC: 8
To PC: 9
To PC: 10
...

So, PIC to PC is OK. But when I try:

echo "something" > /dev/ttyUSB0

or

cat > /dev/ttyUSB0
something

or even if I write a code to open the /dev/ttyUSB0 as a file and write, use the python serial module, nothing happen.

Was it helpful?

Solution

I have locked at the SDCC usart implementation and it's look fine. However I notice that somethings had been changed recently. (SDCC usart source). So maybe the SDCC usart have errors and I decide implements by myself. So I change the usart code:

   usart_open(
    USART_TX_INT_OFF & //0x7f
    USART_RX_INT_ON &  //0xff
    USART_BRGH_HIGH &  //0xff
    USART_EIGHT_BIT & // 0xfd
    USART_ASYNCH_MODE, //0xfe
    129 // 9600 at 20MHz
);

By a my specific code (8bits, RX with interrupt, no Parity):

// Serial Interrupts
INTCONbits.GIE  = 1;
INTCONbits.PEIE = 1; 
PIE1bits.RCIE = 1;
IPR1bits.RCIP = 0;
PIE1bits.TXIE = 0;
IPR1bits.TXIP = 0;

TRISCbits.TRISC7 = 1; //RX (1:input)
TRISCbits.TRISC6 = 1; //TX (0:output)

//~ TXSTAbits.CSRC  = 0; //Don't  care
TXSTAbits.TX9   = 0;
TXSTAbits.TXEN  = 1;
TXSTAbits.SYNC  = 0;
TXSTAbits.SENDB = 0;
TXSTAbits.BRGH  = 1;
//~ TXSTAbits.TRMT  //Read Only
TXSTAbits.TX9D  = 0;

RCSTAbits.SPEN = 1;
RCSTAbits.RX9  = 0;
//~ RCSTAbits.SREN  = 0; //Don't care
RCSTAbits.CREN  = 1;
//~ RCSTAbits.ADDEN  = 0; //Don't care
//~ RCSTAbits.FERR //Read Only
//~ RCSTAbits.OERR //Read Only
//~ RCSTAbits.RX9D //Read Only


//~ BAUDCONbits.ABDOVF //Read
//~ BAUDCONbits.RCIDL  //Read Only
BAUDCONbits.RXDTP = 0; 
BAUDCONbits.TXCKP = 0; 
BAUDCONbits.BRG16 = 0;
//~ Not implemented
BAUDCONbits.WUE   = 0;
BAUDCONbits.ABDEN = 0;

SPBRG = 129;

stdout = STREAM_USART;   

And all is fine. Can be useful for someone the stty command configure a lot of stuffs related to the device communication. For instance set baudrate to 9600 and disable echo

stty -echo -F /dev/ttyUSB0 9600

Show all configuration

stty -a -F /dev/ttyUSB0
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top