I am working with CAN transmission on S12ZVC controller, We establish CAN communication between S12ZVC and MICROCHIP CAN analyzer. The data is transmitting from S12ZVC to CAN analyzer is ok and receiving data from CAN analyzer to S12Z is not getting and it is showing OVERRUN problem. Please help me to sort of this problem.
I have attached the screen shot of that error and code. With this error i cannot get the received data.
void main(void) {
u16 TSensor[tListEntries];
u16 VSensor[vListEntries];
s32 CSensor[cListEntries];
TYPE_CAN_IBS_Data CAN_IBS_Data;
TYPE_CAN_IBS_Data_Ext CAN_IBS_Data_Ext;
TYPE_CAN_IBS_CONTROL CAN_IBS_Control;
MSCAN_TYPE_ERROR_CODE err_status; //To store the return value of the driver APIs.
MSCAN_TYPE_STATUS mbStat;
u8 CAN_status[3]; //CAN_status to store channel status,byte 0 store CANCTL0, byte 1 store CANCTL1, byte 2 store CANRFLG
u8 u8ModeTimer;
u32 u32Temp;
static TYPE_BATTERY Battery;
s16 s16Vdrop;
u8 u8WakeUpReason;
u8 u8ChipTemp;
u16 u16Result;
Bool WriteSystemCalibrationValues = FALSE; // do not change !!!
SYS_Init();
CPMUInit(&ClockConf);
D2DInit((TYPE_D2DCLKDIV) ClockConf.D2dDiv);
XirqEnable(); // enable XIRQ -> isrD2DErr() "write-once"
if (B_PCR_CTL_OPM & 2) { // Check if Wake Up from Sleep mode (see page RM3.0 110 Intermediate Mode)
u32Temp = B_ACQ_AHC;
B_PCR_CTL = OPM_SET_NORMAL; // set normal mode
while (!(B_PCR_SRH_WLPMF )) DO_NOTHING; // Wait for Clock Domain Change \! /todo where is this described?
}else{
if(!B_PCR_SR_HWRF) {
PCRReset(); // generate a HWR reset to ensure analog die is in defined state! E.g. debugging might cause strange effects in case bits are set from before //
}
}
B_WD_CTL = WD_OFF;
u8WakeUpReason = 0;
// Evaluate wake up reason
if(B_PCR_SR_WULINF) { // wake up caused by LIN
u8WakeUpReason = 1;
}
if(B_PCR_SR_WUAHTHF) {
u8WakeUpReason = 2;
}
if(B_PCR_SR_WUCALF) {
u8WakeUpReason = 3;
}
if(B_PCR_SR_WUCTHF) { // current threshold
u8WakeUpReason = 4;
}
if(B_PCR_SR_WULTCF) {
u8WakeUpReason = 5;
}
B_PCR_SRH = 0xFF; // clear all flags
PCRInit(ClockConf.PCRprescaler);
SYSStartupTrimming();
//! \brief Set a breakpoint to this line and change the variable WriteSystemCalibrationValues to TRUE in the debugger to write values \ref CalibWrite
if(WriteSystemCalibrationValues) { // hook to manually write system calibration values to eeprom during sw development
CalibWriteManual();
}
if(CalibRead()==FALSE) { // reads system calibration data from EEPROM (if avaliable). needs to be before ADCInit()
CalibDefault(); // otherwise use default values
}
VsenseInit(&(vList[0]), &vListEntries, &(vValues[0]));
CsenseInit(&(cList[0]), &cListEntries, &(cValues[0]));
TsenseInit(&(tList[0]), &tListEntries, &(tValues[0]));
ADCInit();
GPIOInit();
LTCInit();
CAN_STDBY(NORMALMODE);
// IBS control frame
CAN_IBS_Control.u8Len = 2;
err_status = Init_CAN(CAN0, FAST); //Initialization msCAN channel 0, FAST means the reset won't wait until current transmit completed
do{
err_status = Check_CAN_Status(CAN0, CAN_status);
}while ((CAN_status[0] & SYNCH) == 0); //Wait for msCAN channel 0 synchronized to CAN Bus
err_status = Config_CAN_MB(CAN0, CANBUF1, TXDF, CAN_MO1); //configure the msCAN channel 0, buffer 1 to be TXDF mode (transmit dataframe) -> message object 1,see details in "MSCANID.h"
err_status = Config_CAN_MB(CAN0, CANBUF2, TXDF, CAN_MO2); //configure the msCAN channel 0, buffer 2 to be TXDF mode (transmit dataframe) -> message object 2
err_status = Config_CAN_MB(CAN0, CANBUF3, RXDF, CAN_MO3); //configure the msCAN channel 0, buffer 3 to be RXDF mode (receive dataframe) -> message object 3
Battery.tMode = BM_PARKING; // used to get an initial OCV based SoC
SoCInit();
RTIInit();
RTIEnable();
IrqEnable();
u8ModeTimer = 50; // timed mode change from parking -> driving (5*100ms)
//isrCANRx();
for EVER {
switch(Battery.tMode) {
case BM_PARKING:
case BM_DRIVING:
// ----- measurements, voltage, current and temp ------
if(TsenseGetValue(CH_TSENSE_ITS, &TSensor[0])) { // request data
u8ChipTemp = (u8)(TSensor[0]/TSENSE_ITS_INVRES+K2C+40); // scale to deg C with offset 40
}
if(TsenseGetValue(TSENSE_EXT, &TSensor[1])) {
Battery.u16TempK = NTCRaw2Kelvin(NTCconvert, TSensor[1]);
}
if(CsenseGetValue(CH_CSENSE, &CSensor[0])) {
Battery.s32mAFilt = CSensor[0];
}
if(VsenseGetValue(CH_VSENSE2, &VSensor[0])) { // if 0 channel is converted then
#if (ISENSE_GND_REF==ISENSEL)
// ISENSEL is GND reference
s16Vdrop = (s16)(Battery.s32mAFilt/G_SHUNT); // calculated shunt drop voltage
Battery.u16mV = (VSensor[0]>>1) - s16Vdrop; // scale to mV and correct shunt drop voltage
#endif
#if (ISENSE_GND_REF==ISENSEH)
// ISENSEH is GND reference
Battery.u16mV = VSensor[0]>>1; // scale to mV and no correction
#endif
}
if(RTIEvery1000ms()) {
SoCUpdate(&Battery);
TsenseHandler(); // temperature needs to be done polling (V,I interrupt driven)
if(u8ModeTimer>0){ // timed mode change from parking -> driving (5*100ms)
u8ModeTimer--;
}else{
Battery.tMode = BM_DRIVING;
}
// CAN_IBS_Data.FrameLen = 8;
// CAN_IBS_Data.BatVolt = u16Swap(Battery.u16mV); // scale to mV
// CAN_IBS_Data.BatCurr = u32Swap(Battery.s32mAFilt);
// CAN_IBS_Data.BatTemp = (u8)(Battery.u16TempK+K2C+40);
// CAN_IBS_Data.BatMode = Battery.tMode;
// err_status = Load_CAN_MB(CAN0, CANBUF1, CAN_IBS_Data.byte);
// err_status = Transmit_CAN_MB(CAN0, CANBUF1);
CAN_IBS_Data.FrameLen = 0x8;
CAN_IBS_Data.BatVolt = 0x08; // scale to mV
CAN_IBS_Data.BatCurr = 0xF;
CAN_IBS_Data.BatTemp = 0x6;
CAN_IBS_Data.BatMode = 0x09;
err_status = Load_CAN_MB(CAN0, CANBUF1, CAN_IBS_Data.byte);
err_status = Transmit_CAN_MB(CAN0, CANBUF1);
delay(1000);
}
if(RTIEvery1000ms()) {
/*CAN_IBS_Data_Ext.FrameLen = 6;
CAN_IBS_Data_Ext.ChipTemp = u8ChipTemp;
CAN_IBS_Data_Ext.SOC = Battery.u8SoC;
CAN_IBS_Data_Ext.Coulomb = u32Swap(Battery.u32CoulombCnt);
err_status = Load_CAN_MB(CAN0, CANBUF2, CAN_IBS_Data_Ext.byte);
err_status = Transmit_CAN_MB(CAN0, CANBUF2);*/
CAN_IBS_Data_Ext.FrameLen = 6;
CAN_IBS_Data_Ext.ChipTemp = 24;
CAN_IBS_Data_Ext.SOC = 75;
CAN_IBS_Data_Ext.Coulomb = 100;
err_status = Load_CAN_MB(CAN0, CANBUF2, CAN_IBS_Data_Ext.byte);
err_status = Transmit_CAN_MB(CAN0, CANBUF2);
}
break;
case BM_CALIBRATION:
ServiceApp();
break;
default:
break;
}
// CAN reception
while(mbStat.Status != NEWDATA) //Wait for the Receive ISR to finish and change the buffer status, NEWDATA indicates that the buffer has receive a new data
{ //check buffer status
err_status = Check_CAN_MB_Status(0, CANBUF3, &mbStat);
}
err_status = Read_CAN_MB_Data(0, CANBUF3, rec_data);
// read message object .....
//(void) Check_CAN_MB_Status(CAN0, CANBUF3, &mbStat);
/*if(mbStat.Status == NEWDATA) { //Wait for the Receive ISR to finish and change the buffer status, NEWDATA indicates that the buffer has receive a new data
err_status = Read_CAN_MB_Data(CAN0, CANBUF3, CAN_IBS_Control.byte);//Copy the received data in msCAN channel 0 buffer 3 to data_rec;
//err_status = Read_CAN_MB_Data(CAN0, CANBUF3, rec_data);
CAN_IBS_Control.u16Var = u16Swap(CAN_IBS_Control.u16Var);
mbStat.Status = NODATA; //Clear buffer_status[0]
if(CAN_IBS_Control.u16Var&0x8000) { // Goto Sleep Request
// goto sleep
err_status = Sleep_CAN(CAN0, CMPTX); // request CAN channel 0 go to sleep with completing transmission scheduled
do {
err_status = Check_CAN_Status(CAN0,CAN_status); // read the channel 0 status
}while (!(CAN_status[1]&SLPAK)); // wait till SLPAK bit set
B_PCR_WUEH_WUPTB4 = 1; // enable PTB4 wakeup
ADCDisable();
TsenseDisable();
B_GPIO_VSENSE = 0;
CAN_STDBY(STANDBYMODE);
PTA_PTA1 = 0;
PCREnterStopMode();
// .....zzzzzzzzzzz (stop mode)
// after wakeup the code continues to run here....
// but first the D2D Interrupt service routine will be run
B_WD_CTL = WD_OFF;
VsenseInit(&(vList[0]), &vListEntries, &(vValues[0]));
CsenseInit(&(cList[0]), &cListEntries, &(cValues[0]));
TsenseInit(&(tList[0]), &tListEntries, &(tValues[0]));
ADCInit();
CAN_STDBY(NORMALMODE);
}
if(CAN_IBS_Control.u16Var&0x1000) { // Goto Calib mode
Battery.tMode = BM_CALIBRATION;
CAN_IBS_Data.BatMode = Battery.tMode;
err_status = Load_CAN_MB(CAN0, CANBUF1, CAN_IBS_Data.byte);
err_status = Transmit_CAN_MB(CAN0, CANBUF1);
err_status = Config_CAN_MB (CAN0, 8, RXDF, 8);
err_status = Config_CAN_MB (CAN0, 9, TXDF, 9);
}
if(CAN_IBS_Control.u16Var&0x2000) { // Goto normal mode
Battery.tMode = BM_DRIVING;
VsenseInit(&(vList[0]), &vListEntries, &(vValues[0]));
CsenseInit(&(cList[0]), &cListEntries, &(cValues[0]));
TsenseInit(&(tList[0]), &tListEntries, &(tValues[0]));
ADCInit();
}
}*/
} // for EVER
}
Solved! Go to Solution.
Hello @baji,
According to the description here, you use S12ZVC but from your other posts on this issue it seems like you use the MM9Z1638 demo code.
As @nujia mentioned, there is a CAN driver for S12ZVC and an example posted on S12ZVC can be found here:
https://www.nxp.com/docs/en/application-note-software/AN4975SW.zip
Please read the MSCAN registers, I understand CANRFLG_OVRIF gets set.
The whole process is explained in Section 18.4.2.3 Receive Structures in the S12ZVC RM.
Regards,
Daniel
Hello @baji,
According to the description here, you use S12ZVC but from your other posts on this issue it seems like you use the MM9Z1638 demo code.
As @nujia mentioned, there is a CAN driver for S12ZVC and an example posted on S12ZVC can be found here:
https://www.nxp.com/docs/en/application-note-software/AN4975SW.zip
Please read the MSCAN registers, I understand CANRFLG_OVRIF gets set.
The whole process is explained in Section 18.4.2.3 Receive Structures in the S12ZVC RM.
Regards,
Daniel
Hello, do you have a can driver example for S12ZVMC128,if you have can you give ma one , Thank you verymuch
Thank you daniel, i tried you suggested procedure but i am facing the same error(OVERRUN).
I am using RD9Z1_638_4Li Rev 1.2 board and demo code of RD9Z1_638_12VLA_CAN_demo, please help me to sort of this issue and here i am adding demo code.
// --------------------------------------------------------------------
// Copyright (c) 2015, NXP Semiconductors.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// o Redistributions of source code must retain the above copyright notice, this list
// of conditions and the following disclaimer.
//
// o Redistributions in binary form must reproduce the above copyright notice, this
// list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
//
// o Neither the name of NXP Semiconductors nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// --------------------------------------------------------------------
#include "drv638.h" // driver for MM9Z1-638
#include "nvm.h" // nvm driver
#include <stdio.h> // sprintf
#include "main.h"
#include "soc.h"
#include "rd9z1_638_12vc.h"
#include "ntc.h"
#include "service.h"
#include "usercan.h"
#include "msCANdrv.h"
// For CAN bit Timing see AN1798.pdf
// --------------------------------------------------------------------
// This demo software is provided "AS-IS".
// For documentation please see the folder \docu\documentation.html
// --------------------------------------------------------------------
//---------------------------------------------------------------------
/*! \brief Structure for Clock configuration for CAN demo
- use external oscillator (16.000MHz) as reference clock (divide by 16)
- target VCO clock: 50.000MHz
- target core clock: 50.000MHz
- target bus clock : 25.000MHz
- target D2D clock : 25.000MHz
*/
TYPE_CPMU_CONF const ClockConf = {
ClockSrc_EXT,
VCO_RANGE,
SYNR(CLOCK_VCO, CLOCK_REF),
REFCLK_FREQ_1_2_MHZ_RANGE, // Ref is IRC = 1.000MHz
// REFDIV(4), // Refdivider div = 4 (4MHz quarz)
REFDIV(16), // Refdivider div = 16 (16MHz quarz)
POSTDIV(CLOCK_VCO, CLOCK_BUS),
PLL_FREQ_MOD_0_PERCENT,
PCRPRE(CLOCK_D2D), // PCR prescaler
D2DDIV(CLOCK_BUS, CLOCK_D2D)
};
// --------------------------------------------------------------------
//! \brief TSENSE list of channels to convert...
TYPE_TSENSE_LIST const tList[] = {
// ch , avg
CH_TSENSE_ITS , 1, 6, //!< measure internal chip temperature
TSENSE_EXT , 1, 6 //!< measure external temperature sensor (NTC)
};
const u8 tListEntries = sizeof(tList)/sizeof(TYPE_TSENSE_LIST); //!< number of entries in the list above
static u16 tValues[sizeof(tList)/sizeof(TYPE_TSENSE_LIST)]; //!< RAM buffer for the TSENSE module
// --------------------------------------------------------------------
//! \brief VSENSE list of channels to convert...
TYPE_VSENSE_LIST const vList[] = {
// ch , avg , latency
CH_VSENSE2 , 100, 12,
};
const u8 vListEntries = sizeof(vList)/sizeof(TYPE_VSENSE_LIST); //!< number of entries in the list above
static u16 vValues[sizeof(vList)/sizeof(TYPE_VSENSE_LIST)]; //!< RAM buffer for the VSENSE module
// --------------------------------------------------------------------
//! \brief CSENSE list of channels to convert...
TYPE_CSENSE_LIST const cList[] = {
// ch , avg , latency
CH_CSENSE , 100 , 0
};
const u8 cListEntries = sizeof(cList)/sizeof(TYPE_CSENSE_LIST); //!< number of entries in the list above
static s32 cValues[sizeof(cList)/sizeof(TYPE_CSENSE_LIST)]; //!< RAM buffer for the TSENSE module
/*// --------------------------------------------------------------------
// PTA0 is connected to MC33901 STB pin
#define STANDBYMODE (1)
#define NORMALMODE (0)
#define CAN_STDBY(v) {DDRA_DDRA0 = 1; PTA_PTA0 = (v);}
*/
// --------------------------------------------------------------------
// PTA0 is connected to MC33901 STB pin
#define STANDBYMODE (1)
#define NORMALMODE (0)
#define CAN_STDBY(v) {DDRA_DDRA6 = 1; PTA_PTA6 = (v);}
// ---------------------------------------------------------------------
// private prototypes
void GPIOInit(void);
void LTCInit(void);
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
void main(void) {
u16 TSensor[tListEntries];
u16 VSensor[vListEntries];
s32 CSensor[cListEntries];
TYPE_CAN_IBS_Data CAN_IBS_Data;
TYPE_CAN_IBS_Data_Ext CAN_IBS_Data_Ext;
TYPE_CAN_IBS_CONTROL CAN_IBS_Control;
MSCAN_TYPE_ERROR_CODE err_status; //To store the return value of the driver APIs.
MSCAN_TYPE_STATUS mbStat;
u8 CAN_status[3]; //CAN_status to store channel status,byte 0 store CANCTL0, byte 1 store CANCTL1, byte 2 store CANRFLG
u8 u8ModeTimer;
u32 u32Temp;
static TYPE_BATTERY Battery;
s16 s16Vdrop;
u8 u8WakeUpReason;
u8 u8ChipTemp;
u16 u16Result;
Bool WriteSystemCalibrationValues = FALSE; // do not change !!!
SYS_Init();
CPMUInit(&ClockConf);
D2DInit((TYPE_D2DCLKDIV) ClockConf.D2dDiv);
XirqEnable(); // enable XIRQ -> isrD2DErr() "write-once"
if (B_PCR_CTL_OPM & 2) { // Check if Wake Up from Sleep mode (see page RM3.0 110 Intermediate Mode)
u32Temp = B_ACQ_AHC;
B_PCR_CTL = OPM_SET_NORMAL; // set normal mode
while (!(B_PCR_SRH_WLPMF )) DO_NOTHING; // Wait for Clock Domain Change \! /todo where is this described?
}else{
if(!B_PCR_SR_HWRF) {
PCRReset(); // generate a HWR reset to ensure analog die is in defined state! E.g. debugging might cause strange effects in case bits are set from before //
}
}
B_WD_CTL = WD_OFF;
u8WakeUpReason = 0;
// evaluate wakeup reason
if(B_PCR_SR_WULINF) { // wakeup caused by LIN
u8WakeUpReason = 1;
}
if(B_PCR_SR_WUAHTHF) {
u8WakeUpReason = 2;
}
if(B_PCR_SR_WUCALF) {
u8WakeUpReason = 3;
}
if(B_PCR_SR_WUCTHF) { // current threshold
u8WakeUpReason = 4;
}
if(B_PCR_SR_WULTCF) {
u8WakeUpReason = 5;
}
B_PCR_SRH = 0xFF; // clear all flags
PCRInit(ClockConf.PCRprescaler);
SYSStartupTrimming();
//! \brief Set a breakpoint to this line and change the variable WriteSystemCalibrationValues to
//TRUE in the debugger to write values \ref CalibWrite
if(WriteSystemCalibrationValues) { // hook to manually write system calibration values to eeprom during sw development
CalibWriteManual();
}
if(CalibRead()==FALSE) { // reads system calibration data from EEPROM (if avaliable). needs to be before ADCInit()
CalibDefault(); // otherwise use default values
}
VsenseInit(&(vList[0]), &vListEntries, &(vValues[0]));
CsenseInit(&(cList[0]), &cListEntries, &(cValues[0]));
TsenseInit(&(tList[0]), &tListEntries, &(tValues[0]));
ADCInit();
GPIOInit();
LTCInit();
CAN_STDBY(NORMALMODE);
// IBS control frame
CAN_IBS_Control.u8Len = 2;
err_status = Init_CAN(CAN0, FAST); //Initialization msCAN channel 0, FAST means the reset won't wait until current transmit completed
do{
err_status = Check_CAN_Status(CAN0, CAN_status);
}while ((CAN_status[0] & SYNCH) == 0); //Wait for msCAN channel 0 synchronized to CAN Bus
err_status = Config_CAN_MB(CAN0, CANBUF1, TXDF, CAN_MO1); //configure the msCAN channel 0, buffer 1 to be TXDF mode
//(transmit dataframe) -> message object 1,see details in "MSCANID.h"
err_status = Config_CAN_MB(CAN0, CANBUF2, TXDF, CAN_MO2); //configure the msCAN channel 0, buffer 2 to be TXDF mode (transmit dataframe) -> message object 2
err_status = Config_CAN_MB(CAN0, CANBUF3, RXDF, CAN_MO3); //configure the msCAN channel 0, buffer 3 to be RXDF mode (receive dataframe) -> message object 3
Battery.tMode = BM_PARKING; // used to get an initial OCV based SoC
SoCInit();
RTIInit();
RTIEnable();
IrqEnable();
//XirqEnable();
u8ModeTimer = 5; // timed mode change from parking -> driving (5*100ms)
for EVER {
switch(Battery.tMode) {
case BM_PARKING:
case BM_DRIVING:
// ----- measurements, voltage, current and temp ------
if(TsenseGetValue(CH_TSENSE_ITS, &TSensor[0])) { // request data
u8ChipTemp = (u8)(TSensor[0]/TSENSE_ITS_INVRES+K2C+40);// scale to deg C with offset 40
}
if(TsenseGetValue(TSENSE_EXT, &TSensor[1])) {
Battery.u16TempK = NTCRaw2Kelvin(NTCconvert, TSensor[1]);
}
if(CsenseGetValue(CH_CSENSE, &CSensor[0])) {
Battery.s32mAFilt = CSensor[0];
}
if(VsenseGetValue(CH_VSENSE2, &VSensor[0])) { // if 0 channel is converted then
#if (ISENSE_GND_REF==ISENSEL)
// ISENSEL is GND reference
s16Vdrop = (s16)(Battery.s32mAFilt/G_SHUNT); // calculated shunt drop voltage
Battery.u16mV = (VSensor[0]>>1) - s16Vdrop; // scale to mV and correct shunt drop voltage
#endif
#if (ISENSE_GND_REF==ISENSEH)
// ISENSEH is GND reference
Battery.u16mV = VSensor[0]>>1; // scale to mV and no correction
#endif
}
if( !RTIEvery100ms()) {
SoCUpdate(&Battery);
TsenseHandler(); // temperature needs to be done polling (V,I interrupt driven)
if(u8ModeTimer>0) { // timed mode change from parking -> driving (5*100ms)
u8ModeTimer--;
}else{
Battery.tMode = BM_DRIVING;
}
CAN_IBS_Data.FrameLen = 8;
CAN_IBS_Data.BatVolt = u16Swap(Battery.u16mV); // scale to mV
CAN_IBS_Data.BatCurr = u32Swap(Battery.s32mAFilt);
CAN_IBS_Data.BatTemp = (u8)(Battery.u16TempK+K2C+40);
CAN_IBS_Data.BatMode = Battery.tMode;
err_status = Load_CAN_MB(CAN0, CANBUF1, CAN_IBS_Data.byte);
err_status = Transmit_CAN_MB(CAN0, CANBUF1);
}
if( !RTIEvery1000ms()) {
CAN_IBS_Data_Ext.FrameLen = 6;
CAN_IBS_Data_Ext.ChipTemp = u8ChipTemp;
CAN_IBS_Data_Ext.SOC = Battery.u8SoC;
CAN_IBS_Data_Ext.Coulomb = u32Swap(Battery.u32CoulombCnt);
err_status = Load_CAN_MB(CAN0, CANBUF2, CAN_IBS_Data_Ext.byte);
err_status = Transmit_CAN_MB(CAN0, CANBUF2);
}
break;
case BM_CALIBRATION:
ServiceApp();
break;
default:
break;
}
// read message object .....
(void) Check_CAN_MB_Status(CAN0, CANBUF3, &mbStat);
if(mbStat.Status == NEWDATA) { //Wait for the Receive ISR to finish and change the buffer status, NEWDATA indicates that the buffer has receive a new data
err_status = Read_CAN_MB_Data(CAN0, CANBUF3, CAN_IBS_Control.byte);//Copy the received data in msCAN channel 0 buffer 2 to data_rec;
CAN_IBS_Control.u16Var = u16Swap(CAN_IBS_Control.u16Var);
mbStat.Status = NODATA; //Clear buffer_status[0]
if(CAN_IBS_Control.u16Var&0x8000) { // Goto Sleep Request
// goto sleep
err_status = Sleep_CAN(CAN0, CMPTX); // request CAN channel 0 go to sleep with completing transmission scheduled
do {
err_status = Check_CAN_Status(CAN0,CAN_status); // read the channel 0 status
}while (!(CAN_status[1]&SLPAK)); // wait till SLPAK bit set
B_PCR_WUEH_WUPTB4 = 1; // enable PTB4 wakeup
ADCDisable();
TsenseDisable();
B_GPIO_VSENSE = 0;
CAN_STDBY(STANDBYMODE);
PTA_PTA1 = 0;
PCREnterStopMode();
// .....zzzzzzzzzzz (stop mode)
// after wakeup the code continues to run here....
// but first the D2D Interrupt service routine will be run
B_WD_CTL = WD_OFF;
VsenseInit(&(vList[0]), &vListEntries, &(vValues[0]));
CsenseInit(&(cList[0]), &cListEntries, &(cValues[0]));
TsenseInit(&(tList[0]), &tListEntries, &(tValues[0]));
ADCInit();
CAN_STDBY(NORMALMODE);
}
if(CAN_IBS_Control.u16Var&0x1000) { // Goto Calib mode
Battery.tMode = BM_CALIBRATION;
CAN_IBS_Data.BatMode = Battery.tMode;
err_status = Load_CAN_MB(CAN0, CANBUF1, CAN_IBS_Data.byte);
err_status = Transmit_CAN_MB(CAN0, CANBUF1);
err_status = Config_CAN_MB (CAN0, 8, RXDF, 8);
err_status = Config_CAN_MB (CAN0, 9, TXDF, 9);
}
if(CAN_IBS_Control.u16Var&0x2000) { // Goto normal mode
Battery.tMode = BM_DRIVING;
VsenseInit(&(vList[0]), &vListEntries, &(vValues[0]));
CsenseInit(&(cList[0]), &cListEntries, &(cValues[0]));
TsenseInit(&(tList[0]), &tListEntries, &(tValues[0]));
ADCInit();
}
}
} // for EVER
}
// ---------------------------------------------------------------------
/*! \brief Init GPIO
<b>Configuration used for the RD9Z1_638_12VLA_CAN_Demo:</b>
| Pin | Enabled | Direction | Routing | used for |
|:----------:|:--------:|:---------:|:-------:|------------------------------------|
| PTB0 | - | - | | analog input |
| PTB1 | disabled | n.a. | | not used |
| PTB2 | disabled | n.a. | | not used |
| PTB3 | disabled | n.a. | | not used |
| PTB4 | enabled | input | PTWU | CAN PHY wake up input |
| PTB5/GNDSW | - | - | - | GND switch for TSENSE_EXT |
*/
void GPIOInit(void) {
B_GPIO_CTL = GPIO_CTL_PTB1_DISABLE | GPIO_CTL_PTB1_INPUT;
B_GPIO_CTL = GPIO_CTL_PTB2_DISABLE | GPIO_CTL_PTB2_INPUT;
B_GPIO_CTL = GPIO_CTL_PTB3_DISABLE | GPIO_CTL_PTB3_INPUT;
B_GPIO_CTL = GPIO_CTL_PTB4_ENABLE; // PTB4 is used for CAN Wakeup
B_GPIO_IN4 = IN4_PTWU|IN4_NWUE; // enable WU in low power mode, negative edge
}
// ---------------------------------------------------------------------
/*! \brief
*
*/
void LTCInit(void) {
B_LTC_CTL = B_LTC_CTL_LTCEM_MASK | B_LTC_CTL_LTCE_MASK; // LTC enable, no interrupt
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// --------------------------------------------------------------------
interrupt VectorNumber_Vcan0wkup void isrCANWakeup(void) {
CAN_Wakeup(CAN0);
}
// --------------------------------------------------------------------
interrupt VectorNumber_Vcan0err void isrCANErr(void) {
CAN_ERR(CAN0);
}
// --------------------------------------------------------------------
interrupt VectorNumber_Vcan0tx void isrCANTx(void) {
CAN_Transmit(CAN0);
}
// --------------------------------------------------------------------
interrupt VectorNumber_Vcan0rx void isrCANRx(void) {
CAN_Receive(CAN0);
}
I think there are three things to pay attention to
1. //enable RX interrupt
CAN0RIER_RXFIE = 1;
2. //CAN message reception interrupt
void interrupt VectorNumber_Vcan0rx CAN_ISR() {
3.Can analyzer does send a can message.
You can use the oscilloscope to confirm that the can message is sent correctly.
and you can refer to AN4795 Using MSCAN on the MagniV Family – Application Note
Thank you nujia, i tried you suggested procedure but i am facing the same error(OVERRUN).
I am using RD9Z1_638_4Li Rev 1.2 board and demo code of RD9Z1_638_12VLA_CAN_demo, please help me to sort of this issue and here i am adding demo code.
// --------------------------------------------------------------------
// Copyright (c) 2015, NXP Semiconductors.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// o Redistributions of source code must retain the above copyright notice, this list
// of conditions and the following disclaimer.
//
// o Redistributions in binary form must reproduce the above copyright notice, this
// list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
//
// o Neither the name of NXP Semiconductors nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// --------------------------------------------------------------------
#include "drv638.h" // driver for MM9Z1-638
#include "nvm.h" // nvm driver
#include <stdio.h> // sprintf
#include "main.h"
#include "soc.h"
#include "rd9z1_638_12vc.h"
#include "ntc.h"
#include "service.h"
#include "usercan.h"
#include "msCANdrv.h"
// For CAN bit Timing see AN1798.pdf
// --------------------------------------------------------------------
// This demo software is provided "AS-IS".
// For documentation please see the folder \docu\documentation.html
// --------------------------------------------------------------------
//---------------------------------------------------------------------
/*! \brief Structure for Clock configuration for CAN demo
- use external oscillator (16.000MHz) as reference clock (divide by 16)
- target VCO clock: 50.000MHz
- target core clock: 50.000MHz
- target bus clock : 25.000MHz
- target D2D clock : 25.000MHz
*/
TYPE_CPMU_CONF const ClockConf = {
ClockSrc_EXT,
VCO_RANGE,
SYNR(CLOCK_VCO, CLOCK_REF),
REFCLK_FREQ_1_2_MHZ_RANGE, // Ref is IRC = 1.000MHz
// REFDIV(4), // Refdivider div = 4 (4MHz quarz)
REFDIV(16), // Refdivider div = 16 (16MHz quarz)
POSTDIV(CLOCK_VCO, CLOCK_BUS),
PLL_FREQ_MOD_0_PERCENT,
PCRPRE(CLOCK_D2D), // PCR prescaler
D2DDIV(CLOCK_BUS, CLOCK_D2D)
};
// --------------------------------------------------------------------
//! \brief TSENSE list of channels to convert...
TYPE_TSENSE_LIST const tList[] = {
// ch , avg
CH_TSENSE_ITS , 1, 6, //!< measure internal chip temperature
TSENSE_EXT , 1, 6 //!< measure external temperature sensor (NTC)
};
const u8 tListEntries = sizeof(tList)/sizeof(TYPE_TSENSE_LIST); //!< number of entries in the list above
static u16 tValues[sizeof(tList)/sizeof(TYPE_TSENSE_LIST)]; //!< RAM buffer for the TSENSE module
// --------------------------------------------------------------------
//! \brief VSENSE list of channels to convert...
TYPE_VSENSE_LIST const vList[] = {
// ch , avg , latency
CH_VSENSE2 , 100, 12,
};
const u8 vListEntries = sizeof(vList)/sizeof(TYPE_VSENSE_LIST); //!< number of entries in the list above
static u16 vValues[sizeof(vList)/sizeof(TYPE_VSENSE_LIST)]; //!< RAM buffer for the VSENSE module
// --------------------------------------------------------------------
//! \brief CSENSE list of channels to convert...
TYPE_CSENSE_LIST const cList[] = {
// ch , avg , latency
CH_CSENSE , 100 , 0
};
const u8 cListEntries = sizeof(cList)/sizeof(TYPE_CSENSE_LIST); //!< number of entries in the list above
static s32 cValues[sizeof(cList)/sizeof(TYPE_CSENSE_LIST)]; //!< RAM buffer for the TSENSE module
/*// --------------------------------------------------------------------
// PTA0 is connected to MC33901 STB pin
#define STANDBYMODE (1)
#define NORMALMODE (0)
#define CAN_STDBY(v) {DDRA_DDRA0 = 1; PTA_PTA0 = (v);}
*/
// --------------------------------------------------------------------
// PTA0 is connected to MC33901 STB pin
#define STANDBYMODE (1)
#define NORMALMODE (0)
#define CAN_STDBY(v) {DDRA_DDRA6 = 1; PTA_PTA6 = (v);}
// ---------------------------------------------------------------------
// private prototypes
void GPIOInit(void);
void LTCInit(void);
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
void main(void) {
u16 TSensor[tListEntries];
u16 VSensor[vListEntries];
s32 CSensor[cListEntries];
TYPE_CAN_IBS_Data CAN_IBS_Data;
TYPE_CAN_IBS_Data_Ext CAN_IBS_Data_Ext;
TYPE_CAN_IBS_CONTROL CAN_IBS_Control;
MSCAN_TYPE_ERROR_CODE err_status; //To store the return value of the driver APIs.
MSCAN_TYPE_STATUS mbStat;
u8 CAN_status[3]; //CAN_status to store channel status,byte 0 store CANCTL0, byte 1 store CANCTL1, byte 2 store CANRFLG
u8 u8ModeTimer;
u32 u32Temp;
static TYPE_BATTERY Battery;
s16 s16Vdrop;
u8 u8WakeUpReason;
u8 u8ChipTemp;
u16 u16Result;
Bool WriteSystemCalibrationValues = FALSE; // do not change !!!
SYS_Init();
CPMUInit(&ClockConf);
D2DInit((TYPE_D2DCLKDIV) ClockConf.D2dDiv);
XirqEnable(); // enable XIRQ -> isrD2DErr() "write-once"
if (B_PCR_CTL_OPM & 2) { // Check if Wake Up from Sleep mode (see page RM3.0 110 Intermediate Mode)
u32Temp = B_ACQ_AHC;
B_PCR_CTL = OPM_SET_NORMAL; // set normal mode
while (!(B_PCR_SRH_WLPMF )) DO_NOTHING; // Wait for Clock Domain Change \! /todo where is this described?
}else{
if(!B_PCR_SR_HWRF) {
PCRReset(); // generate a HWR reset to ensure analog die is in defined state! E.g. debugging might cause strange effects in case bits are set from before //
}
}
B_WD_CTL = WD_OFF;
u8WakeUpReason = 0;
// evaluate wakeup reason
if(B_PCR_SR_WULINF) { // wakeup caused by LIN
u8WakeUpReason = 1;
}
if(B_PCR_SR_WUAHTHF) {
u8WakeUpReason = 2;
}
if(B_PCR_SR_WUCALF) {
u8WakeUpReason = 3;
}
if(B_PCR_SR_WUCTHF) { // current threshold
u8WakeUpReason = 4;
}
if(B_PCR_SR_WULTCF) {
u8WakeUpReason = 5;
}
B_PCR_SRH = 0xFF; // clear all flags
PCRInit(ClockConf.PCRprescaler);
SYSStartupTrimming();
//! \brief Set a breakpoint to this line and change the variable WriteSystemCalibrationValues to
//TRUE in the debugger to write values \ref CalibWrite
if(WriteSystemCalibrationValues) { // hook to manually write system calibration values to eeprom during sw development
CalibWriteManual();
}
if(CalibRead()==FALSE) { // reads system calibration data from EEPROM (if avaliable). needs to be before ADCInit()
CalibDefault(); // otherwise use default values
}
VsenseInit(&(vList[0]), &vListEntries, &(vValues[0]));
CsenseInit(&(cList[0]), &cListEntries, &(cValues[0]));
TsenseInit(&(tList[0]), &tListEntries, &(tValues[0]));
ADCInit();
GPIOInit();
LTCInit();
CAN_STDBY(NORMALMODE);
// IBS control frame
CAN_IBS_Control.u8Len = 2;
err_status = Init_CAN(CAN0, FAST); //Initialization msCAN channel 0, FAST means the reset won't wait until current transmit completed
do{
err_status = Check_CAN_Status(CAN0, CAN_status);
}while ((CAN_status[0] & SYNCH) == 0); //Wait for msCAN channel 0 synchronized to CAN Bus
err_status = Config_CAN_MB(CAN0, CANBUF1, TXDF, CAN_MO1); //configure the msCAN channel 0, buffer 1 to be TXDF mode
//(transmit dataframe) -> message object 1,see details in "MSCANID.h"
err_status = Config_CAN_MB(CAN0, CANBUF2, TXDF, CAN_MO2); //configure the msCAN channel 0, buffer 2 to be TXDF mode (transmit dataframe) -> message object 2
err_status = Config_CAN_MB(CAN0, CANBUF3, RXDF, CAN_MO3); //configure the msCAN channel 0, buffer 3 to be RXDF mode (receive dataframe) -> message object 3
Battery.tMode = BM_PARKING; // used to get an initial OCV based SoC
SoCInit();
RTIInit();
RTIEnable();
IrqEnable();
//XirqEnable();
u8ModeTimer = 5; // timed mode change from parking -> driving (5*100ms)
for EVER {
switch(Battery.tMode) {
case BM_PARKING:
case BM_DRIVING:
// ----- measurements, voltage, current and temp ------
if(TsenseGetValue(CH_TSENSE_ITS, &TSensor[0])) { // request data
u8ChipTemp = (u8)(TSensor[0]/TSENSE_ITS_INVRES+K2C+40);// scale to deg C with offset 40
}
if(TsenseGetValue(TSENSE_EXT, &TSensor[1])) {
Battery.u16TempK = NTCRaw2Kelvin(NTCconvert, TSensor[1]);
}
if(CsenseGetValue(CH_CSENSE, &CSensor[0])) {
Battery.s32mAFilt = CSensor[0];
}
if(VsenseGetValue(CH_VSENSE2, &VSensor[0])) { // if 0 channel is converted then
#if (ISENSE_GND_REF==ISENSEL)
// ISENSEL is GND reference
s16Vdrop = (s16)(Battery.s32mAFilt/G_SHUNT); // calculated shunt drop voltage
Battery.u16mV = (VSensor[0]>>1) - s16Vdrop; // scale to mV and correct shunt drop voltage
#endif
#if (ISENSE_GND_REF==ISENSEH)
// ISENSEH is GND reference
Battery.u16mV = VSensor[0]>>1; // scale to mV and no correction
#endif
}
if( !RTIEvery100ms()) {
SoCUpdate(&Battery);
TsenseHandler(); // temperature needs to be done polling (V,I interrupt driven)
if(u8ModeTimer>0) { // timed mode change from parking -> driving (5*100ms)
u8ModeTimer--;
}else{
Battery.tMode = BM_DRIVING;
}
CAN_IBS_Data.FrameLen = 8;
CAN_IBS_Data.BatVolt = u16Swap(Battery.u16mV); // scale to mV
CAN_IBS_Data.BatCurr = u32Swap(Battery.s32mAFilt);
CAN_IBS_Data.BatTemp = (u8)(Battery.u16TempK+K2C+40);
CAN_IBS_Data.BatMode = Battery.tMode;
err_status = Load_CAN_MB(CAN0, CANBUF1, CAN_IBS_Data.byte);
err_status = Transmit_CAN_MB(CAN0, CANBUF1);
}
if( !RTIEvery1000ms()) {
CAN_IBS_Data_Ext.FrameLen = 6;
CAN_IBS_Data_Ext.ChipTemp = u8ChipTemp;
CAN_IBS_Data_Ext.SOC = Battery.u8SoC;
CAN_IBS_Data_Ext.Coulomb = u32Swap(Battery.u32CoulombCnt);
err_status = Load_CAN_MB(CAN0, CANBUF2, CAN_IBS_Data_Ext.byte);
err_status = Transmit_CAN_MB(CAN0, CANBUF2);
}
break;
case BM_CALIBRATION:
ServiceApp();
break;
default:
break;
}
// read message object .....
(void) Check_CAN_MB_Status(CAN0, CANBUF3, &mbStat);
if(mbStat.Status == NEWDATA) { //Wait for the Receive ISR to finish and change the buffer status, NEWDATA indicates that the buffer has receive a new data
err_status = Read_CAN_MB_Data(CAN0, CANBUF3, CAN_IBS_Control.byte);//Copy the received data in msCAN channel 0 buffer 2 to data_rec;
CAN_IBS_Control.u16Var = u16Swap(CAN_IBS_Control.u16Var);
mbStat.Status = NODATA; //Clear buffer_status[0]
if(CAN_IBS_Control.u16Var&0x8000) { // Goto Sleep Request
// goto sleep
err_status = Sleep_CAN(CAN0, CMPTX); // request CAN channel 0 go to sleep with completing transmission scheduled
do {
err_status = Check_CAN_Status(CAN0,CAN_status); // read the channel 0 status
}while (!(CAN_status[1]&SLPAK)); // wait till SLPAK bit set
B_PCR_WUEH_WUPTB4 = 1; // enable PTB4 wakeup
ADCDisable();
TsenseDisable();
B_GPIO_VSENSE = 0;
CAN_STDBY(STANDBYMODE);
PTA_PTA1 = 0;
PCREnterStopMode();
// .....zzzzzzzzzzz (stop mode)
// after wakeup the code continues to run here....
// but first the D2D Interrupt service routine will be run
B_WD_CTL = WD_OFF;
VsenseInit(&(vList[0]), &vListEntries, &(vValues[0]));
CsenseInit(&(cList[0]), &cListEntries, &(cValues[0]));
TsenseInit(&(tList[0]), &tListEntries, &(tValues[0]));
ADCInit();
CAN_STDBY(NORMALMODE);
}
if(CAN_IBS_Control.u16Var&0x1000) { // Goto Calib mode
Battery.tMode = BM_CALIBRATION;
CAN_IBS_Data.BatMode = Battery.tMode;
err_status = Load_CAN_MB(CAN0, CANBUF1, CAN_IBS_Data.byte);
err_status = Transmit_CAN_MB(CAN0, CANBUF1);
err_status = Config_CAN_MB (CAN0, 8, RXDF, 8);
err_status = Config_CAN_MB (CAN0, 9, TXDF, 9);
}
if(CAN_IBS_Control.u16Var&0x2000) { // Goto normal mode
Battery.tMode = BM_DRIVING;
VsenseInit(&(vList[0]), &vListEntries, &(vValues[0]));
CsenseInit(&(cList[0]), &cListEntries, &(cValues[0]));
TsenseInit(&(tList[0]), &tListEntries, &(tValues[0]));
ADCInit();
}
}
} // for EVER
}
// ---------------------------------------------------------------------
/*! \brief Init GPIO
<b>Configuration used for the RD9Z1_638_12VLA_CAN_Demo:</b>
| Pin | Enabled | Direction | Routing | used for |
|:----------:|:--------:|:---------:|:-------:|------------------------------------|
| PTB0 | - | - | | analog input |
| PTB1 | disabled | n.a. | | not used |
| PTB2 | disabled | n.a. | | not used |
| PTB3 | disabled | n.a. | | not used |
| PTB4 | enabled | input | PTWU | CAN PHY wake up input |
| PTB5/GNDSW | - | - | - | GND switch for TSENSE_EXT |
*/
void GPIOInit(void) {
B_GPIO_CTL = GPIO_CTL_PTB1_DISABLE | GPIO_CTL_PTB1_INPUT;
B_GPIO_CTL = GPIO_CTL_PTB2_DISABLE | GPIO_CTL_PTB2_INPUT;
B_GPIO_CTL = GPIO_CTL_PTB3_DISABLE | GPIO_CTL_PTB3_INPUT;
B_GPIO_CTL = GPIO_CTL_PTB4_ENABLE; // PTB4 is used for CAN Wakeup
B_GPIO_IN4 = IN4_PTWU|IN4_NWUE; // enable WU in low power mode, negative edge
}
// ---------------------------------------------------------------------
/*! \brief
*
*/
void LTCInit(void) {
B_LTC_CTL = B_LTC_CTL_LTCEM_MASK | B_LTC_CTL_LTCE_MASK; // LTC enable, no interrupt
}
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// --------------------------------------------------------------------
interrupt VectorNumber_Vcan0wkup void isrCANWakeup(void) {
CAN_Wakeup(CAN0);
}
// --------------------------------------------------------------------
interrupt VectorNumber_Vcan0err void isrCANErr(void) {
CAN_ERR(CAN0);
}
// --------------------------------------------------------------------
interrupt VectorNumber_Vcan0tx void isrCANTx(void) {
CAN_Transmit(CAN0);
}
// --------------------------------------------------------------------
interrupt VectorNumber_Vcan0rx void isrCANRx(void) {
CAN_Receive(CAN0);
}