当前位置: 首页 > news >正文

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总线错误、设备无响应等)。

最终效果:

http://www.cnnetsun.cn/news/69934.html

相关文章:

  • 嵌入式系统时序图完全指南:从原理到实战
  • 小团队与大团队的管理差异
  • [CISCN2019 华东南赛区]Web4
  • AI编程革命!Claude Skills大揭秘:小白也能快速上手的Agent开发神器,大模型开发者必看!
  • 内点法求最优潮流附matlab代码
  • 三相PWM整流器有限集模型预测电流控制附Simulink仿真模型
  • 光伏四可“可观”功能:光伏电站全景数字化的底层支撑技术
  • 如何用FLUX.1-dev镜像在本地部署下一代AI绘画模型?
  • 基于 Comsol 移动网格方法的激光熔池流动数值模拟
  • BLDC无刷直流电机Matlab仿真:转速电流双闭环控制及有感无感换相方式研究
  • [光学原理与应用-491]:水冷机、零气模块CDA、功率计等影响266皮秒紫外激光器的种子源1064nm功率稳定性结果的主要因素有哪些?
  • 昆仑通态MCGS与欧姆龙E5CC温控器通讯实战:PID模式及输出启停控制
  • 通达信〖逆势突破强牛〗指标公式 逆市环境中率先突破前期重要压力位 较强内在上涨动力
  • 基于扰动观测器的永磁同步电机(PMSM)模型预测控制(MPC)仿真探索
  • AEB联合仿真算法设计:Carsim2019.0+Matlab/Simulink2021a实现...
  • Java毕设选题推荐:基于springboot个人博客系统的设计与实现基于SpringBoot+Vue个人博客系统的设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】
  • Java毕设选题推荐:基于springboot停车场车位预约系统基于Java springboot停车场管理系统停车位预约【附源码、mysql、文档、调试+代码讲解+全bao等】
  • Java毕设选题推荐:基于springboot的无人化、线上化、数据化海洋馆预约系统的设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】
  • Ascend C高级API应用:InitGlobalMemory与Pad操作的底层原理
  • Java毕设选题推荐:基于Java Web的新能源汽车信息咨询服务基于SpringBoot+Vue的新能源汽车信息咨询服务的设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 开箱即用的 GoWind Admin|风行,企业级前后端一体中后台框架:OPA 集成指南:从原理到实践
  • Object.defineProperty和Proxy实现拦截的区别
  • 若依物联网
  • PSEN1抗体:如何揭示阿尔茨海默病致病机制与治疗新靶点?
  • Docker Engine 升级指南:保障容器安全的关键步骤
  • 基于zigbee灯光控制照明及色温调节系统的设计与实现(有完整资料)
  • 7、Python高级语法:描述器、属性与元编程实战
  • 【开题答辩全过程】以 基于java技术的校园一卡通系统的设计与实现为例,包含答辩的问题和答案
  • 11、Python 包与应用开发全解析
  • django基于智能推荐算法的全屋定制平台网站设计