STM32F3的I2C通信问题求解:如何读取触摸动作实现LED闪烁
Alright, let's work through your STM32F3 I2C touchscreen issue to get that LED blinking on touch. I’ll fill in the gaps in your code and cover common pitfalls to make this work smoothly.
Your touch_i2c_read function is missing the core implementation. Assuming you're using STM32 HAL (the most common framework for STM32), here's a robust version that handles status returns and timeout:
static uint32_t touch_i2c_read(uint8_t DeviceAddr, uint8_t RegAddr, uint8_t *pBuffer, uint16_t len) { HAL_StatusTypeDef hal_status; // Note: DeviceAddr is 7-bit, so we shift left by 1 to get the 8-bit address HAL expects // (HAL automatically sets the read/write bit based on the operation) hal_status = HAL_I2C_Mem_Read( &hi2c1, // Replace with your I2C handle (e.g., hi2c2 if using I2C2) (DeviceAddr << 1), // 8-bit device address RegAddr, // Register to read from I2C_MEMADD_SIZE_8BIT, // 8-bit register address (common for touchscreens) pBuffer, // Buffer to store read data len, // Number of bytes to read I2C_TIMEOUT // Timeout in milliseconds ); // Map HAL status codes to your custom return values switch(hal_status) { case HAL_OK: return 0; // Success case HAL_ERROR: return 1; // Generic hardware error case HAL_BUSY: return 2; // I2C bus is busy case HAL_TIMEOUT: return 3; // Read timed out default: return 4; // Unknown error } }
Next, we need to check for touch events and trigger the LED. Most touchscreens have a status register that indicates if a touch is active. For example, the popular FT6236 uses register 0x02 where bit 0 is set when a touch is detected. Adjust the register address to match your specific touchscreen's datasheet.
#define TOUCH_STATUS_REG 0x02 // Adjust based on your touchscreen's specs #define LED_GPIO_PORT GPIOA // Replace with your LED's GPIO port #define LED_GPIO_PIN GPIO_PIN_5 // Replace with your LED's pin void process_touch_and_led(void) { uint8_t touch_status; res = touch_i2c_read(deviceaddr, TOUCH_STATUS_REG, &touch_status, 1); if(res == 0) // I2C read succeeded { if(touch_status & 0x01) // Check if touch is detected (bit 0 set) { HAL_GPIO_TogglePin(LED_GPIO_PORT, LED_GPIO_PIN); // Blink LED // Optional: Read touch coordinates if needed // touch_i2c_read(deviceaddr, 0x03, i2c_buffer, 4); // uint16_t touch_x = (i2c_buffer[0] & 0x0F) << 8 | i2c_buffer[1]; // uint16_t touch_y = (i2c_buffer[2] & 0x0F) << 8 | i2c_buffer[3]; } else { // Optional: Turn LED off when no touch // HAL_GPIO_WritePin(LED_GPIO_PORT, LED_GPIO_PIN, GPIO_PIN_RESET); } } else { // Handle I2C errors: Blink LED rapidly to signal fault for(int i = 0; i < 3; i++) { HAL_GPIO_TogglePin(LED_GPIO_PORT, LED_GPIO_PIN); HAL_Delay(100); } HAL_Delay(500); // Pause before next check } }
If you run into issues, start with these checks — they fix 90% of I2C problems on STM32:
- Hardware Pull-Ups: Ensure SDA and SCL lines have 4.7kΩ pull-up resistors. STM32's internal pull-ups are too weak for reliable I2C communication.
- Device Address: Verify your touchscreen's 7-bit address (common values are
0x38or0x3A). Don't confuse it with the 8-bit address (which is 7-bit shifted left by 1). - I2C GPIO Configuration: Set SDA/SCL pins to Alternate Function Open Drain with pull-ups. Open drain is mandatory for I2C.
- Timeout Value: Your
I2C_TIMEOUTis set to 65536 — HAL expects this value in milliseconds, so that's 65 seconds, which is way too long. Reduce it to 1000 (1 second) for faster error detection. - I2C Speed: Match the touchscreen's supported speed (100kHz standard mode is safest; 400kHz fast mode works if the screen supports it).
Finally, add the touch processing function to your main loop after initializing all peripherals:
int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); // Initialize LED GPIO (make sure to set it as output) MX_I2C1_Init(); // Initialize your I2C peripheral deviceaddr = 0x38; // Set your touchscreen's 7-bit address here while(1) { process_touch_and_led(); HAL_Delay(100); // Adjust polling rate (100ms is a good starting point) } }
内容的提问来源于stack exchange,提问作者NetworkStudent

