• AVR Freaks

Hot!dsPIC33EV256GM106 (lin protocol )

Author
Badeaa Alsukhni
New Member
  • Total Posts : 8
  • Reward points : 0
  • Joined: 2020/02/10 01:52:47
  • Location: 0
  • Status: offline
2020/02/11 00:45:45 (permalink)
0

dsPIC33EV256GM106 (lin protocol )

Hello all i am using dsPIC33EV256GM106 (lin protocol to read sensor data)
the sensor commands are as below 
1)the sensor write data frame : break+syn+ID(0x38) ,PID(0x78) +data1(0x01)+data2(0x02)+checksum
2)delay 50 ms
3)the sensor read data frame :break+syn+ID(0x01) ,PID(0xC1) and  Will return 8 data bytes.
i checked the sending data by oscilloscope it displays the correct data but found that i receive every transmitted byte. so I'm assuming I have something configured incorrectly in void InitLIN_TX(void); .
 
i noticed from the datasheet that 
URXEN: Receive Enable bit  (can't be enabled). how to solve this problem to allow me receive the response data. 
 
. Any help is appreciated.
 

#include <p33EV256GM106.h>
//
// includes for the header files
//
// port definitions for the starter kit
//
#define LED1 _LATC4
#define TRISLED1 _TRISC4
#define LED2 _LATC5
#define TRISLED2 _TRISC5
#define LED3 _LATC6
#define TRISLED3 _TRISC6
#define TRIS_POT _TRISG6
#define TRIS_TEMP _TRISG7
#define ANSEL_POT _ANSG6
#define ANSEL_TEMP _ANSG7
#define SW1 _RC7
#define SW2 _RC8
#define SW3 _RC9
#define LIN_TXE _LATA8
#define LIN_CS _LATA7
#define ANSEL_LIN _ANSA7
#define TRISLINTXE _TRISA8
#define TRISLINCS _TRISA7
#define FCAN 40000000 // Fcyc = 1/2Fpll
#define LIN_BAUD 19200 
#define LIN_BIT_TIME ((1000000/LIN_BAUD) + 0.5) // 1 bit time calculation in us
#define LIN_BRGVAL ((FCAN/LIN_BAUD)/16) - 1
//#define LIN_ID 0x23 // arbitrary LIN ID byte (with parity = 0xE2)
#define LIN_ID 0x38 // arbitrary LIN ID byte (with parity = 0xE2)

#define LIN_ID3 0x03 // arbitrary LIN ID byte (with parity = 0xE2)
#define LIN_BIT_STUFF 0x4 // number of bit times to stuff 'idle' between bytes
#define BAUD9600 ((FCAN/9600)/16) - 1
#define BAUD19200 ((FCAN/19200)/16) - 1
#define BAUD38400 ((FCAN/38400)/16) - 1 // this is what the demo UART serial baud rate is
#define BAUD576000 ((FCAN/57600)/16) - 1 // selection of transmitter baud rate divisors
#define ANSEL_RTS _ANSE12
#define ANSEL_CTS _ANSE13
#define TRIS_RTS _TRISE12
#define TRIS_MON _TRISB4
#define TRANSMIT 1
#define RECEIVE 0

// Macros for Configuration Fuse Registers
_FOSCSEL(FNOSC_PRIPLL);
_FOSC(FCKSM_CSDCMD & OSCIOFNC_OFF & POSCMD_XT);
// Startup directly into XT + PLL
// OSC2 Pin Function: OSC2 is Clock Output
// Primary Oscillator Mode: XT Crystal

_FWDT(FWDTEN_OFF); // Watchdog Timer Enabled/disabled by user software

_FICD(ICS_PGD2); // PGD3 for external PK3/ICD3/RealIce, use PGD2 for PKOB
_FPOR(BOREN0_OFF); // no brownout detect
_FDMT(DMTEN_DISABLE); // no deadman timer <<< *** New feature, important to DISABLE



//#define STRING_BUFFER_SIZE 64 // arbitrary length message buffer
#define LIN_MESSAGE_SIZE 8 // message size of the received LIN demo message


// Prototype Declarations

//void clearRxFlags(unsigned char buffer_number);
void oscConfig(void);
void clearIntrflags(void);
void init_hw(void);
void delay_10ms(unsigned char num);
void Delayus(int);
void Test_Mode(void);
void LED_Transmit(void);
void InitLIN_TX(void);
void LIN_Transmit(void);
void LIN_Transmit3(void);
void Calc_Checksum(int);



volatile int i;
volatile int f_tick, s_tick, p0, p1, id_byte, data_byte, checksum, lin_index, lin_start;
volatile char lin_rx; // receive message flags
volatile unsigned int LIN_RXBUF[LIN_MESSAGE_SIZE]; // buffer of the received LIN message
unsigned char mode;

volatile int datal;



int main(void)
{

    // Configure Oscillator Clock Source
    oscConfig();

    // Clear Interrupt Flags
    clearIntrflags();

    // Initialize hardware on the board
    init_hw();

    // Test to see if we are in TRANSMIT or RECIEVE mode for the demo, show LEDs
    Test_Mode();

    if (mode == TRANSMIT)
    {
        LED_Transmit();
        
        InitLIN_TX();
     
 
 
 
 
 
 
 
while(1){

        LIN_Transmit();


          delay_10ms(5);  //50 ms
            LIN_Transmit3();
       }
       
    }
}

void clearIntrflags(void)
{
    /* Clear Interrupt Flags */

    IFS0 = 0;
    IFS1 = 0;
    IFS2 = 0;
    IFS3 = 0;
    IFS4 = 0;
    IPC16bits.U1EIP = 6; //service the LIN framing error before the RX
    IPC2bits.U1RXIP = 4;
}

void init_hw(void)
{
    int j;

    // set up the LED and switch ports

    TRISLED1 = 0;
    TRISLED2 = 0;
    TRISLED3 = 0;
    ANSEL_POT = 1;
    ANSEL_TEMP = 1;
    TRIS_POT = 1;
    TRIS_TEMP = 1;
    ANSELC = ANSELC & 0xFC3F; // (re)set the 3 switch bits + CAN due to error in v1.20 header
    s_tick = 0;
    f_tick = 0; // the timer ticks
    lin_index = 0;
    lin_start = 0;
    for (j = 0; j < 8; j++)
    {
        LIN_RXBUF[j] = 0;
    }

    //
    // Timer 1 to generate an interrupt every 250ms
    //
    T1CONbits.TON = 0; // Disable Timer1
    T1CONbits.TCS = 0; // Select internal instruction cycle clock
    T1CONbits.TGATE = 0; // Disable Gated Timer mode
    T1CONbits.TCKPS = 0x3; // Select 1:256 Prescaler
    PR1 = 39062; // Load the period value (250ms/(256*25ns))
    IPC0bits.T1IP = 0x03; // Set Timer 1 Interrupt Priority Level
    IFS0bits.T1IF = 0; // Clear Timer 1 Interrupt Flag
    IEC0bits.T1IE = 1; // Enable Timer1 interrupt

    //
    // Timer 2 to generate an interrupt every 10ms
    //
    T2CONbits.TON = 0; // Disable Timer2
    T2CONbits.TCS = 0; // Select internal instruction cycle clock
    T2CONbits.TGATE = 0; // Disable Gated Timer mode
    T2CONbits.TCKPS = 0x3; // Select 1:256 Prescaler
    TMR2 = 0x00; // Clear timer register
    PR2 = 1562; // Load the period value (10ms/(256*25ns))
    IPC1bits.T2IP = 0x02; // Set Timer 2 Interrupt Priority Level
    IFS0bits.T2IF = 0; // Clear Timer 2 Interrupt Flag
    IEC0bits.T2IE = 1; // Enable Timer2 interrupt

    T2CONbits.TON = 1; // Start Timer2
    T1CONbits.TON = 1; // Start Timer1
}

void Test_Mode(void)
{
    mode = TRANSMIT;
}

void LED_Transmit(void)
{
    //
    // sequence LEDs on & off as a power-up test
    //
    LED1 = 1;
    LED2 = 0;
    LED3 = 0;
    //
    // wait 200ms, turn on LED2
    //
    delay_10ms(20);
    LED2 = 1;
    //
    // wait 200ms, turn on LED3
    //
    delay_10ms(20);
    LED3 = 1;
    //
    // wait 500ms, turn off LED3
    //
    delay_10ms(50);
    LED3 = 0;
    //
    // wait 200ms, turn off LED2
    //
    delay_10ms(20);
    LED2 = 0;
    //
    // wait 200ms, turn off LED1
    //
    delay_10ms(20);
    LED1 = 0;
}

void oscConfig(void)
{

    // Configure Oscillator to operate the device at 80MHz/40MIPs
    // Fosc= Fin*M/(N1*N2), Fcy=Fosc/2
    // Fosc= 8M*40/(2*2)=80Mhz for 8M input clock
    // To be safe, always load divisors before feedback
    
   
    CLKDIVbits.PLLPOST = 0; // N1=2
    CLKDIVbits.PLLPRE = 0; // N2=2
    PLLFBD = 38; // M=(40-2), Fcyc = 40MHz for ECAN baud timer


    // Disable Watch Dog Timer

    RCONbits.SWDTEN = 0;

}

void InitLIN_TX(void)
 
 
 
{
 
 
 
ANSEL_LIN = 0;
TRISLINTXE = 0;
TRISLINCS = 0;
LIN_TXE = 1; // enable LIN transmitter
LIN_CS = 1; // enable LIN interface MCP2021A
//
// map LIN_TX pin to port RD6, which is remappable RP70
// map LIN_RX pin to port RD8, which is remappable RPI72
//
RPOR8bits.RP70R = 0x01; // map LIN transmitter to pin RD6, hi byte
_TRISD6 = 0; // digital output pin
 
 
 
RPINR18 = 0x48; // map LIN receiver to pin RD8
_TRISD8 = 1; // digital input pin
//
// set up the UART for LIN_BRGVAL baud, 1 start, 1 stop, no parity
//
U1MODEbits.STSEL = 0; // 1-Stop bit
U1MODEbits.PDSEL = 0; // No Parity, 8-Data bits
U1MODEbits.ABAUD = 0; // Auto-Baud disabled
U1MODEbits.BRGH = 0; // Standard-Speed mode
U1BRG = LIN_BRGVAL; // Baud Rate setting for 9600
U1STAbits.UTXISEL0 = 1; // Interrupt after one TX done //1 //0
U1STAbits.UTXISEL1 = 0;
IEC0bits.U1TXIE = 1; // Enable Transmit Interrupts

// IEC0bits.U1TXIE = 1; // Enable UART TX interrupt
// U1MODEbits.UARTEN = 1; // Enable UART (this bit must be set *BEFORE* UTXEN)
 
 
 
U1STAbits.URXISEL=0;
U1STAbits.URXISEL=0;
IEC0bits.U1RXIE = 1; // Enable Receive Interrupts
//U1STAbits.URXEN = 1;

U1MODEbits.UARTEN = 1; // enable The UART module must set before UTXEN (Transmit Enable)
 
 
 
U1STAbits.UTXEN = 1; /// UARTx Transmit Enable bit
 
 
 


}



void LIN_Transmit(void)
{
// putsU2("***TRANSMITTING using LIN 0**********");
    //
    // send break followed by 0x55 'autobaud' byte
    //
    while (U1STAbits.TRMT == 0); // wait for transmitter empty
    while (U1STAbits.UTXBRK == 1); // wait for HW to clear the previous BREAK
    U1STAbits.UTXEN = 1; // Enable UART TX
    U1STAbits.UTXBRK = 1; // set the BREAK bit
    U1TXREG = 0; // dummy write to trigger UART transmit
 
 
 
while (U1STAbits.TRMT == 0);    // wait for transmitter empty
    Nop(); // must wait 1 instruction cycle
    U1TXREG = 0x55; // AUTO-BAUD sync character per J2602 spec

    //
    // send the LIN_MESSAGE_ID byte, is arbitrary but must be in the range 0x00 to 0x3B
    // there are also 2 parity bits sent
    p0 = (LIN_ID & 0x01) ^ ((LIN_ID & 0x02) >> 1) ^ ((LIN_ID & 0x04) >> 2) ^ ((LIN_ID & 0x10) >> 4);
    p0 = p0 & 0x01; // get bit value
    p1 = ~(((LIN_ID & 0x02) >> 1) ^ ((LIN_ID & 0x08) >> 3) ^ ((LIN_ID & 0x10) >> 4) ^ ((LIN_ID & 0x20) >> 5));
    p1 = p1 & 0x01; // get the bit value
    //
    // form protected ID byte and transmit it
    // the bit stuffing is optional, used here to test LIN receiver hardware
    //
    while (U1STAbits.TRMT == 0); // wait for transmitter empty
  // Delayus(LIN_BIT_TIME * LIN_BIT_STUFF); // wait for idle time stuff
    id_byte = (p1 << 7) | (p0 << 6) | LIN_ID; // stuff parity bits into proper places
    U1TXREG = id_byte; // transmit the protected ID byte
  // Delayus(LIN_BIT_TIME * LIN_BIT_STUFF); // wait for idle time stuff
    
    //
    checksum = id_byte; // initial checksum value (limited to a byte value)
    
    // form Byte #1
    
    data_byte = 0x0F; // switch data, leading zeros
    Calc_Checksum(data_byte);
    while (U1STAbits.TRMT == 0); // wait for transmitter empty
    U1TXREG = data_byte; // send it
    //
    // form Byte #2
    //
    data_byte = 0x00; // upper byte, temperature reading
    Calc_Checksum(data_byte);
    while (U1STAbits.TRMT == 0); // wait for transmitter empty
  // Delayus(LIN_BIT_TIME * LIN_BIT_STUFF); // wait for idle time stuff
    U1TXREG = data_byte; // send it
    
// the last byte in the frame is the checksum
    
    checksum = (~checksum) & 0xFF; // invert, byte value
    while (U1STAbits.TRMT == 0); // wait for transmitter empty
  // Delayus(LIN_BIT_TIME * LIN_BIT_STUFF); // wait for idle time stuff
    U1TXREG = checksum; // send it
}

void LIN_Transmit3(void)
{
// putsU2("***TRANSMITTING using LIN 0**********");
    //
    // send break followed by 0x55 'autobaud' byte
    //
    while (U1STAbits.TRMT == 0); // wait for transmitter empty
    while (U1STAbits.UTXBRK == 1); // wait for HW to clear the previous BREAK
    U1STAbits.UTXEN = 1; // Enable UART TX
    U1STAbits.UTXBRK = 1; // set the BREAK bit
    U1TXREG = 0; // dummy write to trigger UART transmit
 
 
 
while (U1STAbits.TRMT == 0);    // wait for transmitter empty
    Nop(); // must wait 1 instruction cycle
    U1TXREG = 0x55; // AUTO-BAUD sync character per J2602 spec

//
    // send the LIN_MESSAGE_ID byte, is arbitrary but must be in the range 0x00 to 0x3B
    // there are also 2 parity bits sent
    p0 = (LIN_ID3 & 0x01) ^ ((LIN_ID3 & 0x02) >> 1) ^ ((LIN_ID3 & 0x04) >> 2) ^ ((LIN_ID3 & 0x10) >> 4);
    p0 = p0 & 0x01; // get bit value
    p1 = ~(((LIN_ID3 & 0x02) >> 1) ^ ((LIN_ID3 & 0x08) >> 3) ^ ((LIN_ID3 & 0x10) >> 4) ^ ((LIN_ID3 & 0x20) >> 5));
    p1 = p1 & 0x01; // get the bit value
    //
    // form protected ID byte and transmit it
    // the bit stuffing is optional, used here to test LIN receiver hardware
    //
    while (U1STAbits.TRMT == 0); // wait for transmitter empty
   // Delayus(LIN_BIT_TIME * LIN_BIT_STUFF); // wait for idle time stuff
    id_byte = (p1 << 7) | (p0 << 6) | LIN_ID3; // stuff parity bits into proper places
    U1TXREG = id_byte; // transmit the protected ID byte
}

void Calc_Checksum(int data_byte)
{
    checksum = checksum + data_byte; // add next
    if (checksum > 0xFF)
    {
        checksum = (checksum & 0xFF) + 1; // truncate and add carry bit
    }
}

void delay_10ms(unsigned char num)
{
    f_tick = 0; //f_tick increments every 10ms
    while (f_tick < num); // wait here until 'num' ticks occur
    f_tick = 0;
}

void Delayus(int delay)
{
    int i;
    for (i = 0; i < delay; i++)
    {
        __asm__ volatile ("repeat #39");
        __asm__ volatile ("nop");
    }
}


/* code for Timer1 ISR, called every 250ms*/
void __attribute__((__interrupt__, no_auto_psv)) _T1Interrupt(void)
{
    s_tick++; // increment the 'slow tick'

    IFS0bits.T1IF = 0; //Clear Timer1 interrupt flag

}

/* code for Timer2 ISR, called every 10ms*/
void __attribute__((__interrupt__, no_auto_psv)) _T2Interrupt(void)
{
    f_tick++; // we increment the variable f_tick

    IFS0bits.T2IF = 0; //Clear Timer2 interrupt flag

}



void __attribute__((interrupt, no_auto_psv)) _U1TXInterrupt(void)
{
    while (U1STAbits.TRMT == 0); // wait for transmitter empty
    IFS0bits.U1TXIF = 0; // Clear TX1 Interrupt flag
}


void __attribute__((interrupt, no_auto_psv)) _U1RXInterrupt(void)
{
 
 
 
if(U1STAbits.URXDA == 1)
{
datal = U1RXREG;
LIN_RXBUF[lin_index] = datal & 0xFF;
lin_index++;
if (lin_index == LIN_MESSAGE_SIZE)
{
lin_index = 0;
}

}
 
 
 


    IFS0bits.U1RXIF = 0; // Clear RX1 Interrupt flag
}

void __attribute__((interrupt, no_auto_psv)) _U1ErrInterrupt(void)
{
    //
    // a LIN 'BREAK' (13 consecutive '0's) will generate a Framing Error
    // ***NOTE*** This ISR MUST be at a higher priority than U1RX ISR in order
    // to test for framing error prior to testing for SYNC byte
    //

    if (U1STAbits.FERR == 1)
    {
        lin_start = 1; // first message detection phase
    }
    IFS4bits.U1EIF = 0; // Clear LIN Error Flag
}




void __attribute__((interrupt, auto_psv)) _DefaultInterrupt(void)
{
    LED1 = 1;
    LED2 = 1;
    LED3 = 1;

    while (1);
}

void __attribute__((interrupt, auto_psv)) _OscillatorFail(void)
{
    LED1 = 1;
    LED2 = 1;
    LED3 = 1;

    while (1);
}

void __attribute__((interrupt, no_auto_psv)) _MathError(void)
{
    LED1 = 1;
    LED2 = 1;
    LED3 = 1;

    while (1);
}

void __attribute__((interrupt, no_auto_psv)) _StackError(void)
{
    LED1 = 1;
    LED2 = 1;
    LED3 = 1;

    while (1);
}

void __attribute__((interrupt, no_auto_psv)) _AddressError(void)
{
    LED1 = 1;
    LED2 = 1;
    LED3 = 1;

    while (1);

}




post edited by Badeaa Alsukhni - 2020/02/16 01:09:02
#1

6 Replies Related Threads

    du00000001
    Just Some Member
    • Total Posts : 3477
    • Reward points : 0
    • Joined: 2016/05/03 13:52:42
    • Location: Germany
    • Status: offline
    Re: dsPIC33EV256GM106 (lin protocol ) 2020/02/13 14:05:26 (permalink)
    0
    Might be I missed it, but I can't see the general interrupt enable.
    Could as well be you missed it ...

    PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
    #2
    Badeaa Alsukhni
    New Member
    • Total Posts : 8
    • Reward points : 0
    • Joined: 2020/02/10 01:52:47
    • Location: 0
    • Status: offline
    Re: dsPIC33EV256GM106 (lin protocol ) 2020/02/16 01:05:00 (permalink)
    0
    hello ,
    what do you mean by the general interrupt enable?
     
    i noticed from the datasheet that 
    URXEN: UARTx Receive Enable bit(1)
    1 = Receive is enabled, UxRX pin is controlled by UARTx
    0 = Receive is disabled, UxRX pin is controlled by the port
     
    and  (This bit is only available in devices supporting Smart Card. Refer to the “Universal Asynchronous
    Receiver Transmitter (UART)” chapter of the specific device data sheet for availability.)
     
    that's why i receive every  transmitted byte.
    but i need just to receive the response data how to solve this problem???
     
     
    #3
    du00000001
    Just Some Member
    • Total Posts : 3477
    • Reward points : 0
    • Joined: 2016/05/03 13:52:42
    • Location: Germany
    • Status: offline
    Re: dsPIC33EV256GM106 (lin protocol ) 2020/02/19 13:00:19 (permalink)
    0
    Oh - when re-reading the original post, I found I had missed something:
     
    Originally assuming you didn't receive anything (wrong assumption), I now got it: you're receiving too much  Smile
     
    There are basically 2 ways to handle this:
    • Ignore the echo of your own transmissions. (This might be the easiest way to handle this "issue".)
    • Disable the RX interrupt (or the whole RX function) while transmitting. (But don't forget to re-enable it post transmitting.
      This might require to (dummy-) read the RX buffer and clear some status bits (like RX overrun etc.)
     

    PEBKAC / EBKAC / POBCAK / PICNIC (eventually see en.wikipedia.org)
    #4
    JPortici
    Super Member
    • Total Posts : 925
    • Reward points : 0
    • Joined: 2012/11/17 06:27:45
    • Location: Grappaland
    • Status: offline
    Re: dsPIC33EV256GM106 (lin protocol ) 2020/02/20 00:19:33 (permalink)
    1 (1)
    It is expected that you receive the data you send... just look at the hardware. Or if the lin transceiver you are using is a black box, look up on how to make a discrete a lin transceiver. Or maybe looking up how lin works is sufficient.
    What i don't understand from your post is: do you also receive the data from the sensor, after the data you send?
     
    du00000001
    Might be I missed it, but I can't see the general interrupt enable.

    GIE is set in hardware at every reset..
    #5
    Badeaa Alsukhni
    New Member
    • Total Posts : 8
    • Reward points : 0
    • Joined: 2020/02/10 01:52:47
    • Location: 0
    • Status: offline
    Re: dsPIC33EV256GM106 (lin protocol ) 2020/02/25 02:38:19 (permalink)
    0
    JPortici
    for your question, yes i also receive the data from the sensor after the data i had sent
     
    would the following code will solve my issue??
     
     
    void __attribute__((interrupt, no_auto_psv)) _U1RXInterrupt(void)
    {
    datal = U1RXREG;

    if ((datal == 0x38) && (lin_start == 1) && (lin_index == 0))
    {
    lin_start = 2;
    // RX_BUFFER[lin_index] = datal & 0xFF;
    // lin_index++;
    }
    //
    // is part of the LIN message
    else if (lin_start == 2)
    {
    RX_BUFFER[lin_index] = datal & 0xFF; // get the data byte
    lin_index++;
    if (lin_index == LIN_MESSAGE_SIZE)
    {
    lin_start = 0;
    lin_index = 0;

    }

    Rx_Flag++;
    }
    IFS0bits.U1RXIF = 0; // Clear RX1 Interrupt flag
    }
    //
    void __attribute__((interrupt, no_auto_psv)) _U1ErrInterrupt(void)
    {


    if (U1STAbits.FERR == 1)
    {
    lin_start = 1; // first message detection phase
    }
    IFS4bits.U1EIF = 0; // Clear LIN Error Flag
    }
    #6
    Badeaa Alsukhni
    New Member
    • Total Posts : 8
    • Reward points : 0
    • Joined: 2020/02/10 01:52:47
    • Location: 0
    • Status: offline
    Re: dsPIC33EV256GM106 (lin protocol ) 2020/02/25 02:42:33 (permalink)
    0
    du00000001
    could you please edit my code as you suggest above
    i don't got what you mean.
    #7
    Jump to:
    © 2020 APG vNext Commercial Version 4.5