news 2026/5/1 1:39:28

26.MPSOC FPGA linux读AHT20传感器

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
26.MPSOC FPGA linux读AHT20传感器

一、vivado 工程搭建

因为十分简单,不在赘述。

生成平台文件,导出,建立vitis linux 设备树工程,不在赘述。

生成的设备树文件:

axi_iic_0: i2c@80000000 { #address-cells = <1>; #size-cells = <0>; clock-names = "s_axi_aclk"; clocks = <&zynqmp_clk 71>; compatible = "xlnx,axi-iic-2.1", "xlnx,xps-iic-2.00.a"; interrupt-names = "iic2intc_irpt"; interrupt-parent = <&gic>; interrupts = <0 89 4>; reg = <0x0 0x80000000 0x0 0x10000>; };

将设备树文件放到linux下编译,生成映像文件:略。

二、AHT20读

在Linux操作系统下,你完全可以不编写内核驱动程序,直接通过系统提供的I2C用户空间接口(/dev/i2c-2)编写应用程序访问AHT20,这是嵌入式Linux中访问I2C外设最常用、最高效的方式。

核心原理

Linux内核已自带i2c-dev驱动(通用I2C字符设备驱动),会将硬件I2C控制器(如你裸机中用的IIC1)映射为/dev/i2c-x设备文件,用户空间程序通过操作该文件(open/read/write/ioctl)即可实现I2C通信,无需重复编写底层驱动。

#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <linux/i2c-dev.h> #include <errno.h> /************************** AHT20配置 *****************************/ #define AHT20_SLAVE_ADDR 0x38 // AHT20 7位I2C地址 #define AHT20_CMD_INIT 0xBE // 初始化指令 #define AHT20_CMD_MEASURE 0xAC // 测量指令 #define AHT20_DATA_LEN 6 // 读取数据长度 /************************** 函数声明 *****************************/ int aht20_init(int fd); int aht20_read_data(int fd, float *temp, float *humi); int i2c_write(int fd, unsigned char *buf, int len); int i2c_read(int fd, unsigned char *buf, int len); int main(int argc, char *argv[]) { int fd; float temperature, humidity; const char *i2c_dev = "/dev/i2c-2"; // 1. 打开I2C设备文件 fd = open(i2c_dev, O_RDWR); if (fd < 0) { perror("Failed to open i2c device"); return -1; } // 2. 设置I2C从机地址 if (ioctl(fd, I2C_SLAVE, AHT20_SLAVE_ADDR) < 0) { perror("Failed to set slave address"); close(fd); return -1; } // 3. 初始化AHT20 if (aht20_init(fd) != 0) { fprintf(stderr, "AHT20 init failed\n"); close(fd); return -1; } printf("AHT20 init success\n"); // 4. 循环读取温湿度 while (1) { if (aht20_read_data(fd, &temperature, &humidity) == 0) { // 格式化输出(与你裸机逻辑一致) int temp_int = (int)(temperature * 100 + 0.5); int humi_int = (int)(humidity * 100 + 0.5); printf("Temperature: %d.%02d ℃, Humidity: %d.%02d %%RH\n", temp_int/100, temp_int%100, humi_int/100, humi_int%100); } else { fprintf(stderr, "Read AHT20 data failed\n"); } sleep(1); // 1秒间隔 } close(fd); return 0; } /** * @brief 初始化AHT20 * @param fd: I2C设备文件描述符 * @return 0成功,-1失败 */ int aht20_init(int fd) { unsigned char init_cmd[3] = {AHT20_CMD_INIT, 0x08, 0x00}; // 发送初始化指令 if (i2c_write(fd, init_cmd, 3) != 3) { return -1; } usleep(10000); // 等待初始化完成(10ms) return 0; } /** * @brief 读取AHT20温湿度数据 * @param fd: I2C设备文件描述符 * @param temp: 输出温度值(℃) * @param humi: 输出湿度值(%RH) * @return 0成功,-1失败 */ int aht20_read_data(int fd, float *temp, float *humi) { unsigned char measure_cmd[3] = {AHT20_CMD_MEASURE, 0x33, 0x00}; unsigned char read_buf[AHT20_DATA_LEN] = {0}; // 发送测量指令 if (i2c_write(fd, measure_cmd, 3) != 3) { return -1; } usleep(80000); // 等待测量完成(80ms) // 读取6字节数据 if (i2c_read(fd, read_buf, AHT20_DATA_LEN) != AHT20_DATA_LEN) { return -1; } // 校验数据有效性(第1字节bit7=0表示有效) if (read_buf[0] & 0x80) { fprintf(stderr, "AHT20 data invalid\n"); return -1; } // 湿度计算:(read_buf[1]<<12 | read_buf[2]<<4 | read_buf[3]>>4) / 2^20 * 100 unsigned int humi_raw = (read_buf[1] << 12) | (read_buf[2] << 4) | (read_buf[3] >> 4); *humi = (float)humi_raw / (1 << 20) * 100.0; // 温度计算:((read_buf[3]&0x0F)<<16 | read_buf[4]<<8 | read_buf[5]) / 2^20 * 200 - 50 unsigned int temp_raw = ((read_buf[3] & 0x0F) << 16) | (read_buf[4] << 8) | read_buf[5]; *temp = (float)temp_raw / (1 << 20) * 200.0 - 50.0; return 0; } /** * @brief I2C写数据 * @param fd: I2C设备文件描述符 * @param buf: 待发送数据缓冲区 * @param len: 数据长度 * @return 实际发送字节数,失败返回-1 */ int i2c_write(int fd, unsigned char *buf, int len) { int ret = write(fd, buf, len); if (ret < 0) { perror("I2C write failed"); return -1; } return ret; } /** * @brief I2C读数据 * @param fd: I2C设备文件描述符 * @param buf: 接收数据缓冲区 * @param len: 期望读取长度 * @return 实际读取字节数,失败返回-1 */ int i2c_read(int fd, unsigned char *buf, int len) { int ret = read(fd, buf, len); if (ret < 0) { perror("I2C read failed"); return -1; } return ret; }

编译与运行

  • 编译命令(需交叉编译,替换为你的交叉编译器):
arm-linux-gnueabihf-gcc aht20_app.c -o aht20_app -O2
  • 拷贝到开发板
scp aht20_app root@<开发板IP>:/root/
  • 运行程序(需root权限):
chmod +x aht20_app ./aht20_app

关键注意事项

  • 权限问题/dev/i2c-2默认可能只有root可访问,若普通用户运行需修改权限:
chmod 666 /dev/i2c-2
  • I2C地址确认:AHT20的7位地址是0x38i2c-dev驱动无需转换为8位(驱动会自动处理);
  • 时序保障:测量指令发送后需等待至少75ms再读取数据,否则数据无效;
  • 错误处理:代码中增加了perror打印系统错误,便于调试(如I2C总线错误、设备无响应等)。

最终效果:

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 4:42:44

煤层卸压开采瓦斯越流以及塑性变形 煤层工作开挖过程,会引起邻近煤岩层应力、变形场发生变化,以及...

煤层卸压开采瓦斯越流以及塑性变形 煤层工作开挖过程&#xff0c;会引起邻近煤岩层应力、变形场发生变化&#xff0c;以及引起临近煤层卸压&#xff0c;从而达到保护层开挖目的。 本模型根据煤岩层之间的位置关系&#xff0c;建立瓦斯流动场、煤岩弹塑性变形场&#xff0c;供大…

作者头像 李华
网站建设 2026/5/1 6:51:09

sxstrace.exe

sxstrace.exe找了个老版本的&#xff0c;嘿嘿

作者头像 李华
网站建设 2026/5/1 5:44:18

通信系统仿真:数字调制与解调技术_(29).通信系统性能评估

通信系统性能评估 在通信系统的设计和优化过程中&#xff0c;性能评估是一个至关重要的环节。通过性能评估&#xff0c;我们可以验证系统的设计是否满足预定的性能指标&#xff0c;发现系统中的潜在问题&#xff0c;并进行相应的优化。本节将详细介绍通信系统性能评估的基本原理…

作者头像 李华
网站建设 2026/5/1 5:44:53

Matlab/Simulink 下多风电场协调虚拟惯性与调频控制探索

matlab/simulink多风电场协调的虚拟惯性&#xff0c;下垂控制一次调频&#xff0c;风电渗透率可调&#xff0c;目前为20%。 所有参数均设计好&#xff0c;可直接运行。 可加入超速减载&#xff0c;变桨控制&#xff0c;频率二次跌落转速回复设计。 多个风电场协调更符合实际&am…

作者头像 李华