Application - MPR121, capacitive touch sensor controller

出自 flip the world
前往: 導覽搜尋
STM32F4+MPR121+LEDs

Library pinouts

 	PINS PACK 1 	PINS PACK 2 	PINS PACK 3 	PINS PACK 4
I2Cx 	SCL 	SDA 	SCL 	SDA 	SCL 	SDA 	SCL 	SDA
I2C1 	PB6 	PB7 	PB8 	PB9 	PB6 	PB9 		
I2C2 	PB10 	PB11 	PF1 	PF0 	PH4 	PH5 		
I2C3 	PA8 	PC9 	PH7 	PH8 				
I2C4 	PD12 	PD13 	PF1 	PF0 	PF14 	PF15 	PH11 	PH12

HW connection

STM32F4      --  MPR121
VCC          --  VCC(3.3V)
GND          --  GND
IRQ          --  IRQ(selected)
PB7          --  SDA
PB8          --  SCL

I²C Slave Address Pin Selects

  • Connect to VSS, VDD, SDA, SCL to choose address 0x5A, 0x5B, 0x5C, 0x5D respectively
  • Default was connected to VSS (0x5A)

Timing

  • I2C reg read, 0x5D = 0x24 (Default)

MPR121 - Read reg

  • IRQ, negative edge interrupt

MPR121 - Read reg

library hacking

  • The API HAL_I2C_Master_Transmit() always generate stop bit
    /* Generate Stop */
    //hi2c->Instance->CR1 |= I2C_CR1_STOP;
  • Control stop bit and start bit in main function
    I2cHandle.Instance->CR1 &= ~I2C_CR1_STOP;
    I2cHandle.Instance->CR1 |= I2C_CR1_START;
  • The API HAL_I2C_Master_Receive() wait for busy flag until timeout
#if 0
    /* Wait until BUSY flag is reset */
    if(I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG) != HAL_OK)
    {
      return HAL_BUSY;
    }
#endif

mpr121 read/write API

uint8_t mpr121Read(uint8_t reg)
{
  uint8_t data;

   if(HAL_I2C_Master_Transmit(&I2cHandle,(uint16_t)I2C_ADDRESS<<1 , &reg, 1, 10000) != HAL_OK) {
	   //Todo
   }

   I2cHandle.Instance->CR1 &= ~I2C_CR1_STOP;
   I2cHandle.Instance->CR1 |= I2C_CR1_START;

  /* Receive multiple byte */
  if(HAL_I2C_Master_Receive(&I2cHandle, (uint16_t)I2C_ADDRESS<<1, data, 1, 10000) != HAL_OK) {
	   //Todo
  }
  return data;
}

void mpr121Write(uint8_t register_address, uint8_t data) {
        uint8_t d[2];

        /* Format array to send */
        d[0] = register_address;
        d[1] = data;

        /* Try to transmit via I2C */
        if (HAL_I2C_Master_Transmit(&I2cHandle,(uint16_t)I2C_ADDRESS<<1, (uint8_t *)d, 2, 1000) != HAL_OK) {
        	Error_Handler();
        }
        I2cHandle.Instance->CR1 |= I2C_CR1_STOP;
}

mpr121 interrupt API

Note that, the IRQ would be triggered in both pressed and released!!

void EXTI3_IRQHandler(void)
{
	  uint16_t touchstatus=0;
	  touchstatus = mpr121Read(0x01) << 8;
	  touchstatus |= mpr121Read(0x00);

	  if(touchstatus & 0x0001)
		  BSP_LED_On(LED4);
	  else
		  BSP_LED_Off(LED4);

	  if(touchstatus & 0x0002)
		  BSP_LED_On(LED5);
	  else
		  BSP_LED_Off(LED5);

	  if(touchstatus & 0x0004)
		  BSP_LED_On(LED6);
	  else
		  BSP_LED_Off(LED6);

	  EXTI->PR = 0x0008; //clear interrupt flag for EXTI3
	  GPIOE->ODR |= 0x0100; //added to show the execution of IRQ function
	  GPIOE->ODR &= 0x0100; //end of execution, about 300ns later
}

Reference