STM32G0开发笔记:I2C接口软件模拟与GXHT30温湿度模块

发布时间:2023-10-11  

使用Platformio平台的libopencm3开发框架来开发STM32G0,以下使用软件模拟I2C总线时序,并用它来读取GXHT30温湿度数据。


1 新建项目

建立gxht30项目

在PIO的Home页面新建项目,项目名称gxht30,选择开发板为 MonkeyPi_STM32_G070RB,开发框架选择libopencm3;


项目建立完成后在src目录下新建main.c主程序文件;

修改下载和调试方式,这里开发板使用的是DAPLink仿真器,因此修改platformio.ini文件如下:

1upload_protocol = cmsis-dap

2debug_tool = cmsis-dap


2 I2C软件模拟

2.1 文件结构

在lib目录新建 sw_i2c 文件夹,并新建如下文件:


2.2 sw_i2c_port.h 与底层IO读写相关

1/**

 2 * @file sw_i2c_port.h

 3 * @author MakerInChina (makerinchina.cn)

 4 * @brief 

 5 * @version 0.01

 6 * @date 2022-09-25

 7 * 

 8 * @copyright Copyright (c) 2022

 9 * 

10 */

11

12#ifndef _SW_I2C_PORT_HEAD_H_

13#define _SW_I2C_PORT_HEAD_H_

14

15#include 3/stm32/rcc.h>

16#include 3/stm32/gpio.h>

17

18#define    SW_I2C_SCL_CLOCK        RCC_GPIOB

19#define SW_I2C_SCL_PORT           GPIOB

20#define SW_I2C_SCL_PIN            GPIO13

21

22#define    SW_I2C_SDA_CLOCK        RCC_GPIOB

23#define SW_I2C_SDA_PORT           GPIOB

24#define SW_I2C_SDA_PIN            GPIO14

25

26#define sw_i2c_scl_high()       gpio_set(SW_I2C_SCL_PORT, SW_I2C_SCL_PIN)

27#define sw_i2c_scl_low()        gpio_clear(SW_I2C_SCL_PORT, SW_I2C_SCL_PIN)

28#define sw_i2c_sda_high()       gpio_set(SW_I2C_SDA_PORT, SW_I2C_SDA_PIN)

29#define sw_i2c_sda_low()        gpio_clear(SW_I2C_SDA_PORT, SW_I2C_SDA_PIN)

30

31#define sw_i2c_sda_input()      gpio_mode_setup(SW_I2C_SDA_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SW_I2C_SDA_PIN)

32#define sw_i2c_sda_output()     gpio_mode_setup(SW_I2C_SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, SW_I2C_SDA_PIN)

33

34// #define sw_i2c_delay()       delay_us(5)

35#define sw_i2c_delay()          do{                                     

36                                    for (int i=0; i<58; i++) {         

37                                        __asm__ volatile ("nop");       

38                                    }                                   

39                                }while(0)

40static bool sw_i2c_sda_get(void) 

41{

42    return (gpio_get(SW_I2C_SDA_PORT, SW_I2C_SDA_PIN) != 0) ? true:false;

43} 

44

45static void sw_i2c_port_init()

46{

47    /* 打开GPIO时钟 */

48    rcc_periph_clock_enable(SW_I2C_SCL_CLOCK);

49    rcc_periph_clock_enable(SW_I2C_SDA_CLOCK);

50

51    /* 禁用默认上拉,使SCL, SDA保持高阻状态, 设置为 OD 模式 */

52    gpio_mode_setup(SW_I2C_SCL_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, SW_I2C_SCL_PIN);

53    gpio_mode_setup(SW_I2C_SDA_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, SW_I2C_SDA_PIN);

54    gpio_set_output_options(SW_I2C_SCL_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_25MHZ, SW_I2C_SCL_PIN);

55    gpio_set_output_options(SW_I2C_SDA_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_25MHZ, SW_I2C_SDA_PIN);

56

57    /* 空闲: 拉高SCL和SDA */

58    gpio_set(SW_I2C_SCL_PORT, SW_I2C_SCL_PIN);

59    gpio_set(SW_I2C_SDA_PORT, SW_I2C_SDA_PIN);

60}

61

62#endif //!_SW_I2C_PORT_HEAD_H_

i2c时序中的延时这里使用软件延时,模拟的是 100KHz的频率;


2.3 sw_i2c_private.h 实现i2c的基本时序

