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)
- IRQ, negative edge interrupt
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 , ®, 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