news 2026/5/6 14:27:09

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/3 20:48:30

AI产品经理转型+大模型实战:收藏这套系统化学习资源,小白也能变专家

文章介绍AI产品经理职责、与传统产品经理的区别(需懂技术)、类型分类及必备技能&#xff0c;重点分享AI大模型学习资源&#xff0c;包括七阶段学习路线、300视频教程、数百本技术文档和面试题&#xff0c;帮助小白和程序员系统掌握大模型应用开发技能。1.AI产品经理是什么 回答…

作者头像 李华
网站建设 2026/4/28 16:51:32

基于Vue的电商后台管理系统的设计与实现qyf0i(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末

系统程序文件列表 系统功能 用户,商品分类,品牌信息,商家,商品信息,促销商品,咨询商家 开题报告内容 《基于Vue的电商后台管理系统的设计与实现》开题报告 一、选题背景、研究意义及国内外研究现状 1. 选题背景 随着互联网技术的快速发展和数字化转型的深入推进&#xff0…

作者头像 李华
网站建设 2026/5/5 8:37:15

RK3568 Android14 集成 HYM8563 外部 RTC (I2C接口)

RK3568 Android14 集成 HYM8563 外部 RTC (I2C接口) 前言 虽然 RK3568 SoC 内部自带了 RTC 控制器&#xff08;rtc-rkw808&#xff09;&#xff0c;但在很多工业板卡或手持设备设计中&#xff0c;为了更低的待机功耗和更灵活的电池备份方案&#xff0c;硬件工程师往往会选择外挂…

作者头像 李华
网站建设 2026/5/2 16:44:49

进程的状态及其 CPU 占用

1. R —— 唯一的 CPU 消费者这是最直观的状态&#xff0c;但这里有一个必须厘清的概念。定义&#xff1a;在内核源码中&#xff0c;R 并不意味着进程一定正在 CPU 上跑。它表明进程“要么是在运行中&#xff0c;要么在运行队列 (runqueue) 里” 。对 CPU 的占用&#xff1a;正…

作者头像 李华