news 2026/5/16 1:16:40

27.MPSOC FPGA 驱动PCF8574

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
27.MPSOC FPGA 驱动PCF8574

上一篇记录了AHT20,本篇记录下PCF8574,原理类似:

#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <linux/i2c-dev.h> #include <errno.h> #include <stdint.h> /************************** PCF8574配置 *****************************/ #define PCF8574_SLAVE_ADDR 0x23 // PCF8574 7位I2C地址(A0=1、A1=1、A2=0) #define PCF8574_IO_NUM 8 // 8个IO口(P0-P7) #define PCF8574_IO_DIR 0x0F // P0-P3输出(0),P4-P7输入(1) #define I2C_DEV_PATH "/dev/i2c-1"// 对应裸机的IIC1 /************************** 函数声明 *****************************/ int pcf8574_init(int fd); int pcf8574_set_output(int fd, uint8_t output_val); int pcf8574_get_input(int fd, uint8_t *input_val); int pcf8574_set_pin_level(int fd, uint8_t pin, uint8_t level); int i2c_write(int fd, uint8_t *buf, int len); int i2c_read(int fd, uint8_t *buf, int len); int main(int argc, char *argv[]) { int fd; uint8_t output_cnt = 0; uint8_t input_val, output_val; // 1. 打开I2C设备文件(/dev/i2c-1) fd = open(I2C_DEV_PATH, O_RDWR); if (fd < 0) { perror("Failed to open /dev/i2c-1"); return -1; } // 2. 设置PCF8574从机地址(0x23) if (ioctl(fd, I2C_SLAVE, PCF8574_SLAVE_ADDR) < 0) { perror("Failed to set PCF8574 slave address"); close(fd); return -1; } // 3. 初始化PCF8574(默认输出低电平) if (pcf8574_init(fd) != 0) { fprintf(stderr, "PCF8574 init failed\n"); close(fd); return -1; } printf("PCF8574 init success (Slave Addr: 0x%02X)\n", PCF8574_SLAVE_ADDR); // 4. 循环测试:对齐裸机逻辑(P0-P3输出循环,P4-P7读输入) while (1) { // 设置P0-P3输出电平(循环0-15) output_val = output_cnt % 16; if (pcf8574_set_output(fd, output_val) == 0) { printf("Set Output (P0-P3): 0x%02X (Binary: %04b)\n", output_val, output_val); } else { fprintf(stderr, "Set Output Failed\n"); } // 读取P4-P7输入电平 if (pcf8574_get_input(fd, &input_val) == 0) { // 屏蔽输出位,仅保留P4-P7(右移4位方便查看) input_val = (input_val & PCF8574_IO_DIR) >> 4; printf("Read Input (P4-P7): 0x%02X (Binary: %04b)\n", input_val, input_val); } else { fprintf(stderr, "Read Input Failed\n"); } // 示例:单独控制P1口电平(每2次循环翻转一次) if (output_cnt % 2 == 0) { pcf8574_set_pin_level(fd, 1, 1); // P1置高 printf("Set P1 Level: HIGH\n"); } else { pcf8574_set_pin_level(fd, 1, 0); // P1置低 printf("Set P1 Level: LOW\n"); } output_cnt++; sleep(1); // 1秒循环,对齐裸机 } close(fd); return 0; } /** * @brief 初始化PCF8574(默认输出低电平) * @param fd: I2C设备文件描述符 * @return 0成功,-1失败 */ int pcf8574_init(int fd) { return pcf8574_set_output(fd, 0x00); // 输出口默认低电平 } /** * @brief 设置PCF8574输出口电平(仅P0-P3有效) * @param fd: I2C设备文件描述符 * @param output_val: 输出值(仅低4位有效) * @return 0成功,-1失败 */ int pcf8574_set_output(int fd, uint8_t output_val) { uint8_t write_buf[1]; // 逻辑对齐裸机:输出口设为指定值,输入口设为1(高阻) write_buf[0] = (output_val & (~PCF8574_IO_DIR)) | PCF8574_IO_DIR; if (i2c_write(fd, write_buf, 1) != 1) { return -1; } usleep(1000); // 短暂等待总线稳定 return 0; } /** * @brief 读取PCF8574输入口电平(仅P4-P7有效) * @param fd: I2C设备文件描述符 * @param input_val: 存储输入值的指针 * @return 0成功,-1失败 */ int pcf8574_get_input(int fd, uint8_t *input_val) { uint8_t read_buf[1] = {0}; if (i2c_read(fd, read_buf, 1) != 1) { return -1; } *input_val = read_buf[0]; return 0; } /** * @brief 设置PCF8574指定输出Pin的电平(对齐裸机的SetPinLevel函数) * @param fd: I2C设备文件描述符 * @param pin: 目标Pin(0-7) * @param level: 电平(0=低,1=高) * @return 0成功,-1失败 */ int pcf8574_set_pin_level(int fd, uint8_t pin, uint8_t level) { // 检查Pin合法性+是否为输出口 if (pin >= PCF8574_IO_NUM || (PCF8574_IO_DIR & (1 << pin))) { fprintf(stderr, "Pin %d is invalid or not an output pin!\n", pin); return -1; } // 读取当前IO状态 uint8_t current_val; if (pcf8574_get_input(fd, &current_val) != 0) { return -1; } // 屏蔽输入口位,仅保留当前输出口状态 current_val &= ~PCF8574_IO_DIR; // 修改目标Pin电平 if (level == 0) { current_val &= ~(1 << pin); // 置低 } else { current_val |= (1 << pin); // 置高 } // 写回新状态 return pcf8574_set_output(fd, current_val); } /** * @brief Linux I2C写操作封装 * @param fd: I2C设备描述符 * @param buf: 写缓冲区 * @param len: 长度 * @return 实际写入长度,失败返回-1 */ int i2c_write(int fd, uint8_t *buf, int len) { int ret = write(fd, buf, len); if (ret < 0) { perror("I2C write failed"); return -1; } return ret; } /** * @brief Linux I2C读操作封装 * @param fd: I2C设备描述符 * @param buf: 读缓冲区 * @param len: 长度 * @return 实际读取长度,失败返回-1 */ int i2c_read(int fd, uint8_t *buf, int len) { int ret = read(fd, buf, len); if (ret < 0) { perror("I2C read failed"); return -1; } return ret; }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/10 20:26:57

