/* ===================================================================*/ LDD_TDeviceData* I2C2_Init(LDD_TUserData *UserDataPtr) { /* Allocate HAL device structure */ I2C2_TDeviceData *DeviceDataPrv; /* {Default RTOS Adapter} Driver memory allocation: Dynamic allocation is simulated by a pointer to the static object */ DeviceDataPrv = &DeviceDataPrv__DEFAULT_RTOS_ALLOC; DeviceDataPrv->UserData = UserDataPtr; /* Store the RTOS device structure */ /* Allocate interrupt vector */ /* {Default RTOS Adapter} Set interrupt vector: IVT is static, ISR parameter is passed by the global variable */ INT_I2C0__DEFAULT_RTOS_ISRPARAM = DeviceDataPrv; DeviceDataPrv->SerFlag = 0x00U; /* Reset all flags */ DeviceDataPrv->SendStop = LDD_I2C_SEND_STOP; /* Set variable for sending stop condition (for master mode) */ DeviceDataPrv->InpLenM = 0x00U; /* Set zero counter of data of reception */ DeviceDataPrv->OutLenM = 0x00U; /* Set zero counter of data of transmission */ /* SIM_SCGC4: I2C0=1 */ SIM_SCGC4 |= SIM_SCGC4_I2C0_MASK; /* I2C0_C1: IICEN=0,IICIE=0,MST=0,TX=0,TXAK=0,RSTA=0,WUEN=0,DMAEN=0 */ I2C0_C1 = 0x00U; /* Clear control register */ /* I2C0_FLT: SHEN=0,STOPF=1,STOPIE=0,FLT=0 */ I2C0_FLT = (I2C_FLT_STOPF_MASK | I2C_FLT_FLT(0x00)); /* Clear bus status interrupt flags */ /* I2C0_S: TCF=0,IAAS=0,BUSY=0,ARBL=0,RAM=0,SRW=0,IICIF=1,RXAK=0 */ I2C0_S = I2C_S_IICIF_MASK; /* Clear interrupt flag */ /* PORTE_PCR25: ISF=0,MUX=5 */ PORTE_PCR25 = (uint32_t)((PORTE_PCR25 & (uint32_t)~(uint32_t)( PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x02) )) | (uint32_t)( PORT_PCR_MUX(0x05) )); /* PORTE_PCR24: ISF=0,MUX=5 */ PORTE_PCR24 = (uint32_t)((PORTE_PCR24 & (uint32_t)~(uint32_t)( PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x02) )) | (uint32_t)( PORT_PCR_MUX(0x05) )); /* NVIC_IPR2: PRI_8=0x80 */ NVIC_IPR2 = (uint32_t)((NVIC_IPR2 & (uint32_t)~(uint32_t)( NVIC_IP_PRI_8(0x7F) )) | (uint32_t)( NVIC_IP_PRI_8(0x80) )); /* NVIC_ISER: SETENA|=0x0100 */ NVIC_ISER |= NVIC_ISER_SETENA(0x0100); /* I2C0_C2: GCAEN=0,ADEXT=0,HDRS=0,SBRC=0,RMEN=0,AD=0 */ I2C0_C2 = I2C_C2_AD(0x00); /* I2C0_FLT: SHEN=0,STOPF=0,STOPIE=0,FLT=0 */ I2C0_FLT = I2C_FLT_FLT(0x00); /* Set glitch filter register */ /* I2C0_SMB: FACK=0,ALERTEN=0,SIICAEN=0,TCKSEL=0,SLTF=1,SHTF1=0,SHTF2=0,SHTF2IE=0 */ I2C0_SMB = I2C_SMB_SLTF_MASK; /* I2C0_F: MULT=0,ICR=0 */ I2C0_F = (I2C_F_MULT(0x00) | I2C_F_ICR(0x00)); /* Set prescaler bits */ I2C_PDD_EnableDevice(I2C0_BASE_PTR, PDD_ENABLE); /* Enable device */ I2C_PDD_EnableInterrupt(I2C0_BASE_PTR); /* Enable interrupt */ /* Registration of the device structure */ PE_LDD_RegisterDeviceStructure(PE_LDD_COMPONENT_I2C2_ID,DeviceDataPrv); return ((LDD_TDeviceData *)DeviceDataPrv); /* Return pointer to the data data structure */ }
void TPA6130A2::init_hw(){ if(&I2C == I2C0_BASE_PTR){ SIM_SCGC4 |= SIM_SCGC4_I2C0_MASK; } else if(&I2C == I2C1_BASE_PTR){ SIM_SCGC4 |= SIM_SCGC4_I2C1_MASK; } // Disable by default enabled = false; nSD.clear(); nSD.configure(GPIOPin::MUX_GPIO); nSD.make_output(); SCL.configure(SCL_mux, true, true); SDA.configure(SDA_mux, true, true); I2C.F = I2C_F_MULT(0) | // / 1 = 48MHz I2C_F_ICR(0x27); // / 480 = 100kHz I2C.C1 = I2C_C1_IICEN_MASK; #if CFG_POWER_ALWAYS_ON enable(); #endif }
static uint32_t _ki2c_set_baudrate ( /* [IN] Module input clock in Hz */ uint32_t clock, /* [IN] Desired baudrate in Hz */ uint32_t baudrate ) { #define MAX_ICR 64 uint32_t mult, icr, min, minmult = 0, minicr = 0; int32_t val; min = (uint32_t)-1; /* We will find the nearest smallest diference in desired and real baudrate. ** This is transformed to find smallest clock diference. ** IIC baud rate = bus speed (Hz)/(mul * SCL divider) => ** IIC baud rate * mul * SCL divider <= clock */ for (mult = 0; mult < 3; mult++) { for (icr = 0; icr < MAX_ICR; icr++) { val = BAUDRATE_MULT[mult] * BAUDRATE_ICR[icr] * baudrate - clock; if (val < 0) val = -val; if (min > val) { min = val; minmult = mult; minicr = icr; } } } return I2C_F_MULT(minmult) | I2C_F_ICR(minicr); }
//------------------------------------------------------------ // I2C module config //------------------------------------------------------------ void iI2C_Config(void) { // I2C clock enable // System Clock Gating Control Register 4 (SIM_SCGC4) // K60 Sub-Family Reference Manual, Rev. 2 Jun 2012 page 304 SIM_SCGC4|=SIM_SCGC4_I2C0_MASK; // PTE24 --> SCL I2C0 --> Accéléromètre et magnétomètre FXOS8700CQ PORTE_PCR24 = 0|PORT_PCR_PS_MASK|PORT_PCR_PE_MASK|PORT_PCR_DSE_MASK|(PORT_PCR_MUX(5)); // PTE25 --> SDA I2C0 --> Accéléromètre et magnétomètre FXOS8700CQ PORTE_PCR25 = 0|PORT_PCR_PS_MASK|PORT_PCR_PE_MASK|PORT_PCR_ODE_MASK|PORT_PCR_DSE_MASK|(PORT_PCR_MUX(5)); // PTB2 --> IO input --> interrupt INT1 FXOS8700CQ PORTB_PCR2 = 0|PORT_PCR_PS_MASK|PORT_PCR_ISF_MASK|PORT_PCR_IRQC(0xA)|(PORT_PCR_MUX(1)); // PTB3 --> IO input --> interrupt INT2 FXOS8700CQ PORTB_PCR3 = 0|PORT_PCR_PS_MASK|(PORT_PCR_MUX(1)); // Enable de l'interrupt INT1 de l'accéléromètre enable_irq(INT_PORTB-16); // Baud rate speed and I2C timing // I2C Frequency Divider register (I2Cx_F) // K60 Sub-Family Reference Manual, Rev. 2 Jun 2012 page 1457 // I2C clock rate=390,625 kHz (max 400kHz) // SDA Hold = 0.42us (max 0.9us) // SCL start Hold = 1.16 us (min 0.6us) // SCL stop Hold = 1.3 us (min 0.6us I2C0_F=0; I2C0_F|=I2C_F_ICR(0x17)|I2C_F_MULT(0); }
void i2c_init (void) { /* * this function initializes the I2C bus to use interrupts */ if (i2c_initialize == TRUE) { return; // already initialized } memset(&i2c_buf, 0x00, sizeof(i2c_buf)); /* SIM_SCGC4: I2C0=1 */ SIM_SCGC4 |= SIM_SCGC4_I2C0_MASK; /* I2C0_C1: IICEN=0,IICIE=0,MST=0,TX=0,TXAK=0,RSTA=0,WUEN=0,DMAEN=0 */ I2C0_C1 = 0x00U; /* Clear control register */ /* I2C0_FLT: SHEN=0,STOPF=1,STOPIE=0,FLT=0 */ I2C0_FLT = I2C_FLT_STOPF_MASK; /* Clear bus status interrupt flags */ /* I2C0_S: TCF=0,IAAS=0,BUSY=0,ARBL=0,RAM=0,SRW=0,IICIF=1,RXAK=0 */ I2C0_S = I2C_S_IICIF_MASK; /* Clear interrupt flag */ /* PORTB_PCR1: ISF=0,MUX=2 */ PORTB_PCR1 = (uint32_t)((PORTB_PCR1 & (uint32_t)~(uint32_t)( PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x05) )) | (uint32_t)( PORT_PCR_MUX(0x02) )); /* PORTB_PCR0: ISF=0,MUX=2 */ PORTB_PCR0 = (uint32_t)((PORTB_PCR0 & (uint32_t)~(uint32_t)( PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x05) )) | (uint32_t)( PORT_PCR_MUX(0x02) )); /* NVIC_IPR2: PRI_8=0x80 */ NVIC_IPR2 = (uint32_t)((NVIC_IPR2 & (uint32_t)~(uint32_t)( NVIC_IP_PRI_8(0x7F) )) | (uint32_t)( NVIC_IP_PRI_8(0x80) )); /* NVIC_ISER: SETENA|=0x0100 */ NVIC_ISER |= NVIC_ISER_SETENA(0x0100); /* I2C0_C2: GCAEN=0,ADEXT=0,HDRS=0,SBRC=0,RMEN=0,AD=0 */ I2C0_C2 = 0x00U; /* I2C0_FLT: SHEN=0,STOPF=0,STOPIE=0,FLT=0 */ I2C0_FLT = 0x00U; /* Set glitch filter register */ /* I2C0_SMB: FACK=0,ALERTEN=0,SIICAEN=0,TCKSEL=0,SLTF=1,SHTF1=0,SHTF2=0,SHTF2IE=0 */ I2C0_SMB = I2C_SMB_SLTF_MASK; /* I2C0_F: MULT=0,ICR=2 */ //I2C0_F = I2C_F_ICR(0x02); /* Set prescaler bits */ /* I2C0_F: MULT=0,ICR=F = /68 p.706 of http://cache.freescale.com/files/32bit/doc/ref_manual/KL25P80M48SF0RM.pdf */ I2C0_F = I2C_F_ICR(0x02); //I2C_F_ICR(0x0F); /* Set prescaler bits */ //I2C_PDD_EnableDevice(I2C0_BASE_PTR, PDD_ENABLE); /* Enable device */ #define PDD_ENABLE 1u /* Enable I2C device */ I2C_C1_REG(I2C0_BASE_PTR) = (uint_8) ((I2C_C1_REG(I2C0_BASE_PTR) & ~I2C_C1_IICEN_MASK | 1u << I2C_C1_IICEN_SHIFT)); // TODO: fix this, I am pretty sure |= will work //I2C_PDD_EnableInterrupt(I2C0_BASE_PTR); /* Enable interrupt */ I2C_C1_REG(I2C0_BASE_PTR) |= I2C_C1_IICIE_MASK; i2c_initialize = TRUE; }
/* ===================================================================*/ LDD_TDeviceData* CI2C1_Init(LDD_TUserData *UserDataPtr) { /* Allocate HAL device structure */ CI2C1_TDeviceData *DeviceDataPrv; /* {MQXLite RTOS Adapter} Driver memory allocation: Dynamic allocation is simulated by a pointer to the static object */ DeviceDataPrv = &DeviceDataPrv__DEFAULT_RTOS_ALLOC; DeviceDataPrv->UserData = UserDataPtr; /* Store the RTOS device structure */ /* Allocate interrupt vector */ /* {MQXLite RTOS Adapter} Save old and set new interrupt vector (function handler and ISR parameter) */ /* Note: Exception handler for interrupt is not saved, because it is not modified */ DeviceDataPrv->SavedISRSettings.isrData = _int_get_isr_data(LDD_ivIndex_INT_I2C0); DeviceDataPrv->SavedISRSettings.isrFunction = _int_install_isr(LDD_ivIndex_INT_I2C0, CI2C1_Interrupt, DeviceDataPrv); DeviceDataPrv->SerFlag = 0x00U; /* Reset all flags */ DeviceDataPrv->SendStop = LDD_I2C_SEND_STOP; /* Set variable for sending stop condition (for master mode) */ DeviceDataPrv->InpLenM = 0x00U; /* Set zero counter of data of reception */ DeviceDataPrv->OutLenM = 0x00U; /* Set zero counter of data of transmission */ /* SIM_SCGC4: I2C0=1 */ SIM_SCGC4 |= SIM_SCGC4_I2C0_MASK; /* I2C0_C1: IICEN=0,IICIE=0,MST=0,TX=0,TXAK=0,RSTA=0,WUEN=0,DMAEN=0 */ I2C0_C1 = 0x00U; /* Clear control register */ /* I2C0_S: TCF=0,IAAS=0,BUSY=0,ARBL=0,RAM=0,SRW=0,IICIF=1,RXAK=0 */ I2C0_S = I2C_S_IICIF_MASK; /* Clear interrupt flag */ /* PORTB_PCR1: ISF=0,MUX=2 */ PORTB_PCR1 = (uint32_t)((PORTB_PCR1 & (uint32_t)~(uint32_t)( PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x05) )) | (uint32_t)( PORT_PCR_MUX(0x02) )); PORT_PDD_SetPinOpenDrain(PORTB_BASE_PTR, 0x01u, PORT_PDD_OPEN_DRAIN_ENABLE); /* Set SDA pin as open drain */ /* PORTB_PCR0: ISF=0,MUX=2 */ PORTB_PCR0 = (uint32_t)((PORTB_PCR0 & (uint32_t)~(uint32_t)( PORT_PCR_ISF_MASK | PORT_PCR_MUX(0x05) )) | (uint32_t)( PORT_PCR_MUX(0x02) )); PORT_PDD_SetPinOpenDrain(PORTB_BASE_PTR, 0x00u, PORT_PDD_OPEN_DRAIN_ENABLE); /* Set SCL pin as open drain */ /* NVICIP24: PRI24=0x80 */ NVICIP24 = NVIC_IP_PRI24(0x80); /* NVICISER0: SETENA|=0x01000000 */ NVICISER0 |= NVIC_ISER_SETENA(0x01000000); /* I2C0_C2: GCAEN=0,ADEXT=0,HDRS=0,SBRC=0,RMEN=0,AD=0 */ I2C0_C2 = I2C_C2_AD(0x00); /* I2C0_FLT: ??=0,??=0,??=0,FLT=0 */ I2C0_FLT = I2C_FLT_FLT(0x00); /* Set glitch filter register */ /* I2C0_SMB: FACK=0,ALERTEN=0,SIICAEN=0,TCKSEL=0,SLTF=1,SHTF1=0,SHTF2=0,SHTF2IE=0 */ I2C0_SMB = I2C_SMB_SLTF_MASK; /* I2C0_F: MULT=1,ICR=0x17 */ I2C0_F = (I2C_F_MULT(0x01) | I2C_F_ICR(0x17)); /* Set prescaler bits */ I2C_PDD_EnableDevice(I2C0_BASE_PTR, PDD_ENABLE); /* Enable device */ I2C_PDD_EnableInterrupt(I2C0_BASE_PTR); /* Enable interrupt */ /* Registration of the device structure */ PE_LDD_RegisterDeviceStructure(PE_LDD_COMPONENT_CI2C1_ID,DeviceDataPrv); return ((LDD_TDeviceData *)DeviceDataPrv); /* Return pointer to the data data structure */ }
/*FUNCTION********************************************************************** * * Function Name : I2C_HAL_SetBaudRate * Description : Sets the I2C bus frequency for master transactions. * *END*/ void I2C_HAL_SetBaudRate(I2C_Type * base, uint32_t sourceClockInHz, uint32_t kbps, uint32_t * absoluteError_Hz) { uint32_t mult, i, multiplier, computedRate, absError; uint32_t hz = kbps * 1000u; uint32_t bestError = 0xffffffffu; uint32_t bestMult = 0u; uint32_t bestIcr = 0u; /** Search for the settings with the lowest error. * mult is the MULT field of the I2C_F register, and ranges from 0-2. It selects the * multiplier factor for the divider. */ for (mult = 0u; (mult <= 2u) && (bestError != 0); ++mult) { multiplier = 1u << mult; /** Scan table to find best match.*/ for (i = 0u; i < ARRAY_SIZE(kI2CDividerTable); ++i) { computedRate = sourceClockInHz / (multiplier * kI2CDividerTable[i].sclDivider); absError = hz > computedRate ? hz - computedRate : computedRate - hz; if (absError < bestError) { bestMult = mult; bestIcr = kI2CDividerTable[i].icr; bestError = absError; /** If the error is 0, then we can stop searching * because we won't find a better match.*/ if (absError == 0) { break; } } } } /** Set the resulting error.*/ if (absoluteError_Hz) { *absoluteError_Hz = bestError; } /** Set frequency register based on best settings.*/ I2C_WR_F(base, I2C_F_MULT(bestMult) | I2C_F_ICR(bestIcr)); }
//init i2c0 void i2c_init(void) { //clock i2c peripheral and port E SIM->SCGC4 |= SIM_SCGC4_I2C0_MASK; SIM->SCGC5 |= (SIM_SCGC5_PORTE_MASK); //set pins to I2C function PORTE->PCR[24] |= PORT_PCR_MUX(5); PORTE->PCR[25] |= PORT_PCR_MUX(5); //set to 100k baud //baud = bus freq/(scl_div+mul) //~400k = 24M/(64); icr=0x12 sets scl_div to 64 I2C0->F = (I2C_F_ICR(0x12) | I2C_F_MULT(0)); //enable i2c and set to master mode I2C0->C1 |= (I2C_C1_IICEN_MASK ); }
/** * @brief IIC通信速度设置 内部函数 用户无需使用 * @param instance: IIC模块号 HW_I2C0~2 * @param sourceClockInHz :IIC模块时钟源频率 * @param baudrate :IIC模块通信速度 * @retval None */ static void I2C_SetBaudrate(uint32_t instance, uint32_t sourceClockInHz, uint32_t baudrate) { /* check if the requested frequency is greater than the max supported baud. */ if (baudrate > (sourceClockInHz / (1U * 20U))) { return; } uint32_t mult; uint32_t hz = baudrate; uint32_t bestError = 0xffffffffu; uint32_t bestMult = 0u; uint32_t bestIcr = 0u; /* Search for the settings with the lowest error. mult is the MULT field of the I2C_F register, and ranges from 0-2. It selects the multiplier factor for the divider. */ for (mult = 0u; (mult <= 2u) && (bestError != 0); ++mult) { uint32_t multiplier = 1u << mult; /* scan table to find best match. */ uint32_t i; for (i = 0u; i < ARRAY_SIZE(I2C_DiverTable); ++i) { uint32_t computedRate = sourceClockInHz / (multiplier * I2C_DiverTable[i].sclDivider); uint32_t absError = hz > computedRate ? hz - computedRate : computedRate - hz; if (absError < bestError) { bestMult = mult; bestIcr = I2C_DiverTable[i].icr; bestError = absError; /* If the error is 0, then we can stop searching because we won't find a better match.*/ if (absError == 0) { break; } } } } I2C_InstanceTable[instance]->F = (I2C_F_ICR(bestIcr)|I2C_F_MULT(bestMult)); }
/** * @brief Initialises the I2C interface */ void i2c_init(void) { /* Enable clock to the pins used as SCL(PTE19) and SDA(PTE18) */ SIM->SCGC5 |= SIM_SCGC5_PORTE_MASK; /* Enable clock to I2C => I2C0 is driven by the Bus Clock = 24 MHz*/ SIM->SCGC4 |= SIM_SCGC4_I2C0_MASK; /* Set MUX configuration of PTE18 and PTE19 to I2C */ PORTE->PCR[18] |= PORT_PCR_MUX(4); /* SDA */ PORTE->PCR[19] |= PORT_PCR_MUX(4); /* SCL */ /* Minimum "SCL start hold time" is 0.6 us * Minimum "SCL stop hold time" is 0.6 us. * Minimum "SDA hold time" is 0 us * The resulting Baud Rate is 100 kBd/s */ I2C0->F |= I2C_F_MULT(0); // mul = 1 I2C0->F |= I2C_F_ICR(0x1F); // SCL divider = 240 /* Enable I2C module */ I2C0->C1 |= I2C_C1_IICEN_MASK; }
/*---------------------------------------------------------------------------- MAIN function *----------------------------------------------------------------------------*/ int main (void) { #if USE_VLPR == 1 // enter low power run SIM->CLKDIV1 = (0x1 << SIM_CLKDIV1_OUTDIV1_SHIFT) | (0x5 << SIM_CLKDIV1_OUTDIV4_SHIFT); // reduce core clock < 4 MHz and flash < 1 MHz MCG->C6 &= ~MCG_C6_CME0_MASK; // disable MCG clock monitor MCG->C2 |= MCG_C2_IRCS_MASK; // don't use slow internal reference clock MCG->C1 |= MCG_C1_CLKS(2); // enter BLPE mode MCG->C1 &= ~MCG_C1_IREFS_MASK; MCG->C6 &= ~MCG_C6_PLLS_MASK; while(!(MCG->S & MCG_S_IREFST_MASK >> MCG_S_IREFST_SHIFT)); // wait to ensure clock change MCG->C2 |= MCG_C2_LP_MASK; #endif Init_RGB_LEDs(); #if DEBUG_SIGNALS == 1 Init_Debug_Signals(); #endif // I2C and MMA i2c_init(); /* init i2c */ if (!init_mma()) { /* init mma peripheral */ Control_RGB_LEDs(1, 0, 0); /* Light red error LED */ while (1) /* not able to initialize mma */ ; } #if RUN_I2C_FAST == 1 // increase i2c baud rate I2C_DISABLE; I2C0->F = (I2C_F_ICR(0x00) | I2C_F_MULT(0)); I2C_ENABLE; #endif // configure low power modes SMC->PMPROT = SMC_PMPROT_ALLS_MASK | SMC_PMPROT_AVLP_MASK; // allow low leakage stop mode SMC->PMCTRL = SMC_PMCTRL_RUNM(2) | SMC_PMCTRL_STOPM(3); // enable low power run mode (10) and low leakage stop mode (011) SMC->STOPCTRL = SMC_STOPCTRL_PSTOPO(0) | SMC_STOPCTRL_VLLSM(3); // normal stop mode and VLL stop3 (not needed?) // configure low leakage wakeup unit (LLWU) LLWU->ME |= LLWU_ME_WUME0_MASK; // internal module 0 is wakeup source which is apparently the LPTMR // enable stop mode (deep sleep) SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // LPTMR Init_LPTMR(); Start_LPTMR(); __enable_irq(); while (1) { // read acceleration every 100 ms if (run_Read_Accel){ run_Read_Accel = 0; Read_Accel(); } // update LEDs every 500 ms; keep them on for 10 ms if (run_Update_LEDs){ run_Update_LEDs = 0; Update_LEDs(); #if USE_PWM == 1 #if PWM_SLEEP == 1 SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk; // switch to regular sleep mode #if USE_SLEEP_MODES == 1 #if DEBUG_SIGNALS == 1 PTE->PSOR |= MASK(30); #endif __wfi(); // PWM does not work in LLS mode #endif SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // switch back to LLS mode #else while(led_on_period); // poll -> bad solution #endif #endif } #if USE_SLEEP_MODES == 1 #if DEBUG_SIGNALS == 1 PTE->PSOR |= MASK(30); #endif __wfi(); // go to sleep #endif } }
/*! * @brief I2C初始化,设置波特率 * @param I2Cn_e I2C模块(I2C0、I2C1) * @param baud 期待的波特率 * @return 实际的波特率 * @since v5.0 * Sample usage: i2c_init(I2C0,400*1000); // 初始化I2C0,期待的波特率为400k */ uint32 i2c_init(I2Cn_e i2cn, uint32 baud) { if(i2cn == I2C0) { /* 开启时钟 */ #if defined(MK60DZ10) SIM_SCGC4 |= SIM_SCGC4_I2C0_MASK; //开启 I2C0时钟 #elif defined( MK60F15) SIM_SCGC4 |= SIM_SCGC4_IIC0_MASK; //开启 I2C0时钟 #endif /* 配置 I2C0功能的 GPIO 接口 */ if(I2C0_SCL == PTB0) port_init (PTB0, ALT2 | ODO | PULLUP ); else if(I2C0_SCL == PTB2) port_init (PTB2, ALT2 | ODO | PULLUP ); else if(I2C0_SCL == PTD8) port_init (PTD8, ALT2 | ODO | PULLUP ); else ASSERT(0); //上诉条件都不满足,直接断言失败了,设置管脚有误? if(I2C0_SDA == PTB1) port_init (PTB1, ALT2 | ODO | PULLUP ); else if(I2C0_SDA == PTB3) port_init (PTB3, ALT2 | ODO | PULLUP ); else if(I2C0_SDA == PTD9) port_init (PTD9, ALT2 | ODO | PULLUP ); else ASSERT(0); //上诉条件都不满足,直接断言失败了,设置管脚有误? } else { /* 开启时钟 */ #if defined(MK60DZ10) SIM_SCGC4 |= SIM_SCGC4_I2C1_MASK; //开启 I2C1时钟 #elif defined(MK60F15) SIM_SCGC4 |= SIM_SCGC4_IIC1_MASK; //开启 I2C1时钟 #endif /* 配置 I2C1功能的 GPIO 接口 */ if(I2C1_SCL == PTE1) port_init (PTE1, ALT6 | ODO | PULLUP ); else if(I2C1_SCL == PTC10) port_init (PTC10, ALT2 | ODO | PULLUP ); else ASSERT(0); //上诉条件都不满足,直接断言失败了,设置管脚有误? if(I2C1_SDA == PTE0) port_init (PTE0, ALT6 | ODO | PULLUP ); else if (I2C1_SDA == PTC11) port_init (PTC11, ALT2 | ODO | PULLUP ); else ASSERT(0); //上诉条件都不满足,直接断言失败了,设置管脚有误? } /* 设置频率 */ // I2C baud rate = bus speed (Hz)/(mul × SCL divider) 即这里 50MHz/(1 ×128)=390.625kHz // SDA hold time = bus period (s) × mul × SDA hold value // SCL start hold time = bus period (s) × mul × SCL start hold value // SCL stop hold time = bus period (s) × mul × SCL stop hold value //查表 ICR 对应的 SCL_divider ,见 《K60P144M100SF2RM.pdf》第1468页的 I2C Divider and Hold Values uint16 ICR_2_SCL_divider[0x40] = { 20, 22, 24, 26, 28, 30, 34, 40, 28, 32, 36, 40, 44, 48, 56, 68, 48, 56, 64, 72, 80, 88, 104, 128, 80, 96, 112, 128, 144, 160, 192, 240, 160, 192, 224, 256, 288, 320, 384, 480, 320, 384, 448, 512, 576, 640, 768, 960, 640, 768, 896, 1024, 1152, 1280, 1536, 1920, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3840 }; uint8 mult; if(bus_clk_khz <= 50000)mult = 0; //bus 一分频 else if(bus_clk_khz <= 100000)mult = 1; //bus 二分频 else mult = 2; //bus 四分频 uint16 scldiv = bus_clk_khz * 1000 / ( (mult + 1) * baud ); //最佳的分频系数 //需要从 ICR_2_SCL_divider 里找到 与最佳分频系数scldiv最相近的 分频系数 uint8 icr, n = 0x40; uint16 min_Dvalue = ~0, Dvalue; while(n) //循环里逐个扫描,找出最接近的 分频系数 { n--; Dvalue = abs(scldiv - ICR_2_SCL_divider[n]); if(Dvalue == 0) { icr = n; break; //退出while循环 } if(Dvalue < min_Dvalue) { icr = n; min_Dvalue = Dvalue; } } I2C_F_REG(I2CN[i2cn]) = ( 0 // I2C Frequency Divider register (I2Cx_F) I2C分频寄存器 I2C最大波特率为 400k | I2C_F_MULT(mult) // 乘数因子 mul = MULT + 1 | I2C_F_ICR(icr) // 时钟速率 = ICR_2_SCL_divider[ICR] ,查表获得 ICR 与 SCL_divider 映射关系 ); /* 使能 IIC1 */ I2C_C1_REG(I2CN[i2cn]) = ( 0 | I2C_C1_IICEN_MASK //使能I2C //| I2C_C1_IICIE_MASK //使能中断 ); return ( bus_clk_khz * 1000 / ( (mult + 1) * ICR_2_SCL_divider[icr]) ); }
int i2c_init_master(i2c_t dev, i2c_speed_t speed) { I2C_Type *i2c; PORT_Type *i2c_port; int pin_scl = 0; int pin_sda = 0; uint32_t baudrate_flags = 0; /** @todo Kinetis I2C: Add automatic baud rate flags selection function */ /* * See the Chapter "I2C divider and hold values": * Kinetis K60 Reference Manual, section 51.4.1.10, Table 51-41. * Kinetis MKW2x Reference Manual, section 52.4.1.10, Table 52-41. * * baud rate = I2C_module_clock / (mul × ICR) */ switch (speed) { case I2C_SPEED_LOW: baudrate_flags |= I2C_F_MULT(KINETIS_I2C_F_MULT_LOW) | I2C_F_ICR(KINETIS_I2C_F_ICR_LOW); break; case I2C_SPEED_NORMAL: baudrate_flags |= I2C_F_MULT(KINETIS_I2C_F_MULT_NORMAL) | I2C_F_ICR(KINETIS_I2C_F_ICR_NORMAL); break; case I2C_SPEED_FAST: baudrate_flags |= I2C_F_MULT(KINETIS_I2C_F_MULT_FAST) | I2C_F_ICR(KINETIS_I2C_F_ICR_FAST); break; case I2C_SPEED_FAST_PLUS: baudrate_flags |= I2C_F_MULT(KINETIS_I2C_F_MULT_FAST_PLUS) | I2C_F_ICR(KINETIS_I2C_F_ICR_FAST_PLUS); break; default: /* * High speed mode is not supported on Kinetis devices, * see: https://community.freescale.com/thread/316371 * * Hardware allows setting the baud rate high enough but the * capacitance of the bus and lacking a proper high speed mode SCL * driver will make the signals go out of spec. */ return -2; } /* read static device configuration */ switch (dev) { #if I2C_0_EN case I2C_0: i2c = I2C_0_DEV; i2c_port = I2C_0_PORT; pin_scl = I2C_0_SCL_PIN; pin_sda = I2C_0_SDA_PIN; I2C_0_CLKEN(); I2C_0_PORT_CLKEN(); break; #endif default: return -1; } /* configure pins, alternate output */ i2c_port->PCR[pin_scl] = I2C_0_PORT_CFG; i2c_port->PCR[pin_sda] = I2C_0_PORT_CFG; i2c->F = baudrate_flags; /* enable i2c-module and interrupt */ i2c->C1 = I2C_C1_IICEN_MASK | I2C_C1_IICIE_MASK | I2C_C1_TXAK_MASK; i2c->C2 = 0; return 0; }
/* * LPLD_I2C_Init * I2C通用初始化函数,在该函数中选择I2C通道,选择I2C SCK总线频率, * 选择I2C SDA 和 I2C SCL的引脚,配置I2C的中断回调函数 * * 参数: * I2C_InitTypeDef--i2c_init_structure * 具体定义见I2C_InitTypeDef * 输出: * 0--配置错误 * 1--配置成功 */ uint8 LPLD_I2C_Init(I2C_InitTypeDef i2c_init_structure) { I2C_Type *i2cx = i2c_init_structure.I2C_I2Cx; uint8 bus_speed = i2c_init_structure.I2C_ICR; PortPinsEnum_Type scl_pin = i2c_init_structure.I2C_SclPin; PortPinsEnum_Type sda_pin = i2c_init_structure.I2C_SdaPin; I2C_ISR_CALLBACK isr_func = i2c_init_structure.I2C_Isr; boolean ode = i2c_init_structure.I2C_OpenDrainEnable; uint8 ode_mask = 0; //参数检查,判断SCL频率 ASSERT( bus_speed <= 0x3F); if(ode == TRUE) { ode_mask = PORT_PCR_ODE_MASK; } if(i2cx == I2C0) { #if defined(CPU_MK60DZ10) || defined(CPU_MK60D10) SIM->SCGC4 |= SIM_SCGC4_I2C0_MASK; //开启I2C0时钟 #elif defined(CPU_MK60F12) || defined(CPU_MK60F15) SIM->SCGC4 |= SIM_SCGC4_IIC0_MASK; //开启I2C0时钟 #endif if(scl_pin == PTD8) { PORTD->PCR[8] = PORT_PCR_MUX(2) | ode_mask; } else if(scl_pin == PTB0) { PORTB->PCR[0] = PORT_PCR_MUX(2) | ode_mask; } else //scl_pin = PTB2 { PORTB->PCR[2] = PORT_PCR_MUX(2) | ode_mask; } if(sda_pin == PTD9) { PORTD->PCR[9] = PORT_PCR_MUX(2) | ode_mask; } else if(sda_pin == PTB1) { PORTB->PCR[1] = PORT_PCR_MUX(2) | ode_mask; } else //sda_pin = PTB3 { PORTB->PCR[3] = PORT_PCR_MUX(2) | ode_mask; } } else if(i2cx == I2C1) { #if defined(CPU_MK60DZ10) || defined(CPU_MK60D10) SIM->SCGC4 |= SIM_SCGC4_I2C1_MASK; //开启I2C0时钟 #elif defined(CPU_MK60F12) || defined(CPU_MK60F15) SIM->SCGC4 |= SIM_SCGC4_IIC1_MASK; //开启I2C0时钟 #endif if(scl_pin == PTE1) { PORTE->PCR[1] = PORT_PCR_MUX(6) | ode_mask; } else //scl_pin = PTC10 { PORTC->PCR[10] = PORT_PCR_MUX(2) | ode_mask; } if(sda_pin == PTE0) { PORTE->PCR[0] = PORT_PCR_MUX(6) | ode_mask; } else //sda_pin = PTC11 { PORTC->PCR[11] = PORT_PCR_MUX(2) | ode_mask; } } else return 0; if(i2c_init_structure.I2C_IntEnable == TRUE && isr_func != NULL) { //产生I2C中断的中断源: //1,完成1个字节传输时,IICIF置位产生中断; //2,当Calling Address匹配成功时产生中断,参考K60文档1456页I2Cx_S寄存器IAAS位; //3,从机模式下当总线仲裁丢失时,IICIF置位产生中断; // 需要同时写1清除II2Cx_S的ARBL标志位和 I2Cx_S的 IICIF的标志位; //4,如果SMB寄存器的SHTF2 interrupt使能,当SHTF2 timeout时IICIF置位产生中断; // 需要同时写1清除I2Cx_SMB的SLTF标志位和 I2Cx_S的 IICIF的标志位; //5,当SLT寄存器不为0时,SMBus的SCL low timer计数等于SLT的值时IICIF置位产生中断; // 需要同时写1清除I2Cx_SMB的SHTF2标志位和 I2Cx_S的 IICIF的标志位; //6,当Wakeup 使能,I2C在停止模式下接收到Wakeup信号,将产生中断. i2cx->C1 |= I2C_C1_IICIE_MASK; if(i2cx == I2C0) { I2C_ISR[0] = isr_func; } else if(i2cx == I2C0) { I2C_ISR[1] = isr_func; } else return 0; } //i2cx->C2 |= I2C_C2_HDRS_MASK; //提高I2C驱动能力 i2cx->F = I2C_F_ICR(bus_speed)|I2C_F_MULT(0); //配置I2Cx SCL BusSpeed i2cx->C1 |= I2C_C1_IICEN_MASK; //使能I2Cx return 1; }