24.5 Application Examples

SENT Transmission (SPC Pulse Reception)

#include <xc.h>
#define FCY (8E+06)
#include <libpic30.h>

#define mFclk (4E+6)
#define mTickTime (50E-6)
#define mFrameTime (25E-3)
#define mSPCPulseWidth (56 * mTickTime)
void InputCapture_configure(void);
void SENT_Tx_configure(void);
uint8_t count = 0;
uint16_t falling_edge_capture = 0, rising_edge_capture = 0,delta,firstRead;
float pulseWidth;

int main(void) {
    SENT_Tx_configure(); // Configure SENT for Transmission
    InputCapture_configure(); // Configure Input Capture
    while (1);
    return 0;
}

void InputCapture_configure(void) {
    _ICM1R = 27; // RP27 as Input Capture 1
    CCP1CON1bits.CCSEL = 1;     // Input capture mode
    CCP1CON1bits.CLKSEL = 0;    // Set the clock source (FPB/2)
    CCP1CON1bits.T32 = 0;       // 16-bit Dual Timer mode
    CCP1CON1bits.MOD = 3;       // Capture every edge of the event
    CCP1CON2bits.ICS = 0;       // Capture rising edge on the Pin
    CCP1CON1bits.OPS = 0;       // Interrupt on every input capture event
    CCP1CON1bits.TMRPS = 0;     // Set the clock pre-scaler (1:1)
    CCP1CON1bits.ON = 1;        // Enable CCP/input capture
    CCP1TMR = 0;
    __delay_ms(10);
    _CCP1IF = 0;               // Clear CCP interrupt flag
    _CCP1IE = 1;               // Enable CCP interrupt
    
}

void SENT_Tx_configure(void) {
    _RP27R = 57; // RP27 as SENT1 output
    SENT1CON1bits.RCVEN = 0;   // Module operates as a transmitter
    SENT1CON1bits.TXM = 1;     // Synchronous Transmit
    SENT1CON1bits.NIBCNT = 6;  // 6 data nibbles per data packet
    SENT1CON1bits.CRCEN = 1;   // CRC is calculated using the J2716 method
    SENT1CON1bits.PPP = 1;    // SENTx messages transmitted with Pause Pulse
    SENT1CON1bits.PS = 0;     // Module clock is FSENT
    SENT1CON2 = ((mTickTime * mFclk) - 1); // TICKTIME
    SENT1CON3 = (mFrameTime / mTickTime); // FRAMETIME
    _SENT1IE = 1; // Enable SENT1 interrupt
    SENT1CON1bits.ON = 1;    // Enable SENT module
    SENT1DATbits.STAT = 0;   // Status Nibble
    SENT1DATbits.DATA1 = 1;  // Data Nibble 1
    SENT1DATbits.DATA2 = 2;  // Data Nibble 2
    SENT1DATbits.DATA3 = 3;  // Data Nibble 3
    SENT1DATbits.DATA4 = 4;  // Data Nibble 4
    SENT1DATbits.DATA5 = 5;  // Data Nibble 5
    SENT1DATbits.DATA6 = 6;  // Data Nibble 6
}

void __attribute__((__interrupt__, __no_auto_psv__)) _CCP1Interrupt(void) {
    
    _CCP1IF = 0; // Clear interrupt flag
    count++;
    if (count == 1) // Falling edge of the SPC pulse
    {
        firstRead = CCP1BUF; 
        falling_edge_capture = CCP1BUF;
    } else if (count == 2)// Raising edge of the SPC pulse
    {
        count = 0; // Clear count
        rising_edge_capture = CCP1BUF;
        if (rising_edge_capture <= falling_edge_capture) {
            delta = (0xFFFF - falling_edge_capture) + rising_edge_capture;// Rollover case
        } else {
            delta = rising_edge_capture - falling_edge_capture;// Non-rollover case
        }
        pulseWidth = delta / mFclk; // Calculate the pulse width
        
        // Check if pulse width is within the range
        if ((mSPCPulseWidth * 1.2) >= pulseWidth && (mSPCPulseWidth * 0.8) <= pulseWidth) {
            _CCP1IE = 0; // Disable CCP interrupt
            CCP1CON1bits.ON = 0; // Disable CCP/input capture
            SENT1STATbits.SYNCTXEN = 1; // Initiate Synchronous Transmission
        }
    }
}

void __attribute__((__interrupt__, __no_auto_psv__)) _SENT1Interrupt(void) {
    _SENT1IF = 0; // Clear SENT1 interrupt flag
    while (SENT1STATbits.PAUSE == 1); // Wait till PAUSE pulse is transmitted
    CCP1CON1bits.ON = 1; // Enable CCP/input capture
    CCP1TMR = 0;
    __delay_ms(1);
    _CCP1IF = 0; // Clear CCP interrupt flag
    _CCP1IE = 1; // Enable CCP interrupt
}

SENT Reception (SPC Pulse Transmission)

#include <xc.h>
#define FCY (8E+6)
#include<libpic30.h>

