// --------------------------------------------------------------------
// 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.
// --------------------------------------------------------------------
// Please find the software documentation: \docu\documentation.htm
// --------------------------------------------------------------------
#include "main.h"
#include "drv638.h" // driver for MM9Z1-638
#include "nvm.h" // nvm driver
#include <stdio.h> // sprintf
#include "kt9z1_638_evm.h"
#include "ntc.h"
#include "msCANdrv.h"
//---------------------------------------------------------------------
#define TSENSE_EXT CH_T_PTB0 //!< external T-sensor is connected to PTBx
extern TYPE_NTC_CONVERT NTCconvert; //!< lookup table for NTC
//---------------------------------------------------------------------
/*! \brief Structure for Clock configuration for CAN demo
- use external oscillator (4.000MHz) as reference clock (divide by 4)
- 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, latency
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 , 1, 12,
CH_VSENSE1 , 1, 12,
CH_VSENSE0 , 1, 12,
CH_VSENSE3 , 1, 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 , 1 , 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) //!< CAN standby signal
#define NORMALMODE (0) //!< CAN standby signal
#define CAN_STDBY(v) {DDRA_DDRA0 = 1; PTA_PTA0 = (v);} //!< CAN standby signal
// --------------------------------------------------------------------
// --------------------------------------------------------------------
// --------------------------------------------------------------------
void main(void) {
u16 TSensor[tListEntries];
u16 VSensor[vListEntries];
s32 CSensor[cListEntries];
u16 temp = 0;
TYPE_CAN_IBS_Dummy CAN_IBS_Dummy;
TYPE_CAN_IBS_Data CAN_IBS_Data;
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
Bool WriteSystemCalibrationValues = FALSE; // do not change !!!
// LEDs
// LEDModeInit();
// LEDRxInit();
LED3Init();
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)
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;
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
}
ADCInit();
VsenseInit(&(vList[0]), &vListEntries, &(vValues[0]));
CsenseInit(&(cList[0]), &cListEntries, &(cValues[0]));
//TsenseInit(&(tList[0]), &tListEntries, &(tValues[0]));
//GPIOInit();
CAN_STDBY(NORMALMODE); //
// IBS data frame
CAN_IBS_Data.u8Len = 8;
CAN_IBS_Data.u16Volt = 0x00;//u16Swap(0x1234)
CAN_IBS_Data.s32Curr = 0x00; //u32Swap(0)
CAN_IBS_Data.u8CTemp = 0x00;
// IBS dummy frame
CAN_IBS_Dummy.u8Len = 2;
CAN_IBS_Dummy.u16Var = u16Swap(0x1234);
// IBS control frame
CAN_IBS_Control.u8Len = 2;
err_status = Init_CAN(CAN0, FAST); //CMPTX 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
// LEDModeOn();
RTIInit();
RTIEnable();
IrqEnable();
for EVER {
if(RTIEvery100ms()) { //
CAN_IBS_Data.u16Volt = u16Swap(VSensor[3]); // scale to mV
CAN_IBS_Data.s32Curr = u32Swap(CSensor[0]); //CSensor[0]
err_status = Load_CAN_MB(CAN0, CANBUF1, CAN_IBS_Data.byte);
err_status = Transmit_CAN_MB(CAN0, CANBUF1);
LED3Tog();
temp++;
}
// TsenseHandler(); // temperature needs to be done polling (V,I interrupt driven)
//! Measurement results
(void) CsenseGetValue(CH_CSENSE, &CSensor[0]);
(void) VsenseGetValue(CH_VSENSE3, &VSensor[3]);
/* if(VsenseGetValue(CH_VSENSE3, &VSensor[3])) { // if 3rd channel is converted then first 3 are done
(void) TsenseGetValue(CH_TSENSE_ITS, &TSensor[0]); // check for new results ITS
(void) TsenseGetValue(CH_T_PTB0, &TSensor[1]); // check for new results PTB4
(void) VsenseGetValue(CH_VSENSE0, &VSensor[0]); // check for new results
(void) VsenseGetValue(CH_VSENSE1, &VSensor[1]); // check for new results
(void) VsenseGetValue(CH_VSENSE2, &VSensor[2]); // check for new results
}*/
// read message object .....读CAN数据
/* err_status = 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
}
}*/
}
}
// ---------------------------------------------------------------------
/*! \brief Initialises GPIO PTBx pins
<b>Configuration used for the KT9Z1_638_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;
B_GPIO_CTL = GPIO_CTL_PTB2_DISABLE;
B_GPIO_CTL = GPIO_CTL_PTB3_DISABLE;
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
}
// --------------------------------------------------------------------
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);
}