From ca970e5e68344be9bacfb3c5ba12a55deb1d8933 Mon Sep 17 00:00:00 2001 From: yelvlab Date: Sat, 28 Dec 2024 18:39:11 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0board=5Fconfig.h=E4=BD=9C?= =?UTF-8?q?=E4=B8=BA=E5=85=A8=E9=83=A8=E6=9D=BF=E4=B8=8AIO=E7=9A=84?= =?UTF-8?q?=E5=AE=8F=E5=AE=9A=E4=B9=89=E4=BD=8D=E7=BD=AE=EF=BC=8C=E7=8B=AC?= =?UTF-8?q?=E7=AB=8Bsoft=5Fi2c=E4=B8=BA=E5=8D=95=E7=8B=AC=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 1 + inc/board_config.h | 21 ++++++ inc/i2c.h | 29 +------- inc/soft_i2c.h | 37 ++++++++++ src/i2c.c | 137 ---------------------------------- src/main.c | 38 +++++----- src/soft_i2c.c | 179 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 257 insertions(+), 185 deletions(-) create mode 100644 inc/board_config.h create mode 100644 inc/soft_i2c.h create mode 100644 src/soft_i2c.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 05b94d6..d06d055 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,7 @@ set(TARGET_C_SRC ${CMAKE_SOURCE_DIR}/src/rs485.c ${CMAKE_SOURCE_DIR}/src/led.c ${CMAKE_SOURCE_DIR}/src/i2c.c + ${CMAKE_SOURCE_DIR}/src/soft_i2c.c ) add_executable(xlsw_3dp_LDC1612 ${TARGET_C_SRC}) diff --git a/inc/board_config.h b/inc/board_config.h new file mode 100644 index 0000000..48fa1dd --- /dev/null +++ b/inc/board_config.h @@ -0,0 +1,21 @@ +// +// Created by dell on 24-12-28. +// + +#ifndef BOARD_CONFIG_H +#define BOARD_CONFIG_H + +/******************************************************************************/ + +#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 + +/******************************************************************************/ + +#endif //BOARD_CONFIG_H diff --git a/inc/i2c.h b/inc/i2c.h index c606a4a..acd8d12 100644 --- a/inc/i2c.h +++ b/inc/i2c.h @@ -15,16 +15,7 @@ #include #include -/******************************************************************************/ - -#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 +#include "board_config.h" /******************************************************************************/ @@ -55,24 +46,6 @@ 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_send_byte(uint8_t byte); - -uint8_t i2c_receive_byte(uint8_t ack); - void i2c_config(void); void i2c_bus_reset(void); diff --git a/inc/soft_i2c.h b/inc/soft_i2c.h new file mode 100644 index 0000000..1a47906 --- /dev/null +++ b/inc/soft_i2c.h @@ -0,0 +1,37 @@ +// +// Created by dell on 24-12-28. +// + +#ifndef SOFT_I2C_H +#define SOFT_I2C_H + +#include "gd32e23x_it.h" +#include "gd32e23x.h" +#include "systick.h" +#include "main.h" + +#include "board_config.h" + +/******************************************************************************/ + +#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) + +/******************************************************************************/ + +void i2c_delay(void); + +void soft_i2c_config(void); + +void soft_i2c_start(void); +void soft_i2c_stop(void); +void soft_i2c_send_ack(void); +void soft_i2c_send_nack(void); +uint8_t soft_i2c_wait_ack(void); +void soft_i2c_send_byte(uint8_t data); +uint8_t soft_i2c_receive_byte(uint8_t ack); + +#endif //SOFT_I2C_H diff --git a/src/i2c.c b/src/i2c.c index 1e512da..3c018dd 100644 --- a/src/i2c.c +++ b/src/i2c.c @@ -25,143 +25,6 @@ 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(20); // 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 sda_out(void) { -// 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); -// } -// -// void sda_in(void) { -// gpio_mode_set(I2C_SDA_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, I2C_SDA_PIN); -// } - -void i2c_start(void) { - // sda_out(); - I2C_SDA_HIGH(); - I2C_SCL_HIGH(); - i2c_delay(); - I2C_SDA_LOW(); - i2c_delay(); - I2C_SCL_LOW(); - i2c_delay(); - i2c_delay(); - // 从全高开始,SCL为高期间,SDA下降沿表示start信号,再拉低SCL -} - -void i2c_stop(void) { - // sda_out(); - I2C_SCL_LOW(); - I2C_SDA_LOW(); - i2c_delay(); - I2C_SCL_HIGH(); - i2c_delay(); - I2C_SDA_HIGH(); - // 从全低开始,SCL为高期间,SDA上升沿表示stop -} - -void i2c_send_ack(void) { - // sda_out(); - 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) { - // sda_out(); - 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) { - // sda_in(); - 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) { - // sda_out(); - 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拉低电平 - delay_us(5); - } - // i2c_wait_ack(); -} - -uint8_t i2c_receive_byte(uint8_t ack) { - // sda_in(); - 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 8712ad3..598612c 100644 --- a/src/main.c +++ b/src/main.c @@ -12,6 +12,7 @@ #include "rs485.h" #include "led.h" #include "i2c.h" +#include "soft_i2c.h" #include "ldc1612.h" #include "tmp112.h" @@ -61,10 +62,26 @@ int main(void) { while (1) { - si2c_config(); + soft_i2c_config(); printf("111\n"); i2c_start(); + i2c_send_byte((0x2B << 1)); + if (!i2c_wait_ack()) + { + printf("NACK\n"); + } + + + i2c_send_byte(0x7E); + if (!i2c_wait_ack()) + { + printf("NACK\n"); + } + + i2c_delay(); + i2c_start(); + i2c_send_byte((0x2B << 1) + 1); if (!i2c_wait_ack()) { @@ -73,30 +90,11 @@ int main(void) { i2c_delay(); - i2c_send_byte(0x7E); - // if (!i2c_wait_ack()) - // { - // printf("NACK\n"); - // } - - i2c_delay(); - i2c_start(); - - i2c_send_byte((0x2B << 1)); - if (!i2c_wait_ack()) - { - printf("NACK\n"); - } - - i2c_delay(); - data[0] = i2c_receive_byte(1); - i2c_delay(); data[1] = i2c_receive_byte(0); delay_us(5); i2c_stop(); - // printf("OK\n"); printf("0x%x 0x%x\n", data[0], data[1]); diff --git a/src/soft_i2c.c b/src/soft_i2c.c new file mode 100644 index 0000000..3e9953b --- /dev/null +++ b/src/soft_i2c.c @@ -0,0 +1,179 @@ +// +// Created by dell on 24-12-28. +// + +#include "soft_i2c.h" + +/*! + \brief delay + \param[in] none + \param[out] none + \retval none +*/ +void i2c_delay(void) { + delay_us(20); // Adjust delay as needed + /* delay to freq + * 20KHz: delay_us(20); + * 65KHz: delay_us(1); + */ +} + +/*! + \brief configure the software IIC GPIO + \param[in] none + \param[out] none + \retval none +*/ +void soft_i2c_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(); +} + +/*! + \brief generate I2C start signal + \param[in] none + \param[out] none + \retval none +*/ +void soft_i2c_start(void) { + // sda_out(); + I2C_SDA_HIGH(); + I2C_SCL_HIGH(); + i2c_delay(); + I2C_SDA_LOW(); + i2c_delay(); + I2C_SCL_LOW(); + // i2c_delay(); + // 从全高开始,SCL为高期间,SDA下降沿表示start信号,再拉低SCL +} + +/*! + \brief generate I2C stop signal + \param[in] none + \param[out] none + \retval none +*/ +void soft_i2c_stop(void) { + // sda_out(); + I2C_SCL_LOW(); + I2C_SDA_LOW(); + i2c_delay(); + I2C_SCL_HIGH(); + i2c_delay(); + I2C_SDA_HIGH(); + // 从全低开始,SCL为高期间,SDA上升沿表示stop +} + +/*! + \brief send I2C ACK signal + \param[in] none + \param[out] none + \retval none +*/ +void soft_i2c_send_ack(void) { + // sda_out(); + I2C_SDA_LOW(); + i2c_delay(); + I2C_SCL_HIGH(); + i2c_delay(); + I2C_SCL_LOW(); + i2c_delay(); + I2C_SDA_HIGH(); + // SCL产生一个正常的时钟周期,其间SDA始终为低电平,表示ACK +} + +/*! + \brief send I2C NACK signal + \param[in] none + \param[out] none + \retval none +*/ +void soft_i2c_send_nack(void) { + // sda_out(); + I2C_SDA_HIGH(); + i2c_delay(); + I2C_SCL_HIGH(); + i2c_delay(); + I2C_SCL_LOW(); + i2c_delay(); + I2C_SDA_HIGH(); + // SCL产生一个正常的时钟周期,其间SDA始终为高电平,表示NACK +} + +/*! + \brief wait I2C ACK signal + \param[in] none + \param[out] none + \retval 0: ACK received, 1: ACK not received +*/ +uint8_t soft_i2c_wait_ack(void) { + // sda_in(); + 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; +} + +/*! + \brief send a byte via I2C + \param[in] byte: byte to be sent + \param[out] none + \retval none +*/ +void soft_i2c_send_byte(uint8_t byte) { + // sda_out(); + 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拉低电平 + delay_us(5); + } + // i2c_wait_ack(); +} + +/*! + \brief receive a byte via I2C + \param[in] ack: 1: send ACK, 0: send NACK + \param[out] none + \retval received byte +*/ +uint8_t soft_i2c_receive_byte(uint8_t ack) { + // sda_in(); + 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) { + soft_i2c_send_ack(); + } else { + soft_i2c_send_nack(); + } + return byte; +} \ No newline at end of file