AI大模型学习全攻略:产品经理必看,程序员必备的实用指南

本文探讨AI大模型发展现状及对产品经理的影响&#xff0c;提供把握机遇的方法&#xff0c;包括技术理解、需求洞察、产品规划和跨团队协作。详细介绍学习路径&#xff1a;基础学习、编程技能、理论与实践、专业课程、社区参与和持续跟踪。同时提供学习路线、报告合集、经典书籍…

作者头像 李华
网站建设 2026/5/9 1:11:07

团队协作必备!SimpleMindMap + cpolar,思维导图随时共享

文章目录前言1. Docker一键部署思维导图2. 本地访问测试3. Linux安装Cpolar4. 配置公网地址5. 远程访问思维导图6. 固定Cpolar公网地址7. 固定地址访问前言 SimpleMindMap 是一款支持私有化部署的思维导图工具&#xff0c;能通过拖拽操作快速创建组织结构图、项目规划图等&…

作者头像 李华
网站建设 2026/5/15 6:29:08

【优化选址】基于遗传算法GA求解物流网络选址优化问题附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f34a;个人信条&#xff1a;格物致知,完整Matlab代码获取及仿真…

作者头像 李华
网站建设 2026/5/13 13:24:21

【Go/Python/Java】基础语法+核心特性对比

文章目录目录引言一、核心技术维度对比表二、分语言核心语法深度解析2.1 Go语言&#xff1a;简洁高效的“并发王者”2.1.1 变量声明与类型系统&#xff08;零值初始化指针&#xff09;2.1.2 流程控制&#xff08;仅for循环switch无穿透&#xff09;2.1.3 错误处理&#xff08;e…

作者头像 李华
网站建设 2026/5/13 13:56:41

【AIGC】RealVideo:一种基于自回归扩散视频生成的实时流媒体对话系统

系统概览图RealVideo 系统工作流程概述系统工作流程始于角色初始化&#xff1a;用户提供参考图像和参考语音文件用于克隆&#xff0c;系统据此实例化角色。用户还可以设置系统提示&#xff0c;指定模型应扮演的角色。随后&#xff0c;RealVideo 通过文本输入与用户交互。用户消…

作者头像 李华
网站建设 2026/5/14 22:41:23

针对模拟芯片发热的热源测试系统设计方案

&#x1f393;作者简介&#xff1a;科技自媒体优质创作者 &#x1f310;个人主页&#xff1a;莱歌数字-CSDN博客 &#x1f48c;公众号&#xff1a;莱歌数字 &#x1f4f1;个人微信&#xff1a;yanshanYH 211、985硕士&#xff0c;职场15年 从事结构设计、热设计、售前、产品设…

作者头像 李华