From 8c1cf00d2fb1e4709e66924f995232fe1504c54d Mon Sep 17 00:00:00 2001 From: yelvlab Date: Fri, 27 Dec 2024 00:54:48 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=87=E6=8D=A2=E4=B8=BA=E8=BD=AF=E4=BB=B6II?= =?UTF-8?q?C=EF=BC=8C=E5=AE=8C=E6=88=90=E5=90=84=E7=A7=8D=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E5=87=BD=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- inc/i2c.h | 40 ++++++++++++++---- src/i2c.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.c | 4 +- 3 files changed, 152 insertions(+), 10 deletions(-) diff --git a/inc/i2c.h b/inc/i2c.h index bdb05c9..e592da8 100644 --- a/inc/i2c.h +++ b/inc/i2c.h @@ -17,14 +17,22 @@ /******************************************************************************/ -#define I2C_SPEED 20000 -#define RCU_GPIO_I2C RCU_GPIOF -#define RCU_I2C RCU_I2C0 -#define I2C_SCL_PORT GPIOF -#define I2C_SCL_PIN GPIO_PIN_1 -#define I2C_SDA_PORT GPIOF -#define I2C_SDA_PIN GPIO_PIN_0 -#define I2C_GPIO_AF GPIO_AF_1 +#define I2C_SPEED 20000 +#define RCU_GPIO_I2C RCU_GPIOF +#define RCU_I2C RCU_I2C0 +#define I2C_SCL_PORT GPIOF +#define I2C_SCL_PIN GPIO_PIN_1 +#define I2C_SDA_PORT GPIOF +#define I2C_SDA_PIN GPIO_PIN_0 +#define I2C_GPIO_AF GPIO_AF_1 + +/******************************************************************************/ + +#define I2C_SCL_HIGH() gpio_bit_set(I2C_SCL_PORT, I2C_SCL_PIN) +#define I2C_SCL_LOW() gpio_bit_reset(I2C_SCL_PORT, I2C_SCL_PIN) +#define I2C_SDA_HIGH() gpio_bit_set(I2C_SDA_PORT, I2C_SDA_PIN) +#define I2C_SDA_LOW() gpio_bit_reset(I2C_SDA_PORT, I2C_SDA_PIN) +#define I2C_SDA_READ() gpio_input_bit_get(I2C_SDA_PORT, I2C_SDA_PIN) /******************************************************************************/ @@ -47,6 +55,22 @@ typedef enum { void i2c_gpio_config(void); +void si2c_config(void); + +void i2c_delay(void); + +void i2c_start(void); + +void i2c_stop(void); + +void i2c_send_ack(void); + +void i2c_send_nack(void); + +uint8_t i2c_wait_ack(void); + + + void i2c_config(void); void i2c_bus_reset(void); diff --git a/src/i2c.c b/src/i2c.c index 3c018dd..bd104e9 100644 --- a/src/i2c.c +++ b/src/i2c.c @@ -25,6 +25,124 @@ void i2c_gpio_config(void) { gpio_output_options_set(I2C_SDA_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SDA_PIN); } +void i2c_delay(void) { + delay_us(5); // Adjust delay as needed +} + +/*! + \brief configure the software IIC GPIO + \param[in] none + \param[out] none + \retval none +*/ +void si2c_config(void) { + rcu_periph_clock_enable(RCU_GPIO_I2C); + + gpio_mode_set(I2C_SCL_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, I2C_SCL_PIN); + gpio_output_options_set(I2C_SCL_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SCL_PIN); + + gpio_mode_set(I2C_SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, I2C_SDA_PIN); + gpio_output_options_set(I2C_SDA_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, I2C_SDA_PIN); + + I2C_SCL_HIGH(); + I2C_SDA_HIGH(); +} + +void i2c_start(void) { + I2C_SDA_HIGH(); + I2C_SCL_HIGH(); + i2c_delay(); + I2C_SDA_LOW(); + i2c_delay(); + I2C_SCL_LOW(); + // 从全高开始,SCL为高期间,SDA下降沿表示start信号,再拉低SCL +} + +void i2c_stop(void) { + I2C_SCL_LOW(); + I2C_SDA_LOW(); + i2c_delay(); + I2C_SCL_HIGH(); + i2c_delay(); + I2C_SDA_HIGH(); + // 从全低开始,SCL为高期间,SDA上升沿表示stop信号,再拉高SCL +} + +void i2c_send_ack(void) { + I2C_SDA_LOW(); + i2c_delay(); + I2C_SCL_HIGH(); + i2c_delay(); + I2C_SCL_LOW(); + i2c_delay(); + I2C_SDA_HIGH(); + // SCL产生一个正常的时钟周期,其间SDA始终为低电平,表示ACK +} + +void i2c_send_nack(void) { + I2C_SDA_HIGH(); + i2c_delay(); + I2C_SCL_HIGH(); + i2c_delay(); + I2C_SCL_LOW(); + i2c_delay(); + I2C_SDA_HIGH(); + // SCL产生一个正常的时钟周期,其间SDA始终为高电平,表示NACK +} + +uint8_t i2c_wait_ack(void) { + I2C_SDA_HIGH(); + i2c_delay(); + I2C_SCL_HIGH(); + i2c_delay(); + uint8_t ack = !I2C_SDA_READ(); + //ACK信号是第九个时钟期间,SDA被从机在SCL高期间,拉低并保持低电平。此处判断SDA是否被拉低,被拉低则返回0,取反为1,表示收到ACK + I2C_SCL_LOW(); + return ack; +} + +void i2c_send_byte(uint8_t byte) { + for (int i = 0; i < 8; i++) { + if (byte & 0x80) { //通过&操作获取第一位是1还是0 + I2C_SDA_HIGH(); //SCL低电平期间,SDA高电平表示1 + } else { + I2C_SDA_LOW(); //SCL低电平期间,SDA低电平表示0 + } + byte <<= 1; //左移一位,把原本第二位的数据移到第一位,再判断高低电平 + i2c_delay(); + I2C_SCL_HIGH(); //SCL拉高电平,SDA电平状态保持不变 + i2c_delay(); + I2C_SCL_LOW(); //SCL拉低电平 + } + i2c_wait_ack(); +} + +uint8_t i2c_receive_byte(uint8_t ack) { + uint8_t byte = 0; + I2C_SDA_HIGH(); //从高开始 + for (int i = 0; i < 8; i++) { + byte <<= 1; + I2C_SCL_HIGH(); + i2c_delay(); + if (I2C_SDA_READ()) { + byte |= 0x01; + } + I2C_SCL_LOW(); + i2c_delay(); + } + if (ack) { + i2c_send_ack(); + } else { + i2c_send_nack(); + } + return byte; +} + + + + + + /*! \brief configure the I2CX interface \param[in] none diff --git a/src/main.c b/src/main.c index 6d9db53..c23361b 100644 --- a/src/main.c +++ b/src/main.c @@ -33,8 +33,8 @@ int main(void) { /* configure LED */ led_config(); /* configure I2C */ - i2c_gpio_config(); - i2c_config(); + // i2c_gpio_config(); + // i2c_config(); // ldc1612_iic_get_sensor_infomation(); /* configure LDC1612 */