#define mFclk (4E+6)
#define mTickTime (50E-6)
#define mFrameTime (25E-3)
#define mSyncCount (8 * mFclk * mTickTime)
#define mSyncMin (0.8 * mSyncCount)
#define mSyncMax (1.2 * mSyncCount)
void OutputCompare_configure();
void SENT_RX_configure();
void SendSPCPulse();
uint8_t mReceivedData[7];
uint8_t i;

int main(void) {
    ANSELB = 0;
    _TRISC6 = 1;               // Connect a Pull-Up switch to RC15
    OutputCompare_configure(); // Configure Output Compare
    SENT_RX_configure();       // Configure SENT for Reception
    while(_RC6 == 0);          // Wait till pull-up switch is pressed
    SendSPCPulse();            // Send SPC pulse
    while(1)
    {
        if(SENT1STATbits.RXIDLE == 1) // Check if the line is Idle
        {
            //Receiver can request for SENT data through SendSPCPulse() function
            SendSPCPulse();
        }
    }
    return 0;
}
void OutputCompare_configure(){
    _CCP3IF = 0; // Clear CCP interrupt flag
    _CCP3IE = 1; // Enable CCP interrupt
    // Set MCCP operating mode
    CCP3CON1bits.CCSEL = 0;   // Set MCCP operating mode (OC mode)
    CCP3CON1bits.MOD = 0b100; // Set mode
    //Configure MCCP Timebase
    CCP3CON1bits.T32 = 0;        // Set timebase width (16-bit)
    CCP3CON1bits.TMRSYNC = 0;    // Set timebase synchronization
    CCP3CON1bits.CLKSEL = 0b000; // Set the clock source (FSENT)
    CCP3CON1bits.TMRPS = 0b00;   // Set the clock pre-scaler (1:1)
    CCP3CON1bits.ONESHOT = 1;
    CCP3CON1bits.TRIGEN = 1;    // Set Sync/Triggered mode (Synchronous)
    CCP3CON1bits.SYNC = 0b1001; // Select Sync/Trigger source
    //Configure MCCP output for PWM signal
    CCP3CON2bits.OCAEN = 1;     // Enable desired output signals (OC1A)
    CCP3CON3bits.POLACE = 1;    //Configure output polarity (Active High)
    CCP3CON3bits.OSCNT = 0;
    CCP3TMR = 0x0000;           //Initialize timer prior to enable module.
    CCP3RA = (56 * mTickTime * mFclk); // Set the rising edge compare value
    CCP3RB = (56 * mTickTime * mFclk)*2; // Set the falling edge compare value
    CCP3PR = CCP3RB; //Configure timebase period
    CCP3CON1bits.ON = 1; // Enable MCCP module
}
void SENT_RX_configure()        
{
    _RP26R = 57; // RP26 as SENT1 output
    _SENT1R = 26; // RP26 as SENT1 input
    SENT1CON1bits.RCVEN = 1;  // Module operates as a receiver
    SENT1CON1bits.NIBCNT = 6; // 6 data nibbles per data packet
    SENT1CON1bits.CRCEN = 1;  // CRC is calculated using the J2716 method
    SENT1CON1bits.PPP = 1;    // SENTx messages transmitted with Pause Pulse
    SENT1CON1bits.PS = 0;     // Module clock is FSENT
    SENT1CON1bits.SPCEN = 1;  // Enable SPC
    SENT1CON2 = mSyncMax;     // SYNCMAX
    SENT1CON3 = mSyncMin;     // SYNCMIN
    _SENT1IE = 1; // Enable SENT1 interrupt
    SENT1CON1bits.ON = 1;     // Enable SENT module
}
void SendSPCPulse()
{
    CCP3STATbits.TRSET = 1; // Set the Trigger
    while(CCP3STATbits.CCPTRIG);
}

void __attribute__((__interrupt__,__no_auto_psv__)) _CCP3Interrupt (void)
{
    _CCP3IF = 0; // Clear interrupt flag
    CCP3STATbits.TRSET = 0; // Set the Trigger
    CCP3CON1bits.ON = 0; // Disable MCCP module
}
void __attribute__((__interrupt__,__no_auto_psv__)) _SENT1Interrupt (void)
{
    _SENT1IF = 0; // Clear interrupt flag
    i=0;
    mReceivedData[i++] = SENT1DATbits.STAT; // Read STAT
    mReceivedData[i++] = SENT1DATbits.DATA1; // Read DATA1
    mReceivedData[i++] = SENT1DATbits.DATA2; // Read DATA2
    mReceivedData[i++] = SENT1DATbits.DATA3; // Read DATA3
    mReceivedData[i++] = SENT1DATbits.DATA4; // Read DATA4
    mReceivedData[i++] = SENT1DATbits.DATA5; // Read DATA5
    mReceivedData[i++] = SENT1DATbits.DATA6; // Read DATA6
    while(SENT1STATbits.PAUSE == 1); // Wait till PAUSE pulse is received
    CCP3CON1bits.ON = 1; // Enable MCCP module
}