504|2

192

帖子

4

TA的资源

纯净的硅(初级)

楼主
 

兆易GD32H759I-EVAL 使用逻辑分析仪辅助分析IIC协议点亮BH1750 [复制链接]

  本帖最后由 御坂10032号 于 2024-6-8 00:43 编辑

题外话

 

本章我们将要测评的是GD32的IIC功能,并且做一个小Demo。 使用逻辑分析仪来辅助分析IIC协议并且点亮BH1750光照传感器

 

正文

 

因为板子上并没有焊接排针,所以你想要使用逻辑分析仪的时候需要焊接2.0MM的排针。 并且根据数据手册的PIN定义找到你支持IIC功能的PIN。

 

 

接线图如下,分别是将开发板的PF14和15 接到BH1750的SCL 和 SDA上,然后逻辑分析仪和BH1750共地。并且连接SCL和SDA用来捕获信号。 

 

 

根据BH1750的数据手册得知 BH1750的IIC地址存在两种情况,分别是H 和 L。 当ADDR 引脚被接到H的话,那么它的地址就是0x46, 如果接到L引脚的话,那么它的地址就是0x23

 

根据官方数据手册提供的example我们可以得知,首先发送地址+写, 然后设置BH1750的分辨率。 之后停止便可以转换为读模式。 通过读模式我们便可以读取到BH1750的值

 

  接下来便开始编码部分。

 

 

编码

 

昨天下午2点开始看GD32的这个IIC库的代码和手册,一直折腾到现在,发现这个库的代码支持的功能比较多。也比较乱。很让人难懂。

手册上的主机发送流程也比较难懂,主要是发送后的这个标志位判断有点难以理解。我来给大家对比一下。

 

GD32的流程

 

STM32F429的

 

  在这一点上我建议厂商能够将每次传送后触发的判断事件,以类似上图的这种方式罗列出来,这样的话参考事件和官方的库函数可以非常快的来开发基于IIC的应用。

  同时,官方提供的Demo,比较难懂(GD32H7xx_Firmware_Library_V1.2.0 下的example 和GD32H759I_EVAL_Demo_Suites 下的Eeprom)代码使用状态机的方式保证了程序的健壮性。但是可读性较差。而且其中某些Flag的判断并没有使用库函数的方式,而是直接操作寄存器。更加增加阅读难度。 

 

读取BH1750光照传感器代码如下

 

#include "gd32h7xx.h"
#include "systick.h"
#include "bsp_usart.h"

// I2C和BH1750相关定义
#define I2C_SPEED           400000

#define RCU_GPIO_I2C_SDA    RCU_GPIOF
#define RCU_GPIO_I2C_SCL    RCU_GPIOF
#define RCU_I2C             RCU_I2C3
#define I2C_SCL_PORT        GPIOF
#define I2C_SDA_PORT        GPIOF
#define I2C_SCL_PIN         GPIO_PIN_14
#define I2C_SDA_PIN         GPIO_PIN_15
#define I2C_GPIO_AF         GPIO_AF_4


#define I2C_TIME_OUT   (uint32_t)(50000)
#define EEP_FIRST_PAGE 0x00
#define I2C_OK         0
#define I2C_FAIL       1


#define BH1750_ADDRESS      0x46
#define BH1750_POWER_ON     0x01
#define BH1750_RESET        0x07
#define BH1750_HRES_MODE    0x10

void cache_enable(void)
{
    /* Enable I-Cache */
    SCB_EnableICache();
    /* Enable D-Cache */
    SCB_EnableDCache();
}

void gpio_config(void)
{
    /* enable I2C_SCL_PIN clock */
    rcu_periph_clock_enable(RCU_GPIO_I2C_SCL);
    /* enable I2C_SDA_PIN clock */
    rcu_periph_clock_enable(RCU_GPIO_I2C_SDA);
    /* enable I2C clock */
    rcu_periph_clock_enable(RCU_I2C3);
    /* connect I2C_SCL_PIN to I2C_SCL */
    gpio_af_set(I2C_SCL_PORT, I2C_GPIO_AF, I2C_SCL_PIN);
    /* connect I2C_SDA_PIN to I2C_SDA */
    gpio_af_set(I2C_SDA_PORT, I2C_GPIO_AF, I2C_SDA_PIN);
    /* configure GPIO pins of I2C */
    gpio_mode_set(I2C_SCL_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, I2C_SCL_PIN);
    gpio_output_options_set(I2C_SCL_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_60MHZ, I2C_SCL_PIN);
    gpio_mode_set(I2C_SDA_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, I2C_SDA_PIN);
    gpio_output_options_set(I2C_SDA_PORT, GPIO_OTYPE_OD, GPIO_OSPEED_60MHZ, I2C_SDA_PIN);
}