1/**

  2 * @file sw_i2c_private.h

  3 * @author MakerInChina (makerinchina.cn)

  4 * @brief 

  5 * @version 0.01

  6 * @date 2022-09-25

  7 * 

  8 * @copyright Copyright (c) 2022

  9 * 

 10 */

 11

 12#ifndef _SW_I2C_PRIVATE_HEAD_H_

 13#define _SW_I2C_PRIVATE_HEAD_H_

 14

 15#include "sw_i2c_port.h"

 16

 17static void i2c_start(void);

 18static void i2c_stop(void);

 19static bool i2c_wait_ack(void);

 20static void i2c_send_ack(void);

 21static void i2c_send_nack(void);

 22static void i2c_send_byte(uint8_t data);

 23static uint8_t i2c_recv_byte(bool ack);

 24

 25/**

 26 * @brief I2C总线启动信号

 27 */

 28static void i2c_start(void)

 29{

 30    /* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */

 31    sw_i2c_sda_high();

 32    sw_i2c_scl_high();

 33    sw_i2c_delay();

 34    sw_i2c_sda_low();

 35    sw_i2c_delay();

 36    sw_i2c_scl_low();

 37    sw_i2c_delay();

 38}

 39

 40/**

 41 * @brief I2C总线停止信号

 42 */

 43static void i2c_stop(void)

 44{

 45    /* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */

 46    sw_i2c_sda_low();

 47    sw_i2c_delay();

 48    sw_i2c_scl_high();

 49    sw_i2c_delay();

 50    sw_i2c_sda_high();

 51}

 52

 53/**

 54 * @brief 向I2C总线设备发送1个字节

 55 * @param data 等待发送的字节

 56 */

 57static void i2c_send_byte(uint8_t data)

 58{

 59    uint8_t i;

 60

 61    /* 先发送字节的高位bit7 */

 62    for (i = 0; i < 8; i++) {

 63        sw_i2c_delay();

 64        sw_i2c_scl_low();

 65

 66        if (data & 0x80) {

 67            sw_i2c_sda_high();

 68        } else {

 69            sw_i2c_sda_low();

 70        }

 71

 72        sw_i2c_delay();

 73        sw_i2c_scl_high();

 74

 75        data <<= 1;    /* 左移一个bit */

 76    }

 77}

 78

 79/**

 80 * @brief 产生一个时钟,并读取器件的ACK应答信号

 81 * @return 返回true表示正确应答,false表示无器件响应

 82 */

 83static bool i2c_wait_ack(void)

 84{

 85    bool res;

 86

 87    sw_i2c_delay();

 88    sw_i2c_scl_low();

 89

 90    sw_i2c_sda_input();

 91

 92    sw_i2c_delay();

 93    sw_i2c_scl_high();    /* 驱动SCL = 1, 此时器件会返回ACK应答 */

 94    sw_i2c_delay();

 95    if (sw_i2c_sda_get() == false) { /* 读取SDA口线状态 */

 96        res = true;

 97    } else {

 98        res = false;

 99    }

100    sw_i2c_scl_low();

101    sw_i2c_sda_high();    /* 释放SDA总线 */

102    sw_i2c_sda_output();

103    sw_i2c_delay();

104

105    return res;

106}

107

108/**

109 * @brief 产生一个ACK信号

110 */

111static void i2c_send_ack(void)

112{

113    sw_i2c_sda_low();    /* CPU驱动SDA = 0 */

114    sw_i2c_delay();

115    sw_i2c_scl_high();    /* CPU产生1个时钟 */

116    sw_i2c_delay();

117    sw_i2c_scl_low();

118    sw_i2c_delay();

119    sw_i2c_sda_high();    /* CPU释放SDA总线 */

120}

121

122/**

123 * @brief CPU产生1个NACK信号

124 */

125static void i2c_send_nack(void)

126{

127    sw_i2c_sda_high();    /* CPU驱动SDA = 1 */

128    sw_i2c_delay();

129    sw_i2c_scl_high();    /* CPU产生1个时钟 */

130    sw_i2c_delay();

131    sw_i2c_scl_low();

132    sw_i2c_delay();

133}

134

135/**

136 * @brief CPU从I2C总线设备读取8bit数据

137 * 读1个字节,ack=1时,发送ACK,ack=0,发送nACK

138 * @return

139 */

140static uint8_t i2c_recv_byte(bool ack)

141{

142    uint8_t i;

143    uint8_t value;

144

145    /* 读到第1个bit为数据的bit7 */

146    value = 0;

147    for (i = 0; i < 8; i++) {

148        value <<= 1;

149        sw_i2c_scl_high();

150        sw_i2c_delay();

151        if (sw_i2c_sda_get()==true) {

152            value++;

153        }

154        sw_i2c_scl_low();

155        sw_i2c_delay();

156    }

157

158    if (ack) {

159        i2c_send_ack(); //发送ACK

160    } else {

161        i2c_send_nack();//发送nACK

162    }

163

164    return value;

165}

166

167#endif //!_SW_I2C_PRIVATE_HEAD_H_

2.4 sw_i2c 读写实现

1/**

  2 * @file sw_i2c.c

  3 * @author MakerInChina (makerinchina.cn)

  4 * @brief 

  5 * @version 0.01

  6 * @date 2022-09-25

  7 * 

  8 * @copyright Copyright (c) 2022

  9 * 

 10 */

 11

 12#include "sw_i2c.h"

 13#include "sw_i2c_port.h"

 14#include "sw_i2c_private.h"

 15

 16void sw_i2c_init()

 17{

 18    sw_i2c_port_init();

 19}

 20

 21/* Function to setup and execute I2C transfer request */

 22bool sw_i2c_transfer(uint8_t dev_addr, uint8_t *tx_buffer,uint16_t tx_size,uint8_t *rx_buffer,uint16_t rx_size)

 23{

 24    uint16_t i;

 25

 26    if (tx_size > 0) {

 27        /* start */

 28        i2c_start();

 29        /* address + write */

 30        i2c_send_byte(dev_addr<<1);

 31        if (i2c_wait_ack() == false) {

 32            goto error_device_nack;

 33        }

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>