博客
关于我
小熊派GD32开发(7)— 使用软件模拟I2C读取SHT30温湿度传感器
阅读量:554 次
发布时间:2019-03-09

本文共 4372 字,大约阅读时间需要 14 分钟。

为了实现GD32开发板上使用软件模拟I2C读取SHT30温湿度传感器的功能,我们需要编写相应的驱动程序和应用程序。以下是详细的步骤说明:

一、编写软件模拟I2C驱动程序

  • 初始化I2C引脚

    • soft_i2c.c文件中,初始化I2C总线的时钟和数据线。
    void IIC_Init(void) {    rcu_periph_clock_enable(RCU_GPIOB);  // 启用GPIOB时钟    gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);  // PB6(IIC_SCL)设置为推挽输出    gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);  // PB7(IIC_SDA)设置为推挽输出    gpio_bit_set(GPIOB, GPIO_PIN_6);  // 确保SCL引脚拉高    gpio_bit_set(GPIOB, GPIO_PIN_7);  // 确保SDA引脚拉高}
  • 编写us延时函数

    void delay_us(uint32_t nus) {    uint32_t ticks;    uint32_t told, tnow, tcnt = 0;    uint32_t reload = SysTick->LOAD;  // 滴答定时器的重装载值    ticks = nus * 120;  // 转换为对定时器节拍的计算    told = SysTick->VAL;  // 刚进入函数时的计数器值    while (1) {        tnow = SysTick->VAL;        if (tnow != told) {            if (tnow < told) {                tcnt += told - tnow;            } else {                tcnt += reload - tnow + told;            }            if (tcnt >= ticks) break;            told = tnow;        }    }}
  • 实现I2C通信函数

    • 启动I2C总线
    void IIC_Start(void) {    SDA_OUT();  // SDA引脚输出    IIC_SDA(1);  // SDA拉高    IIC_SCL(1);  // SCL拉高    delay_us(4);  // 等待SCL和SDA稳定    IIC_SDA(0);  // SDA拉低    delay_us(4);  // 等待SCL和SDA稳定    IIC_SCL(0);  // SCL拉低}
    • 结束I2C总线
    void IIC_Stop(void) {    SDA_OUT();  // SDA引脚输出    IIC_SCL(0);  // SCL拉低    IIC_SDA(0);  // SDA拉低    delay_us(4);  // 等待SCL和SDA稳定    IIC_SCL(1);  // SCL拉高    delay_us(4);  // 等待SCL和SDA稳定    IIC_SDA(1);  // SDA拉高    delay_us(4);  // 等待SCL和SDA稳定}
    • 发送ACK和NACK
    void IIC_ACK(void) {    SDA_OUT();    IIC_SCL(0);    delay_us(2);    IIC_SDA(0);    delay_us(2);    IIC_SCL(1);    delay_us(2);    IIC_SCL(0);    delay_us(1);}
    void IIC_NACK(void) {    SDA_OUT();    IIC_SCL(0);    delay_us(2);    IIC_SDA(1);    delay_us(2);    IIC_SCL(1);    delay_us(2);    IIC_SCL(0);    delay_us(1);}
    • 接收并处理ACK
    uint8_t IIC_wait_ACK(void) {    uint8_t t = 200;    SDA_OUT();    IIC_SDA(1);    delay_us(1);    IIC_SCL(0);    delay_us(1);    SDA_IN();  // 释放数据线    delay_us(1);    while (READ_SDA) {        t--;        delay_us(1);        if (t == 0) {            IIC_SCL(0);            return 1;        }        delay_us(1);    }    delay_us(1);    IIC_SCL(1);    delay_us(1);    IIC_SCL(0);    delay_us(1);    return 0;}
    • 发送和接收一个字节数据
    void IIC_SendByte(uint8_t byte) {    uint8_t BitCnt;    SDA_OUT();    IIC_SCL(0);    for (BitCnt = 0; BitCnt < 8; BitCnt++) {        if ((byte & 0x80) != 0) {            IIC_SDA(1);        } else {            IIC_SDA(0);        }        byte <<= 1;        delay_us(2);        IIC_SCL(1);        delay_us(2);        IIC_SCL(0);        delay_us(2);    }}
    uint8_t IIC_RcvByte(void) {    uint8_t retc = 0;    uint8_t BitCnt;    SDA_IN();    delay_us(1);    for (BitCnt = 0; BitCnt < 8; BitCnt++) {        IIC_SCL(0);        delay_us(2);        IIC_SCL(1);        retc = retc << 1;        if (READ_SDA) {            retc |= 1;        }        delay_us(1);    }    IIC_SCL(0);    return retc;}
  • 二、编写SHT30应用程序

  • 初始化SHT30传感器

    uint8_t SHT3x_Init(void) {    // 初始化传感器地址和其他配置    return 0;}
  • 读取传感器编号

    uint8_t SHT3x_ReadSerialNumber(uint32_t* serialNumber) {    // 发送读取传感器编号命令并接收数据    return 0;}
  • 单次读取温湿度数据

    uint8_t SHT3x_Get_Humiture_single(double* Tem_val, double* Hum_val) {    // 发送测量命令并接收数据    return 0;}
  • 周期读取温湿度数据

    uint8_t SHT3x_Get_Humiture_periodic(double* Tem_val, double* Hum_val) {    // 设置为周期读取模式并读取数据    return 0;}
  • 数据校验函数

    uint8_t CheckCrc8(uint8_t* const message, uint8_t initial_value) {    // CRC8校验    return 0;}
  • 三、集成到主程序并上传到云端

  • 主函数初始化
    int main(void) {    // 初始化系统时钟、UART、I2C等    systick_config();    LED_init();    uart_init(115200);    // 其他初始化    printf("Hello world! \r\n");    while (NB_Start()) {        // 处理NBIoT模块的通信    }    // 初始化SHT30传感器    if (0 == SHT3x_Init()) {        printf("SHT3x_Init OK \r\n");    } else {        printf("SHT3x_Init ERR \r\n");    }    // 设置定时任务读取温湿度数据    while (1) {        if (update_flag == 1) {            update_flag = 0;            // 采集数据并上传到EMQ            if (SHT3x_Get_Humiture_periodic(&Tem_val, &Hum_val) == 0) {                // 生成数据包并发送                // ...            } else {                printf("Get_Humiture ERR\r\n");            }        }        // 处理NBIoT模块的收数据    }}
  • 四、注意事项

    • 延时函数:确保延时函数准确无误,避免I2C通信错误。
    • 数据校验:在接收数据时进行CRC校验,确保数据完整性。
    • 错误处理:增加错误处理逻辑,确保系统稳定运行。
    • 定时任务:在多任务环境中,确保定时任务的正确执行。
    • 云端通信:验证NBIoT模块的通信配置,确保数据能成功上传。

    通过以上步骤,可以实现使用软件模拟I2C读取SHT30温湿度传感器的功能,并将数据上传到云端,完成一个完整的开发流程。

    转载地址:http://qtqsz.baihongyu.com/

    你可能感兴趣的文章
    node~ http缓存
    查看>>
    node不是内部命令时配置node环境变量
    查看>>
    node中fs模块之文件操作
    查看>>
    Node中同步与异步的方式读取文件
    查看>>
    Node中的Http模块和Url模块的使用
    查看>>
    Node中自启动工具supervisor的使用
    查看>>
    Node入门之创建第一个HelloNode
    查看>>
    node全局对象 文件系统
    查看>>
    Node出错导致运行崩溃的解决方案
    查看>>
    Node响应中文时解决乱码问题
    查看>>
    node基础(二)_模块以及处理乱码问题
    查看>>
    node安装卸载linux,Linux运维知识之linux 卸载安装node npm
    查看>>
    node安装及配置之windows版
    查看>>
    Node实现小爬虫
    查看>>
    Node提示:error code Z_BUF_ERROR,error error -5,error zlib:unexpected end of file
    查看>>
    Node提示:npm does not support Node.js v12.16.3
    查看>>
    Node搭建静态资源服务器时后缀名与响应头映射关系的Json文件
    查看>>
    Node服务在断开SSH后停止运行解决方案(创建守护进程)
    查看>>
    node模块化
    查看>>
    node模块的本质
    查看>>