void i2c_config(void)
{
    /* configure the I2C1 clock source selection */
    rcu_i2c_clock_config(IDX_I2C3, RCU_I2CSRC_IRC64MDIV);
    /* configure I2C timing */
    i2c_timing_config(I2C3, 0x0, 0x6, 0);
    i2c_master_clock_config(I2C3, 0x26, 0x73);
    /* enable I2C */
    i2c_enable(I2C3);

}



/*
*@desc: 发送数据
*@parameter 1: IIC外设
*@parameter 2: 从机地址
*@parameter 3: 传送的Buffer
*@parameter 4: 传送的字节数
*@return  :  
*/
void send_data(uint32_t i2c_periph, uint8_t address, uint8_t *p_buffer, uint16_t number_of_byte) {
    uint32_t timeout = 0;
    i2c_master_addressing(i2c_periph, address, I2C_MASTER_TRANSMIT);
    i2c_transfer_byte_number_config(i2c_periph, number_of_byte);
    i2c_automatic_end_enable(i2c_periph);
    while(i2c_flag_get(i2c_periph, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) {
        timeout++;
    }
    if(timeout < I2C_TIME_OUT) {
        i2c_start_on_bus(i2c_periph);
        for(uint16_t i = 0; i < number_of_byte; i++) {
            i2c_data_transmit(i2c_periph, p_buffer[i]);
        }
        timeout = 0;
        while(!i2c_flag_get(i2c_periph, I2C_FLAG_TBE) && (timeout < I2C_TIME_OUT)) {
            timeout++;
        }
    } else {
        printf("i2c bus is busy in write!\n");
    }
}

/*
*@desc: 读取数据到p_buffer 中
*@parameter 1: IIC外设
*@parameter 2: 从机地址
*@parameter 3: 传送的Buffer
*@parameter 4: 传送的字节数
*@return :  
*/
void read_data(uint32_t i2c_periph, uint8_t address, uint8_t *p_buffer, uint16_t number_of_byte) {
    uint32_t timeout = 0;
    i2c_master_addressing(i2c_periph, address, I2C_MASTER_RECEIVE);
    i2c_transfer_byte_number_config(i2c_periph, number_of_byte);
    i2c_automatic_end_enable(i2c_periph);
    while(i2c_flag_get(i2c_periph, I2C_FLAG_I2CBSY) && (timeout < I2C_TIME_OUT)) {
        timeout++;
    }
    if(timeout < I2C_TIME_OUT) {
        i2c_start_on_bus(i2c_periph);
        for(uint16_t i = 0; i < number_of_byte; i++) {
            while(!i2c_flag_get(i2c_periph, I2C_FLAG_RBNE) && (timeout < I2C_TIME_OUT)) {
                timeout++;
            }
            if(timeout < I2C_TIME_OUT) {
                p_buffer[i] = i2c_data_receive(i2c_periph);
            } else {
                printf("i2c read timeout!\n");
                break;
            }
        }
        timeout = 0;
        while(!i2c_flag_get(i2c_periph, I2C_FLAG_STPDET) && (timeout < I2C_TIME_OUT)) {
            timeout++;
        }
    } else {
        printf("i2c bus is busy in read!\n");
    }
}


int main(void)
{
    // 变量定义
    uint16_t light_level;
    uint8_t read_buffer[2];
    uint8_t power_on = BH1750_POWER_ON;
    uint8_t high_res_mode = BH1750_HRES_MODE;

    // 启用 CPU Cache
    cache_enable();
    // 配置 systick 和 USART
    systick_config();
    usart_init();
    usart_receive_init();

    // 配置 GPIO 和 I2C
    gpio_config();
    i2c_config();

    // 等待 BH1750 上电完成
    delay_1ms(10);
    // 发送启动指令
    send_data(I2C3, BH1750_ADDRESS, &power_on, 1);
    delay_1ms(10); // 等待传感器上电完成
    while (1) {
        // 发送高分辨率模式指令
        send_data(I2C3, BH1750_ADDRESS, &high_res_mode, 1);
        delay_1ms(300); // 等待传感器完成测量
        // 读取数据并计算光照强度
        read_data(I2C3, BH1750_ADDRESS, read_buffer, 2);
        light_level = (read_buffer[0] << 8) | read_buffer[1];
        float lux = light_level / 1.2;
        printf("Light intensity: %.2f lux\n", lux);

    }
}

 

 

逻辑分析仪采样的写

 

 

 

逻辑分析仪采样的读

 

 

 

实验效果

WeChat_20240608003734

 

 

 

代码如下

06-I2C_BH1750.zip (47.75 KB, 下载次数: 1)

 

 

额外补充

 

逻辑分析仪是个好东西,特别是在某些情况你并不确定你代码写的是否正常并且是否正常输出的时候,可以非常轻松的用逻辑分析仪捕获输出情况从而来调整代码。要求不高的话可以使用树莓派

最新回复

  我记得当年我调试单总线,死活搞不了,最后有大佬让我知道有逻辑分析仪这东西,才算明白如何看时序。   详情 回复 发表于 2024-6-10 18:59
点赞 关注
 
 

回复
举报

6960

帖子

11

TA的资源

版主

沙发
 

 

我记得当年我调试单总线,死活搞不了,最后有大佬让我知道有逻辑分析仪这东西,才算明白如何看时序。

点评

哎,确实。不过这开发板调试还很方便。我用Bl616都不知道怎么调试  详情 回复 发表于 2024-6-10 20:48
 
 
 

回复

192

帖子

4

TA的资源

纯净的硅(初级)

板凳
 
lugl4313820 发表于 2024-6-10 18:59   我记得当年我调试单总线,死活搞不了,最后有大佬让我知道有逻辑分析仪这东西,才算明白如何看时 ...

哎,确实。不过这开发板调试还很方便。我用Bl616都不知道怎么调试

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
推荐帖子
程昌南同志的AT91SAM7S64调试笔记

RT

推荐一款低功耗段式液晶屏

看论坛正在做低功耗时钟,我刚好手头有个东西也需要低功耗显示,向大家推荐北京青云的LCM061A段式模块,主要是3.3V下可以工作, ...

手把手教你做XDS100v2仿真器

最先知道XDS100是几年前参加TI MCUDAY的时候获赠的一个利尔达的MiniStick开发板,上面有一个XDS100的仿真器带一个28027的核心板 ...

C2000 Piccolo LaunchPad 资料

106104 106105 106106 106107 106108 106109 106110 106111 106112 106113 106114 106115 106116 106117 106118 ...

按键扫描程序分享【装载】

新型的按键扫描程序 不过我在网上游逛了很久,也看过不少源程序了,没有发现这种按键处理办法的踪迹,所以,我将他共享出来,和 ...

蓝牙5标准

蓝牙技术联盟正式宣布了蓝牙5.0标准,经过数月的修订,现在标准正式定案并对外发布。其实这一代叫蓝牙5.0是不准确的,因为官 ...

【EVK-NINA-B400 评估套件】+开发环境

由于采用了openCPU架构,EVK-NINA-B400 评估套件开发环境搭建,基本上就是Nordic SDK开发环境的搭建。 最近Nordic做了直 ...

第五章-芯片封装与测试

书中的第五章介绍了芯片的封装与测试,我对于芯片的封装的理解就是将裸片加工后的晶圆进行保护并且将功能引脚引出来,对于封装我 ...

【得捷电子Follow me第2期】 ESP32实现简单的联网天气时钟

# 【得捷电子Follow me第2期】 ESP32实现简单的联网天气时钟 > ### 演示视频链接 > https://training.eeworld.com.cn/video/ ...

【先楫HPM6750EVK2测评】体验ADC功能

1、新建RTT工程,工程中添加对ADC的驱动: 786310 2、保存工程后,添加测试代码。 3、我们根据原理图上的J10接个,只有PE2 ...

关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表