Exemple #1
0
/* ===================================================================*/
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);
}
Exemple #5
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;
}
Exemple #6
0
/* ===================================================================*/
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 */
}
Exemple #7
0
/*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));
}
Exemple #8
0
//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 );
}
Exemple #9
0
/**
 * @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));
}
Exemple #10
0
/**
 * @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])  );
}
Exemple #13
0
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;
}
Exemple #14
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;
}