【51单片机入门记录】A/D、D/A转换器PCF859应用
目录
一、IIC初始化代码
二、开发板电路图
三、PCF8591读/写字节操作流程及相关函数
(1)PCF8591(AD)读操作流程及代码
(2)PCF8591(AD)写操作流程及代码
四、应用示例-显示电压值
一、IIC初始化代码
- 加载“iic.c文件”,主函数中添加iic.h头文件
- 调节软件延迟时长(全部扩大十倍即可)
- 编写PCF8591读写函数,并且在头文件中定义
- 编写用户用能函数
二、开发板电路图
(图源第十五届蓝桥杯电子赛资源包)

- 根据图以及前面所学的EEPROM存储器的位置,可知IIC总线上有两个设备,一个是PCF85191另一个是AT24C02 EEPROM存储器。
- AIN1(光敏电阻线路)、AIN3(活动变阻器、电压采集)

三、PCF8591读/写字节操作流程及相关函数
(1)PCF8591(AD)读操作流程及代码
- 主控器发出起始信号
- 主控器发出寻址字节(写:0X90)
- 被控器做出应答后
- 主控器发出控制字节(写:)
- 被控器做出应答后
- 主控器发出停止信号
- 主控器发出起始信号
- 主控器发出寻址字节(读:0x91)
- 被控器做出应答后
- 主控器从被控器读出数据字节,主控器发出应答
- 主控器发出停止信号
unsigned char AD_read(unsigned char add)
{unsigned char dat;I2CStart();I2CSendByte(0X90);I2CWaitAck();I2CSendByte(add);I2CWaitAck();I2CStop();I2CStart();I2CSendByte(0X91);I2CWaitAck();dat=I2CReceiveByte();I2CSendAck(1);I2CStop();return dat;
}
(2)PCF8591(AD)写操作流程及代码
- 主控器发出起始信号
- 主控器发出寻址字节(写:0X90)
- 被控器做出应答后
- 主控器发出控制字节(写)
- 被控器做出应答后
- 主控器发出DA输出数据字节(写)
- 被控器做出应答后
- 主控器发出停止信号
void AD_write(unsigned char dat)
{I2CStart();I2CSendByte(0X90);I2CWaitAck();I2CSendByte(0X40);I2CWaitAck();I2CSendByte(dat);I2CWaitAck();I2CStop();}
四、应用示例-显示电压值
//iic.c
#include <STC15F2K60S2.H>
#include<intrins.h>
#define DELAY_TIME 50//总线引脚定义
sbit sda = P2^1;
sbit scl = P2^0; //
static void I2C_Delay(unsigned char n)
{do{_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); }while(n--);
}//
void I2CStart(void)
{sda = 1;scl = 1;I2C_Delay(DELAY_TIME);sda = 0;I2C_Delay(DELAY_TIME);scl = 0;
}//
void I2CStop(void)
{sda = 0;scl = 1;I2C_Delay(DELAY_TIME);sda = 1;I2C_Delay(DELAY_TIME);
}//
void I2CSendByte(unsigned char byt)
{unsigned char i;for(i=0; i<8; i++){scl = 0;I2C_Delay(DELAY_TIME);if(byt & 0x80){sda = 1;}else{sda = 0;}I2C_Delay(DELAY_TIME);scl = 1;byt <<= 1;I2C_Delay(DELAY_TIME);}scl = 0;
}//
unsigned char I2CReceiveByte(void)
{unsigned char da;unsigned char i;for(i=0;i<8;i++){ scl = 1;I2C_Delay(DELAY_TIME);da <<= 1;if(sda) da |= 0x01;scl = 0;I2C_Delay(DELAY_TIME);}return da;
}//
unsigned char I2CWaitAck(void)
{unsigned char ackbit;scl = 1;I2C_Delay(DELAY_TIME);ackbit = sda; scl = 0;I2C_Delay(DELAY_TIME);return ackbit;
}//
void I2CSendAck(unsigned char ackbit)
{scl = 0;sda = ackbit; I2C_Delay(DELAY_TIME);scl = 1;I2C_Delay(DELAY_TIME);scl = 0; sda = 1;I2C_Delay(DELAY_TIME);
}unsigned char AD_read(unsigned char add)
{unsigned char dat;I2CStart();I2CSendByte(0X90);I2CWaitAck();I2CSendByte(add);I2CWaitAck();I2CStop();I2CStart();I2CSendByte(0X91);I2CWaitAck();dat=I2CReceiveByte();I2CSendAck(1);I2CStop();return dat;}
void AD_write(unsigned char dat)
{I2CStart();I2CSendByte(0X90);I2CWaitAck();I2CSendByte(0X40);I2CWaitAck();I2CSendByte(dat);I2CWaitAck();I2CStop();}
//IIC.h
#ifndef _IIC_H
#define _IIC_H
//
static void I2C_Delay(unsigned char n);//
void I2CStart(void);//
void I2CStop(void);//
void I2CSendByte(unsigned char byt);//
unsigned char I2CReceiveByte(void);//
unsigned char I2CWaitAck(void);//
void I2CSendAck(unsigned char ackbit);
//
unsigned char AD_read(unsigned char add);
void AD_write(unsigned char dat);#endif
//main.c
#include <STC15F2K60S2.H>
#include<intrins.h>
#include<IIC.h>#define uchar unsigned char
#define uint unsigned intunsigned char LED_Bit=0XFF;
unsigned char Actuator_Bit=0X00;#define LEDx_ON(n) { LED_Bit&=_crol_(0XFE,n-1); P0=LED_Bit; P2|=0X80; P2&=0X9F; P2&=0X1F;}
#define LEDx_OFF(n) { LED_Bit|=_crol_(0X01,n-1); P0=LED_Bit; P2|=0X80; P2&=0X9F; P2&=0X1F;}#define Buzzer_ON Actuator_Bit|=0x40; P0=Actuator_Bit; P2|=0XA0; P2&=0XBF; P2&=0X1F;
#define Buzzer_OFF Actuator_Bit&=0XBF; P0=Actuator_Bit; P2|=0XA0; P2&=0XBF; P2&=0X1F;
#define Relay_ON Actuator_Bit|=0x10; P0=Actuator_Bit; P2|=0XA0; P2&=0XBF; P2&=0X1F;
#define Relay_OFF Actuator_Bit&=0XEF; P0=Actuator_Bit; P2|=0XA0; P2&=0XBF; P2&=0X1F;unsigned char code tab[]= {0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,\0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10,\0XBF,0XFF};
unsigned char KEY_Value = 0 ;
unsigned char DigCom=0;
unsigned char DigBuf[8] = {10,10,10,10,10,10,10,10};unsigned char LED = 1 ;
unsigned int LED_tt =0;
bit LED_Ref = 0 ;unsigned int SEG_tt =0; //定义一个数码管计数时间标识位
bit SEG_Ref = 0 ; //定义一个数码管刷新标识位
bit SEG_Run = 0 ; //定义一个控制数码管运行标识位
unsigned int Num = 999 ;unsigned char Open;unsigned char EEPROM_Write[8] = {2,3,4,5,6,7,8,9};
unsigned char EEPROM_Read[8] = {0,0,0,0,0,0,0,0};unsigned int AD_VALUE=0;
unsigned int AD_tt =0;
bit AD_Ref =0;void ALL_Init(void);
void Delay_MS(unsigned int MS);
void KeyScan(void);
void ArrKeyScan(void);
void Timer0Init(void); //1毫秒@11.0592MHzvoid main(void)
{ALL_Init();Timer0Init();EA=1;ET0=1;while(1){if(AD_Ref == 1){AD_Ref = 0 ;AD_VALUE = AD_read(0X03);AD_write(AD_VALUE);AD_VALUE = AD_VALUE * 1.96;DigBuf[2]=21;DigBuf[3]=21;DigBuf[4]=21;DigBuf[5]=AD_VALUE/100 + 10; DigBuf[6]=AD_VALUE%100/10;DigBuf[7]=AD_VALUE%10; }KeyScan();if(KEY_Value==7){KEY_Value=0;SEG_Run = 1 ;}if(KEY_Value==6){KEY_Value=0;SEG_Run = 0 ;}if(KEY_Value==5){KEY_Value=0;LEDx_ON(1);Buzzer_ON;}if(KEY_Value==4){KEY_Value=0;LEDx_OFF(1);Buzzer_OFF;} }
}void KeyScan(void)
{if(P30==0){Delay_MS(10);if(P30==0)KEY_Value = 7 ; while(!P30);}else if(P31==0){Delay_MS(10);if(P31==0)KEY_Value = 6 ; while(!P31);} else if(P32==0){Delay_MS(10);if(P32==0)KEY_Value = 5 ; while(!P32);} else if(P33==0){Delay_MS(10);if(P33==0)KEY_Value = 4 ; while(!P33);}
}void Timer0(void) interrupt 1
{P0=0X00;P2|=0XC0; // P2=P2|0XC0; XXXX XXXX | 1100 0000 = 11XX XXXXP2&=0XDF; // P2=P2&0XDF; 11XX XXXX & 1101 1111 = 110X XXXX P2&=0X1F; //关闭所有的74HC573锁存器 P0=tab[DigBuf[DigCom]]; P2|=0XE0; // P2=P2|0XE0; XXXX XXXX | 1110 0000 = 111X XXXXP2&=0XFF; // P2=P2&0XDF; 11XX XXXX & 1101 1111 = 110X XXXX P2&=0X1F; //关闭所有的74HC573锁存器P0=(0X01<<DigCom); //然后选中第一个数码管P2|=0XC0; // P2=P2|0XC0; XXXX XXXX | 1100 0000 = 11XX XXXXP2&=0XDF; // P2=P2&0XDF; 11XX XXXX & 1101 1111 = 110X XXXX P2&=0X1F; //关闭所有的74HC573锁存器if(++DigCom == 8)DigCom = 0 ;LED_tt++;if(LED_tt == 999) {LED_tt = 0 ; LED_Ref = 1 ;}if(++SEG_tt==1000){SEG_tt=0;SEG_Ref=1;}if(++AD_tt==500){AD_tt=0;AD_Ref=1;}
// XXX_tt++;
// if(++XXX_tt==NNN){XXX_tt=0;XXX_Ref=1;}
}void Timer0Init(void) //1毫秒@11.0592MHz
{AUXR |= 0x80; //定时器时钟1T模式TMOD &= 0xF0; //设置定时器模式TL0 = 0xCD; //设置定时初始值TH0 = 0xD4; //设置定时初始值TF0 = 0; //清除TF0标志TR0 = 1; //定时器0开始计时
}void Delay_MS(unsigned int MS)
{unsigned i,j;for(i=0;i<MS;i++)for(j=853;j>0;j--); //STC15单片机设置为853; STC8H单片机修改为1109;STC32G单片机修改为427;
}void ALL_Init(void)
{P0 =0X00; //先设置关闭蜂鸣器继电器的P0输出值(全关)P2|=0XA0; // 将P27 P25 设置为1 其他位保持不变P2&=0XBF; // 将P26设置为0 其他位保持不变P2&=0X1F; //关闭所有的74HC573锁存器P0 =0XFF; //先设置关闭所有的LED的P0输出值(全关)P2|=0X80; // 将P27设置为1 其他位保持不变P2&=0X9F; // 将P26 P25设置为0 其他位保持不变P2&=0X1F; //关闭所有的74HC573锁存器P0 =0X00; //先设置选择数码管位选的P0输出值(全不选)P2|=0XC0; // 将P27 P26 设置为1 其他位保持不变P2&=0XDF; // 将P26设置为0 其他位保持不变P2&=0X1F; //关闭所有的74HC573锁存器
}
相关文章:
【51单片机入门记录】A/D、D/A转换器PCF859应用
目录 一、IIC初始化代码 二、开发板电路图 三、PCF8591读/写字节操作流程及相关函数 (1)PCF8591(AD)读操作流程及代码 (2)PCF8591(AD)写操作流程及代码 四、应用示例-显示电压…...
设计模式(13):模板方法模式
场景: 实现一个功能时,整体步骤很固定,但是,某些部分易变。易变部分可以抽象出来,供子类实现。 开发中常见的场景 非常繁琐,各个框架,类库中都有它的影子,比如常见的有࿱…...
公众号申请上限怎么提升
一般可以申请多少个公众号?众所周知,在2013年前后,公众号申请是不限制数量的,后来企业开始限制申请50个,直到2018年的11月tx又发布,其中个人主体可申请公众号由2个调整为1个,企业主体由50个调整…...
【算法刷题day16】Leetcode:104.二叉树的最大深度 559.n叉树的最大深度 111.二叉树的最小深度 222.完全二叉树的节点个数
104.二叉树的最大深度 (优先掌握递归) 文档链接:[代码随想录] 题目链接:104.二叉树的最大深度 (优先掌握递归) 状态:ok 题目: 给定一个二叉树 root ,返回其最大深度。 二…...
电商技术揭秘一:电商架构设计与核心技术
文章目录 引言一、电商平台架构概述1.1 架构设计原则与架构类型选择1.2 传统电商平台架构与现代化架构趋势分析 二、高并发处理与负载均衡2.1 高并发访问特点分析与挑战2.2 负载均衡原理与算法选择 三、分布式数据库与缓存技术3.1 分布式数据库设计与一致性考量3.2 缓存策略与缓…...
Ubuntu 自启动应用程序的方法
1、自启动的方法 自启动应用程序可以在/etc/rc.local文件中调用脚本来启动应用程序,另外也可以自行编写一个服务来启动应用程序。这两种方法其实都是一种方法即使用服务来启动一个应用程序。rc.local脚本本身也是被一个rc.local的服务来调用的。如下图,可…...
Star GAN论文解析
论文地址:https://arxiv.org/pdf/1912.01865v1.pdf https://openaccess.thecvf.com/content_cvpr_2018/papers/Choi_StarGAN_Unified_Generative_CVPR_2018_paper.pdf 源码:stargan项目实战及源码解读-CSDN博客 1. 概述 在传统方法中&#x…...
全网最强JavaWeb笔记 | 万字长文爆肝JavaWeb开发——day06_数据库-MySQL-02
万字长文爆肝黑马程序员2023最新版JavaWeb教程。这套教程打破常规,不再局限于过时的老套JavaWeb技术,而是与时俱进,运用的都是企业中流行的前沿技术。笔者认真跟着这个教程,再一次认真学习一遍JavaWeb教程,温故而知新&…...
数据结构day2--双向链表
双向链表: 即可以从头遍历到尾部和从尾部遍历到头部的链表,每个结点包括两个链域:前驱指针域和后继指针域,所以比起单向链表,其可以在任意一个结点访问前后两个结点 关于双向链表的一个完整步骤为: 创建一个表头结构…...
蓝桥杯单片机真题实践篇
这里就不完全写思路过程代码什么的,这一篇文章就写我在训练真题中遇到的过程。 (呜呜呜,时间不够辣,能做多少算多少吧....) 十三届省赛题 问题1:数码管的数字消影不明显 (参考:蓝…...
前端pdf.js将pdf转为图片,尤其适合电子发票打印
写这个的原因就是打电子发票不方便,这个代码是纯js不需要后端服务直接将两张电子发票的pdf转为两张图片渲染到一张A4纸上面(完全不浪费,发票也不会变大),自动完成打印分页,点击打印即可。亲测可用所有电子发…...
第四百四十三回
文章目录 1. 概念介绍2. 思路与方法2.1 整体思路2.2 使用方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"自定义Action菜单"相关的内容,本章回中将介绍如何获取屏幕相关参数.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 我们在本…...
一分钟快速用上号称“音乐版ChatGPT”的suno AI,适合普通人的超简单教程!
随着AI的应用变广,各类AI程序已逐渐普及。AI已逐渐深入到人们的工作生活方方面面。而AI涉及的行业也越来越多,从最初的写作,到医疗教育,再到现在的音乐。 Suno是一个专业高质量的AI歌曲和音乐创作平台,用户只需输入简…...
干货!一文读懂:位像素海外仓系统的分销功能
随着跨境电商的蓬勃发展,海外仓系统的重要性日益凸显,成为企业在激烈市场竞争中脱颖而出的关键。当谈及海外仓系统的拓展功能,特别是其中的分销功能,正逐渐成为卖家们不可或缺的工具。 那么,这个神奇的分销功能究竟是…...
【洛谷】P1449 后缀表达式
题目描述 所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右新进行(不用考虑运算符的优先级)。 本题中运算符仅包含 -*…...
【MySQL】聚合函数和分组聚合
👦个人主页:Weraphael ✍🏻作者简介:目前学习计网、mysql和算法 ✈️专栏:MySQL学习 🐋 希望大家多多支持,咱一起进步!😁 如果文章对你有帮助的话 欢迎 评论💬…...
RDD算子(四)、血缘关系、持久化
1. foreach 分布式遍历每一个元素,调用指定函数 val rdd sc.makeRDD(List(1, 2, 3, 4)) rdd.foreach(println) 结果是随机的,因为foreach是在每一个Executor端并发执行,所以顺序是不确定的。如果采集collect之后再调用foreach打印…...
51之定时器与中断系统
目录 1.定时器与中断系统简介 1.1中断系统 1.2定时器 1.2.1定时器简介 1.2.2定时器大致原理及其配置 1.2.3定时器所需的所有配置总介 2.定时器0实现LED闪烁 3.使用软件生成定时器初始化程序 1.定时器与中断系统简介 1.1中断系统 首先,我们需要来了解一下什么…...
C语言中的内存函数
相比于内存函数,字符串函数和字符函数是对字符串和字符进行操作,内存函数是对内存进行操的。下面跟大家分享我学到的几个内存函数。 memcpy函数 void* memcpy(void* dest, const void* sour, size_t num); dest是目标地址,sour要拷贝的源地…...
JS继承与原型、原型链
在 JavaScript 中,继承是实现代码复用和构建对象关系的重要概念。本文将讨论原型链继承、构造函数继承以及组合继承等几种常见的继承方式,并提供相应的示例代码,并分析它们的特点、优缺点以及适用场景。 在开始讲解 JavaScript 的继承方式之…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
