【GD32F427开发板试用】硬件IIC读取SHT40温湿度传感器
创始人
2024-05-20 09:36:08
0

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动,更多开发板试用活动请关注极术社区网站。作者:烟花易冷

介绍

很荣幸又能再次的参加技术社区的开发板试用活动,此次参加用的是GD32F427系列的芯片,该芯片相较于GDF310系列的资源可以说非常丰富了。本次试用的项目是试用板子上面的iic外设读取传感器的温度。

准备工作

拿到板子以后,LED闪烁正常,说明板子正常。

由于以前用的MDK开发环境,本次想要改用IAR的环境,此处需要添加支持包,首先要把这个后缀名改为exe

另外,必须以管理员身份运行,能正确识别到本机IAR的安装路径才算成功,否则安装是不成功的。

另外这个板子配置串口也有些小波折,这里参考了这位的教程:https://aijishu.com/a/1060000000367387
之后实现了printf的输出。

硬件连接

如图所示,iic的通信只需要SDA和SCL两根线。
IIC通信过程由开始、结束、发送、响应、接收五个部分构成。
1、(在发送、接收数据的时候)当SCL为高电平时,SDA线不允许变化;当SCL线为低电平时,SDA线可以任意0、1变化。
2、(在任意时候)只有当SCL为高电平时,IIC电路才对SDA线上的电平(0或者1)进行记录,当SCL线为低电平时,无论SDA是高还是低,IIC电路都不对SDA进行采样。

空闲状态:SDA和SCL都为高

开始和停止:
开始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平。

停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号
应答:
发送器每发送一个字节,就在时钟脉冲9期间释放数据先,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。

对于反馈有效应答位ACK的要求是,接收器在第9个时钟脉冲之前的低电平期间将SDA线拉低,并且确保在该时钟的高电平期间位稳定的低电平。如果接收器是主控器,则在它收到最后一个字节后,发送一个NACK信号,以通知被控发送器结束数据发送,并释放SDA线,以便主控接收器发送一个停止信号P

软件实现

通过参考demo,我们可以很快的试用iic,我们使用PB8 和PB9来做scl和sdl
iic配置的代码如下

时钟配置
/* enable GPIOB clock */rcu_periph_clock_enable(RCU_GPIOB);/* enable I2C1 clock */rcu_periph_clock_enable(RCU_I2C1);

GPIO配置

/* I2C0 and I2C1 GPIO ports *//* connect PB8 to I2C0_SCL */gpio_af_set(GPIOB, GPIO_AF_4, GPIO_PIN_8);/* connect PB9 to I2C0_SDA */gpio_af_set(GPIOB, GPIO_AF_4, GPIO_PIN_9);

iic 配置

/* configure GPIO pins of I2C0 */gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_8);gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_8);gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9);gpio_output_options_set(GPIOB, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_9);/* configure I2C clock */i2c_clock_config(I2C0, 100000, I2C_DTCY_2);/* configure I2C address */i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, I2C0_SLAVE_ADDRESS7);/* enable I2C0 */i2c_enable(I2C0);/* enable acknowledge */i2c_ack_config(I2C0, I2C_ACK_ENABLE);

上述配置好了以后,我们就能正常使用i2c了,我们需要对原始api进行一些简单的封装。

void I2C_LeaderWrite(uint16_t followerAddress, , uint8_t targetAddress, uint8_t *txBuff,uint8_t numBytes) {/* wait until I2C bus is idle */while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));/* send a start condition to I2C bus */i2c_start_on_bus(I2C0);/* wait until SBSEND bit is set */while (!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));/* send slave address to I2C bus */i2c_master_addressing(I2C0, followerAddress, I2C_TRANSMITTER);/* wait until ADDSEND bit is set */while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));/* clear ADDSEND bit */i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);/* wait until the transmit data buffer is empty */while (!i2c_flag_get(I2C0, I2C_FLAG_TBE));for (i = 0; i < numBytes; i++) {/* data transmission */i2c_data_transmit(I2C0, txBuff[i]);/* wait until the TBE bit is set */while (!i2c_flag_get(I2C0, I2C_FLAG_TBE));}/* send a stop condition to I2C bus */i2c_stop_on_bus(I2C0);/* wait until stop condition generate */while (I2C_CTL0(I2C0) & 0x0200);
}
void I2C_LeaderRead(uint16_t followerAddress, uint8_t targetAddress, uint8_t *rxBuff,uint8_t numBytes) {/* wait until I2C bus is idle */while (i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));/* send a start condition to I2C bus */i2c_start_on_bus(I2C0);/* wait until SBSEND bit is set */while (!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));/* send slave address to I2C bus */i2c_master_addressing(I2C0, followerAddress, I2C_TRANSMITTER);/* wait until ADDSEND bit is set */while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));/* clear the ADDSEND bit */i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);/* wait until the transmit data buffer is empty */while (SET != i2c_flag_get(I2C0, I2C_FLAG_TBE));/* enable I2C0*/i2c_enable(I2C0);/* send the EEPROM's internal address to write to */i2c_data_transmit(I2C0, targetAddress);/* wait until BTC bit is set */while (!i2c_flag_get(I2C0, I2C_FLAG_BTC));/* send a start condition to I2C bus */i2c_start_on_bus(I2C0);/* wait until SBSEND bit is set */while (!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));/* send slave address to I2C bus */i2c_master_addressing(I2C0, followerAddress, I2C_RECEIVER);/* wait until ADDSEND bit is set */while (!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));/* clear the ADDSEND bit */i2c_flag_clear(I2C0, I2C_FLAG_ADDSEND);/* while there is data to be read */for (int i = 0; i < numBytes; i++) {/* code *//* read a data from I2C_DATA */rxBuff[i++] = i2c_data_receive(I2C0);/* send a stop condition */i2c_stop_on_bus(I2C0);}/* wait until the stop condition is finished */while (I2C_CTL0(I2C0) & 0x0200);/* enable acknowledge */i2c_ack_config(I2C0, I2C_ACK_ENABLE);i2c_ackpos_config(I2C0, I2C_ACKPOS_CURRENT);
}

如上,我们的MCU就能作为主机来发送和接受了
查阅sht40的手册可以得到读取的命令以及转换关系

主函数代码如下

int main(void)
{my_iic_init():init_sensor_sht40();while(1) {delay_1ms(1000);get_sensor_sht40(&temp,&hum);printf ("get T:%d, H: %d",temp,hum);}
}

结果定时采集当前的环境的数据。

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...