STM32F746-Disco
电容式触控面板 FT5336
STM32CubeIDE,Windows 10
仅限 CMSIS
我正在仅使用 CMSIS 为 STM32F746 开发我的第一个 I2C 驱动程序,我决定最好在内置电容式触摸面板 FT5336 上测试我的 I2C 技能。我使用 ST 提供的 ft5336.c/.h 来获取寄存器地址(因为 FT5336 数据表实际上没有它们)。所以显然我首先要尝试的是读取芯片 ID 寄存器。
最初,我已经为它开发了 DMA 驱动程序(是的,我可以做 DMA,但仍然没有尝试过 I2C),但是当我遇到问题时,我退后一步并采用完全阻塞的方式。有趣的是,结果是相同的。
我所做的:
我以写入模式(ACK)写入从地址,然后是 ID 寄存器(NACK)。
然后我稍微暂停一下(~30us,远高于数据表~10us 用于开始设置;尝试不同)。
然后我以读取模式(ACK)写入从地址,并收到 0x00(NACK)。
我已经用示波器和逻辑分析仪仔细检查了我的信号,确保时序正确无误。我可以随心所欲地写(主发送)(包括使用 DMA),但我似乎无法阅读。我不确定错误在哪一边。显然,如果我在上面运行 TouchGFX 项目,面板就可以工作。我查看了 TouchGFX 生成的代码,以防我在那里看到一些东西,但我没有发现任何让我印象深刻的东西。我手头没有任何其他 I2C 设备可以用来测试它。
I2C3 设置:
- void i2c_setup(I2C_TypeDef *I2C) {
- I2C->CR1 &= ~I2C_CR1_PE; //make sure the peripheral is off
- /*
- * Analog filter enables, digital noise filter disabled
- * Interrupts disabled
- * */
- I2C->CR1 = 0x00; //reset
- I2C->CR1 |= (0x00 << I2C_CR1_ANFOFF_Pos) | (0x00 << I2C_CR1_DNF_Pos);
- /*
- * Set WRITE mode
- * 7-bit mode (ADD10=0)
- * Load 7-bit Slave Address
- */
- I2C->CR2 = 0x00; //reset
- I2C->CR2 |= (0x00 << I2C_CR2_RD_WRN_Pos) | (FT5336_I2C_SLAVE_ADDRESS << I2C_CR2_SADD_Pos);
- /*
- *tiMING
- * 100kHz I2C
- * */
- I2C->TIMINGR = 0x00; //reset
- I2C->TIMINGR |= (0x06 << I2C_TIMINGR_PRESC_Pos) | (0x02 << I2C_TIMINGR_SCLDEL_Pos) | (0x00 << I2C_TIMINGR_SDADEL_Pos) | (0x1E << I2C_TIMINGR_SCLH_Pos)
- | (0x2A << I2C_TIMINGR_SCLL_Pos);
- I2C->CR1 |= I2C_CR1_PE; //activate peripheral
- }
- void i2c_sendByte(uint8_t data, I2C_TypeDef *I2C) {
- I2C->CR2 &= ~I2C_CR2_NBYTES; //make sure number of bytes to transmit is cleared
- I2C->CR2 |= (0x01 << I2C_CR2_NBYTES_Pos); //set number of bytes to send to 1
- I2C->CR2 |= I2C_CR2_AUTOEND; //stop bit after sent byte
- I2C->CR2 &= ~I2C_CR2_RD_WRN; //master requests write transfer
- while (!(I2C->ISR & I2C_ISR_TXE)); //wait while transmit data register is empty (just in case, whatever)
- //Slave address set in setup
- I2C->TXDR = data;
- I2C->CR2 |= I2C_CR2_START; //set start bit
- }
- void i2c_receiveByte(uint8_t *data, I2C_TypeDef *I2C) {
- I2C->CR2 &= ~I2C_CR2_NBYTES; //make sure number of bytes to transmit is cleared
- I2C->CR2 |= (0x01 << I2C_CR2_NBYTES_Pos); //set number of bytes to 1
- I2C->CR2 |= I2C_CR2_AUTOEND; //stop bit after sent byte
- I2C->CR2 |= I2C_CR2_RD_WRN; //master requests write transfer
- I2C->CR2 |= I2C_CR2_START; //set start bit
- while (!(I2C->ISR & I2C_ISR_RXNE)); //wait while receive data register is not empty
- *data = I2C->RXDR;
- }
我实际上是如何在 main.c 中运行它的(删除了不相关的 UART 部分):
- i2c_setup(I2C3);
- uint8_t i2c3_id_register;
- while (1) {
- while (I2C3->ISR & I2C_ISR_BUSY);
- for (uint32_t i = 0; i < 1000; i++); //lame pause
- i2c_sendByte(0xA8, I2C3);
- while (I2C3->ISR & I2C_ISR_BUSY);
- for (uint32_t i = 0; i < 1000; i++); //lame pause
- i2c_receiveByte(&i2c3_id_register, I2C3);
- }
截图如果来自逻辑分析器,所以我实际上看到了线上发生的物理情况,处理数据在这里不是问题。范围给出了相同的图片。我不确定我做错了什么。
0