25.5 Application Examples

Short PWM Code (SPC) Support

#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 = 81; // 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 (FPB/2)
    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 = 81;                                 // 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;                        // TICKTIME
    SENT1CON3 = mSyncMin;                        // FRAMETIME
    _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
}