PCF8591通过了测试
- 格式:pdf
- 大小:75.58 KB
- 文档页数:6
超级电容储能装置电压采集电路设计作者:朱芳来源:《科技资讯》2018年第21期摘要:介绍了超级电容储能系统的整体结构,对储能系统的各组成部分进行阐述和说明。
针对超级电容储能装置系统的特点和要求,设计了一种性能稳定、高精度的电压采集电路。
分析了电路的原理,给出了电路的原理图。
对电路的实际运行数据和测试数据进行了分析,通过软件处理和温度补偿,提高了电路的测量精度。
实验表明,该电压采集电路能够满足超级电容储能装置的要求,具有广泛的应用场景。
关键词:储能系统超级电容电压采集数据分析中图分类号:TM53 文献标识码:A 文章编号:1672-3791(2018)07(c)-0050-02随着新材料的不断发现和储能技术的飞速发展,储能装置在电动汽车、光伏系统、数据中心和轨道交通等领域获得了广泛的应用。
超级电容作为储能装置的重要组成部分,其性能的好坏影响着整个储能系统的稳定运行。
电压采集电路作为超级电容储能装置的重要组成部分,对系统的稳定运行起到十分重要的作用。
本文设计了一种高性价比的电压采集电路,电路采用LM358运算放大器实现,通过对超级电容两端的电压进行差分采集,获取超级电容的两端电压。
利用PCF8591实现采集电压数据的读取,AD转换后的数据存储在各通道的指定寄存器中,控制芯片通过I2C协议实现数据的读取。
通过对读取的电压和实际电压数据的对比,分析系统的电压采样精度。
利用软件调整和温度补偿方式,提高了系统的电压采样精度。
最后,给出了改进前后系统的电压采集曲线。
1 超级电容储能系统介绍超级电容作为一种新式储能元件,具有响应速度快、功率密度大、效率高、维护简单、对环境无污染等优点。
因超级电容器具备的优异的长寿命特性,其还可作为系统的备份电源使用,提高系统整体的可靠稳定性。
储能系统主要用于能量的存储,通过能量转化的方式将电能存储在超级电容器中。
目前,超级电容储能系统的应用场合较为广泛,其系统电路结构也有较大差异。
2009年5月企业技术开发引脚序号引脚名称功能描述1~4AIN0~AIN3模拟信号输入端0~5V5~7A 0~A 2器件硬件地址输入端,由硬件电路决定16、8VDD 、VSS 电源、地9、10SDA 、SCL I 2C 总线的数据线、时钟线11OSC 外部时钟输入端,内部时钟输出端12EXT 时钟选择线,EXT =0,使用内部时钟;EXT =1,使用外部时钟13AGND 模拟信号地15AOUT D/A 转换输出端,V AOUT =V AGND +V REF -V AGND2567i=0ΣD i2i基准电源端(0.6~5V ),取值大小影响D/A 转换输出电压。
当取值等于为VDD 时,输出电压为0~5V 。
14V REF表1PCF8591引脚功能描述基于PCF8591的I 2C 总线A/D 、D/A 转换陈柱峰,沈治国摘要:I 2C 总线是Philips(飞利浦)公司推出的串行总线,整个系统仅靠数据线(SDA )和时钟线(SCL )实现完善的全双工数据传输,文章介绍了具有I 2C 总线的A/D 、D/A 转换芯片PCF8591的内部结构图,引脚功能,A/D 、D/A 转换的控制方法,给出了A/D 、D/A 转换的软件编程的流程图和实例。
关键词:I 2C 总线;PCF8591;A/D 、D/A 转换中图分类号:TN792文献标识码:A文章编号:1006-8937(2009)09-0018-04Abstract:I 2C bus is the serial bus that Philips has introduced,the whole system of relying on the data line (SDA)and clock line (SCL)to achieve a comprehensive,full-duplex data transmission,introduced in this paper with I 2C Bus A/D 、D/A conversion chip PCF8591internal structure diagram,pin functions,A/D 、D/A conversion control methods,gave the A/D 、D/A conversion software programming flow chart and examples.Keywords :I 2C bus ;PCF8591;A/D 、D/A conversion (湖南现代物流职业技术学院物流工程系,湖南长沙410131)The I 2C bus A /D 、D /A conversion based on PCF8591CHEN Zhu-feng ,SHEN Zhi-guo(DepartmentofLogisticsEngineering,HunanVocationalandTechnicalCollegeofModernLogisticsEngineering,Changsha,Hunan410131,China)收稿日期:2009-01-30作者简介:陈柱峰(1973—),男,湖南长沙人,大学本科,助理试验师,主要从事电力电子技术方面的教学和科研工作。
项目一测试1.MCS-51单片机的CPU主要的组成部分为_______ 。
A:运算器、译码器B:运算器、控制器C:加法器、寄存器D:运算器、加法器答案:B2.MCS-51单片机若晶振频率为 =12MHz,则一个机器周期等于 ______µS。
A:1B:1/12C:2D:1/2答案:A3.MCS-51单片机的VSS(20)引脚是_______引脚。
A:接地B:访问片外存贮器C:备用电源D:主电源+5V答案:A4.MCS-51单片机中,输入/输出引脚中用于专门的第二功能的引脚是_______A:P3B:P0C:P1D:P2答案:A5.单片机就是指集成在一个芯片上的微型计算机。
A:错B:对答案:B项目二测试1.单片机并行I/O口线P1.0和P1.1连接了两个开关,此时它是什么接口功能?A:输出接口B:输入接口答案:B2.C语言对嵌套if语句的规定是:else语句总是与()配对。
A:其之前最近的且尚未配对的ifB:其之前最近的ifC:第一个ifD:缩进位置相同的if答案:A3.以下哪些设备是输出设备?A:显示器B:LEDC:扫描仪D:打印机答案:ABD4.以下哪些设备是外部输入设备?A:LEDB:键盘C:鼠标D:开关答案:BCD5.I/O接口是下面哪两个部件之间的交换信息的媒介和桥梁。
A:CPUB:最小系统C:存储器D:I/O设备答案:AD项目三测试1.关于中断优先级,下面说法不正确的是哪一个?A:自然优先级中INT0优先级最高,任何时候它都可以中断其他4个中断源正在执行的服务B:高优先级不能被低优先级中断C:低优先级可被高优先级中断D:任何一种中断一旦得到响应,不会再被它的同级中断源所中断答案:A2.当T1在下列哪种情况下, T1中断请求标志位TF1自动置1,向CPU申请中断。
A:启动时B:设置工作方式时C:计数溢出D:赋初值时答案:C3.编写定时器T1的中断服务程序,按如下编写: void timer1() interrupt n 其中n应为哪一个?A:2B:3C:4答案:B4.MCS-51系列单片机CPU开总中断语句是下面哪一个?A:EA=1;B:EX0=1;C:EA=0;D:ES=1;答案:A5.单片机中断系统有几个中断优先级别?A:2B:1C:4D:5答案:A项目四测试1.定时器的工作方式1是16位计数器,THx和TLx都参与计数过程。
PCF8591中文手册讲义一、PCF8591概述1. 内置一个模拟电压比较器;2. 提供4个模拟输入通道;3. 具有1个模拟输出通道;4. 适用于I2C总线通信;5. 工作电压范围宽,可达2.5V至6V。
二、PCF8591内部结构及功能1. 内部结构(1)模拟输入多路选择器:可以选择4个模拟输入通道之一;(2)A/D转换器:将模拟信号转换为数字信号;(3)D/A转换器:将数字信号转换为模拟信号;(4)模拟电压比较器:对输入的模拟电压进行比较;(5)I2C总线接口:实现与外部设备的通信。
2. 功能介绍(1)模拟输入多路选择器:通过I2C总线接口发送控制字,可以选择4个模拟输入通道之一;(2)A/D转换器:将选定的模拟输入信号转换为8位数字信号;(3)D/A转换器:将8位数字信号转换为模拟信号,输出至模拟输出通道;(4)模拟电压比较器:对输入的模拟电压进行比较,可应用于阈值检测等场景;(5)I2C总线接口:实现与单片机、微处理器等设备的通信,便于数据传输和控制。
三、PCF8591应用电路及编程方法1. 应用电路(1)电源电路:确保电源稳定,满足PCF8591的工作电压范围;(2)模拟输入电路:根据实际需求选择合适的传感器或信号源,并进行滤波、放大等处理;(3)模拟输出电路:可根据实际应用场景,对输出信号进行放大、滤波等处理;(4)I2C总线接口电路:连接单片机或其他设备的I2C接口,实现数据传输和控制。
2. 编程方法(1)初始化I2C总线接口:设置I2C总线的时钟频率、设备地址等参数;(2)发送控制字:选择模拟输入通道、启动A/D转换等;(3)读取A/D转换结果:通过I2C总线读取转换后的数字信号;(4)写入D/A转换数据:通过I2C总线发送8位数字信号,实现模拟信号输出;(5)模拟电压比较器应用:设置比较阈值,实现阈值检测等功能。
四、PCF8591编程实例及注意事项1. 编程实例include <Wire.h> // 引入I2C库define PCF8591_ADDR 0x48 // 设置PCF8591的I2C地址void setup() {Wire.begin(); // 初始化I2C总线}void loop() {// 读取模拟输入通道0的值Wire.beginTransmission(PCF8591_ADDR);Wire.write(0x04); // 控制字:选择通道0,启动A/D转换 Wire.endTransmission();Wire.requestFrom(PCF8591_ADDR, 2); // 请求2个字节的数据if (Wire.available() >= 2) {te high = Wire.read(); // 读取高8位te low = Wire.read(); // 读取低8位int value = (high << 8) | low; // 合并高低8位// value即为模拟输入通道0的数字值}// 通过模拟输出通道输出固定电压值(例如1.25V)Wire.beginTransmission(PCF8591_ADDR);Wire.write(0x40); // 控制字:选择D/A转换Wire.write(outputValue); // 写入D/A转换数据Wire.endTransmission();}2. 注意事项(1)确保I2C总线的电源和地线连接正确,避免信号干扰;(2)在读取A/D转换结果时,注意数据的字节顺序,避免数据解析错误;(3)模拟输入信号的幅值应在PCF8591的输入范围内,以免损坏芯片;(4)模拟输出通道的负载应适当,避免影响输出电压的精度;(5)在使用模拟电压比较器时,注意设置合适的比较阈值,以提高检测准确性。
HC6800初学者手册——————提高篇PCF8591的使用一、基础知识(见初学者手册基本实验)二、PCF8591配套课件二、实例分析1、PCF8591作为DA使用/****************************************************************************** ***********名称:HC6800基于PCF8591DA输出编写:FuQuanJun修改:无内容:使用DA输入,数码管显示输出的数字量,LED显示模拟量的大小说明:P0口作为数码管的输出口,通过38译码器实现数码管动态显示******************************************************************************* ***********/#include<reg52.h>//52单片机头文件#include<intrins.h>//该头文件定义了_nop_()方便下面函数调用#define uchar unsigned char#define uint unsigned int#define_Nop()_nop_()//定义空指令,不执行任何动作,延迟一个周期的时间如果使用12MHZ的晶振则延迟1us,由上面的头文件intrins申明/********************************************************************** *******************定义PCF8591的地址*********************************************************************** *******************/#define AddWr0x90//写数据地址#define AddRd0x91//读数据地址/********************************************************************** *******************定义I2C总线的数据端口和命令端口*********************************************************************** *******************/sbit SDA=P2^1;sbit SCL=P2^0;bit ack;//定义确认信号uchar dat=110;//数字量转为模拟量,参数取值范围为0~255(要测试DA每次改这个数值)转换后的电压值等于dat*(5/256)Vuint num=0;//显示相关,自己看程序吧uint ge,shi,bai,qian;//这个就不用说了吧,数码管显示位/********************************************************************** *******************显示相关*********************************************************************** *******************/sbit LS138A=P2^2;//定义了三八译码器的三个输入端口sbit LS138B=P2^3;//三八译码器没有学懂的同学请翻看HC6800初学者手册sbit LS138C=P2^4;uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//数码管显示的数值0~9/********************************************************************** *******************函数的申明*********************************************************************** *******************/这里采用的是函数申明(具体函数定义在后面)void start_i2c();//启动i2c总线void stop_i2c();//结束总线void sendbyte(uchar c);//发送数据传递函数void delayms(uint ms);//延迟函数void display(uint num);//显示函数bit DAC(unsigned char dat);//输入数字量转换为模拟量void time0_init();//定时器初始化void main()//主函数{time0_init();//定时器初始化,定时输出DA的值,这里只是为了方便后面学员自行开发函数信号发生器而设计的,想想为什么DA输出的时候需要用定时器,为什么普通输出就不行呢?这里留一个问题给各位讨论,呵呵!while(1)//死循环{num=dat*195/100;//num在这里出现了,计算转换的数值,其实这里可以使用宏定义去定义num的,#define num(dat*195/100),当然dat也要在num之前宏定义咯#define dat110代替前面定义的全局变量display(num);//数码管上显示num具体显示函数看后面}}void delayms(uint ms)//延迟函数,可以采用别的延迟,看初学者手册第一章的实验{uint x,y;for(x=ms;x>0;x--)for(y=110;y>0;y--);}void display(uint num)//显示函数,这里就不重复解释了,不懂得学员看HC6800初学者手册的38译码器数码管显示部分{ge=num%10;//分别取个位,十位,百位,千位的数值shi=num/10%10;bai=num/100%10;qian=num/1000%10;P0=table[ge];LS138C=1;LS138B=1;LS138A=1;delayms(1);P0=table[shi];LS138C=1;LS138B=1;LS138A=0;delayms(1);P0=table[bai];LS138C=1;LS138B=0;LS138A=1;delayms(1);P0=table[qian];LS138C=1;LS138B=0;LS138A=0;delayms(1);}/********************************************************************** *******************I2C总线通信协议********************通信协议部分看前面的I2C总线相关部分呵呵其实看不懂的学员去下一下I2C总线的协议,编写I2c总协议只需要根据他的时序来写就行了**********************************************************************/ void start_i2c()//启动i2c总线{SDA=1;//发送起始条件的数据信号_Nop();SCL=1;_Nop();//起始条件建立时间大于4.7us,延时_Nop();_Nop();_Nop();_Nop();SDA=0;//发送起始信号_Nop();//起始条件锁定时间大于4μ_Nop();_Nop();_Nop();_Nop();SCL=0;//钳住I2C总线,准备发送或接收数据_Nop();_Nop();}void stop_i2c()//结束总线{SDA=0;//发送结束条件的数据信号_Nop();//发送结束条件的时钟信号SCL=1;//结束条件建立时间大于4μ_Nop();_Nop();_Nop();_Nop();_Nop();SDA=1;//发送I2C总线结束信号_Nop();_Nop();_Nop();_Nop();}void sendbyte(uchar c)//发送数据传递函数,注意这里发送的是一个字节的数据8bit {unsigned char BitCnt;for(BitCnt=0;BitCnt<8;BitCnt++)//要传送的数据长度为8位{if((c<<BitCnt)&0x80)SDA=1;//判断发送位elseSDA=0;_Nop();SCL=1;//置时钟线为高,通知被控器开始接收数据位_Nop();_Nop();//保证时钟高电平周期大于4μ_Nop();_Nop();_Nop();SCL=0;}_Nop();_Nop();SDA=1;//8位发送完后释放数据线,准备接收应答位_Nop();_Nop();SCL=1;_Nop();_Nop();_Nop();if(SDA==1)ack=0;elseack=1;//判断是否接收到应答信号SCL=0;_Nop();_Nop();}/********************************************************************** *******************定时器定义*********************************************************************** *******************/void time0_init()//定时器初始化{TMOD|=0x01;//使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响TH0=(65536-2000)/256;//重新赋值2msTL0=(65536-2000)%256;EA=1;//总中断打开ET0=1;//定时器中断打开TR0=1;//定时器开关打开}void time0_irq(void)interrupt1//定时器中断函数{TH0=(65536-2000)/256;//重新赋值2msTL0=(65536-2000)%256;DAC(dat);}/**********************************************************************写入DA转换数值,这部分可谓是这个程序的中心,程序的主体就是这个函数,什么I2C总线的通信协议都不是关键的地方,我们只要将它当做一个黑盒来处理就行了,I2C总线的通信协议提供给我们两个接口函数,一个是发送数据的函数sendbyte();还有一个是接受数据的函数将在AD上面介绍呵呵~~~留个小悬念下面我们来分析一下这个函数(重点!!!!!)输入参数:dat表示需要转换的DA数值,范围是0-255**********************************************************************/ bit DAC(unsigned char dat)//输入数字量转换为模拟量{start_i2c();//启动总线,大家翻看数据手册最后面I2C部分,每次发送数据的时候I2C总线都应该初始化sendbyte(AddWr);//PCF8591地址,I2C总线上面可以挂接许多的IC期间,他们共用SDL和SCL数据总线和控制总线,挂在这么多的芯片就像在晾衣架上挂衣服一样,他们既然共用同一根数据总线和控制总线,单片机如何区分他们呢?地址!没错,通过所要操作IC器件的地址来操作IC,每块具有I2C模块的芯片都具有一定位数的可编程位,PCF8591就有三个可编程位,所以可以挂接最多8个芯片,如何使用这八个芯片我们可以依葫芦画瓢,只需要幅值这个DAC()函数对吧,将每次启动I2C 后发送不同的地址就行了,就能够操作不同的IC芯片if(ack==0)return(0);//看I2C总线通信协议,只想用PCF8591的学员这里不深究sendbyte(0x40);//PCF8591控制字,我们知道PCF8591具有很多的功能,什么时候选用DA的功能,什么时候选用AD的功能,什么时候使用单通道输入,什么时候选用差分输入,什么时候选择哪个通道输入都在这个控制字里面去设置对于参加电子设计大赛的大学生朋友我还要提一下差分输入有什么作用?这个也留下一个问题给大家讨论if(ack==0)return(0);sendbyte(dat);//发送数据,将我们输出的电压写上来if(ack==0)return(0);stop_i2c();//关闭I2C总线,自己不用数据线不要老占着,要有公德心return(1);}2、PCF8591作为单路AD使用因为篇幅的关系和程序本身的特点我们下面只介绍改程序和DA程序的异同的部分,相同的部分这里不做相同的解释,各位朋友可以通过与DA的程序比较来理解程序如下:/********************************************************************** *******************名称:HC6800基于PCF8591单路AD输入编写:FuQuanJun修改:无内容:使用PCF8591单路输入,数码管显示输入模拟量得大小说明:P0口作为液晶1602的输出口,本程序不需要跳线*********************************************************************** *******************/#include<reg52.h>//52单片机头文件#include<intrins.h>//该头文件定义了_nop_()方便下面函数调用#define uchar unsigned char#define uint unsigned int#define_Nop()_nop_()//定义空指令,不执行任何动作,延迟一个周期的时间如果使用12MHZ的晶振则延迟1us/********************************************************************** *******************定义PCF8591的地址*********************************************************************** *******************/#define AddWr0x90//写数据地址#define AddRd0x91//读数据地址/********************************************************************** *******************定义I2C总线的数据端口和命令端口*********************************************************************** *******************/sbit SDA=P2^1;sbit SCL=P2^0;bit ack;uchar dat=110;//数字量转为模拟量,参数取值范围为0~255uint num=0;uint ge,shi,bai,qian;/********************************************************************** *******************显示相关******************************************************************************************/sbit LS138A=P2^2;sbit LS138B=P2^3;sbit LS138C=P2^4;uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};/********************************************************************** *******************函数的申明*********************************************************************** *******************/void start_i2c();//启动i2c总线void stop_i2c();//结束总线void sendbyte(uchar c);//发送数据传递函数void delayms(uint ms);//延迟函数void display(uint num);//显示函数uchar ADC(void);//读AD转换模拟值的数字量void time0_init();//定时器初始化void main(){time0_init();while(1){}}void delayms(uint ms){uint x,y;for(x=ms;x>0;x--)for(y=110;y>0;y--);}void display(uint num){ge=num%10;//分别取个位,十位,百位,千位的数值shi=num/10%10;bai=num/100%10;qian=num/1000%10;P0=table[ge];LS138C=0;LS138B=0;LS138A=0;delayms(1);P0=table[shi];LS138C=0;LS138B=0;LS138A=1;delayms(1);P0=table[bai];LS138C=0;LS138B=1;LS138A=0;delayms(1);P0=table[qian];LS138C=0;LS138B=1;LS138A=1;delayms(1);}/********************************************************************** *******************I2C总线通信协议*********************************************************************** *******************/void start_i2c()//启动i2c总线{SDA=1;//发送起始条件的数据信号_Nop();SCL=1;_Nop();//起始条件建立时间大于4.7us,延时_Nop();_Nop();_Nop();_Nop();SDA=0;//发送起始信号_Nop();//起始条件锁定时间大于4μ_Nop();_Nop();_Nop();_Nop();SCL=0;//钳住I2C总线,准备发送或接收数据_Nop();_Nop();}void stop_i2c()//结束总线{SDA=0;//发送结束条件的数据信号_Nop();//发送结束条件的时钟信号SCL=1;//结束条件建立时间大于4μ_Nop();_Nop();_Nop();_Nop();_Nop();SDA=1;//发送I2C总线结束信号_Nop();_Nop();_Nop();_Nop();}void sendbyte(uchar c)//发送数据传递函数,注意这里发送的是一个字节的数据8bit {unsigned char BitCnt;for(BitCnt=0;BitCnt<8;BitCnt++)//要传送的数据长度为8位{if((c<<BitCnt)&0x80)SDA=1;//判断发送位elseSDA=0;_Nop();SCL=1;//置时钟线为高,通知被控器开始接收数据位_Nop();_Nop();//保证时钟高电平周期大于4μ_Nop();_Nop();_Nop();SCL=0;}_Nop();_Nop();SDA=1;//8位发送完后释放数据线,准备接收应答位_Nop();_Nop();SCL=1;_Nop();_Nop();_Nop();if(SDA==1)ack=0;elseack=1;//判断是否接收到应答信号SCL=0;_Nop();_Nop();}uchar rcvbyte()//接受数据传递函数,注意这里发送的是一个字节的数据8bit {uchar retc;uchar BitCnt;retc=0;SDA=1;//置数据线为输入方式for(BitCnt=0;BitCnt<8;BitCnt++){_Nop();SCL=0;//置时钟线为低,准备接收数据位_Nop();_Nop();//时钟低电平周期大于4.7us_Nop();_Nop();_Nop();SCL=1;//置时钟线为高使数据线上数据有效_Nop();_Nop();retc=retc<<1;if(SDA==1)retc=retc+1;//读数据位,接收的数据位放入retc中_Nop();_Nop();}SCL=0;_Nop();_Nop();return(retc);}void noack_i2c(void)//非应答子函数{SDA=1;_Nop();_Nop();_Nop();_Nop();_Nop();//时钟低电平周期大于4μ_Nop();_Nop();_Nop();SCL=0;//清时钟线,钳住I2C总线以便继续接收_Nop();_Nop();}/********************************************************************** *******************定时器定义*********************************************************************** *******************/void time0_init()//定时器初始化{TMOD|=0x01;//使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响TH0=(65536-2000)/256;//重新赋值2msTL0=(65536-2000)%256;EA=1;//总中断打开ET0=1;//定时器中断打开TR0=1;//定时器开关打开}void time0_irq(void)interrupt1//定时器中断函数{TH0=(65536-2000)/256;//重新赋值2msTL0=(65536-2000)%256;num=ADC();display(num);}uchar ADC()//读AD转换模拟值的数字量{uchar Val;start_i2c();//启动总线sendbyte(AddWr);//发送器件地址if(ack==0)return(0);sendbyte(0x40);//发送控制信息if(ack==0)start_i2c();sendbyte(AddRd);if(ack==0)return(0);Val=rcvbyte();noack_i2c();//发送非应位stop_i2c();//结束总线return(Val);}3、PCF8591作为多路AD使用程序如下:/********************************************************************** *******************名称:HC6800基于PCF8591单路AD输入编写:FuQuanJun修改:无内容:使用PCF8591做为多路AD输入,液晶屏分别显示多路AD输入的值说明:*********************************************************************** *******************/#include<reg52.h>//52单片机头文件#include<intrins.h>//该头文件定义了_nop_()方便下面函数调用#define uchar unsigned char#define uint unsigned int#define_Nop()_nop_()//定义空指令,不执行任何动作,延迟一个周期的时间如果使用12MHZ的晶振则延迟1us/********************************************************************** *******************定义PCF8591的地址*********************************************************************** *******************/#define AddWr0x90//写数据地址#define AddRd0x91//读数据地址/********************************************************************** *******************定义I2C总线的数据端口和命令端口*********************************************************************** *******************/sbit SDA=P2^1;//数据总线sbit SCL=P2^0;//控制总线bit ack;//应答位uchar dat=110;//数字量转为模拟量,参数取值范围为0~255uint num1=0,num2=0,num3=0,num4=0;//定义四个变量,分别表示CH1,CH2,CH3,CH4转换得到的模拟数值uint ge,shi,bai,qian;//个位十位百位千位/********************************************************************** *******************显示相关*********************************************************************** *******************/sbit rs=P2^6;//1602读信号位sbit rw=P2^5;//1602写信号位sbit eg=P2^7;//1602使能信号位uchar code table[]={'0','1','2','3','4','5','6','7','8','9'};//1602显示数字/********************************************************************** *******************函数的申明*********************************************************************** *******************/void start_i2c();//启动i2c总线void stop_i2c();//结束总线void sendbyte(uchar c);//发送数据传递函数void delayms(uint ms);//延迟函数void display();//显示函数uchar ADC(uchar ch);//读AD转换模拟值的数字量void time0_init();//定时器初始化void init_1602();//1602液晶初始化程序void writesj(unsigned char sj);//1602液晶写数据void writezl(unsigned char zl);//1602液晶写命令void main()//主函数{init_1602();//1602初始化显示函数time0_init();//定时器初始化while(1){//死循环}}void delayms(uint ms)//延迟函数,延迟ms{for(x=ms;x>0;x--)for(y=110;y>0;y--);}void display()//显示函数{writezl(0x80);//写命令,在第一行一个位写Cwritesj('C');writezl(0x80+0x01);//写命令,在第一行第二位写hwritesj('h');writezl(0x80+0x02);writesj('1');writezl(0x80+0x03);writesj(':');writezl(0x80+0x04);writesj(table[num1/100%10]);writezl(0x80+0x05);writesj(table[num1/10%10]);writezl(0x80+0x06);writesj(table[num1%10]);writezl(0x80+0x07);writesj('C');writezl(0x80+0x08);writesj('h');writezl(0x80+0x09);writesj('2');writezl(0x80+0x0a);writesj(':');writezl(0x80+0x0b);writesj(table[num2/100%10]);writezl(0x80+0x0c);writesj(table[num2/10%10]);writezl(0x80+0x0d);writesj(table[num2%10]);writezl(0x02);//清除指针,但是不清楚显示内容;显示回车writezl(0x80+0x40);//跳转到下行的第一位开始置显示;writesj('C');writezl(0x80+0x41);writesj('h');writezl(0x80+0x42);writesj('3');writezl(0x80+0x43);writezl(0x80+0x44);writesj(table[num3/100%10]);writezl(0x80+0x45);writesj(table[num3/10%10]);writezl(0x80+0x46);writesj(table[num3%10]);writezl(0x80+0x47);//跳转到下行的第一位开始置显示;writesj('C');writezl(0x80+0x48);writesj('h');writezl(0x80+0x49);writesj('4');writezl(0x80+0x4a);writesj(':');writezl(0x80+0x4b);writesj(table[num4/100%10]);writezl(0x80+0x4c);writesj(table[num4/10%10]);writezl(0x80+0x4d);writesj(table[num4%10]);}/********************************************************************** *******************I2C总线通信协议*********************************************************************** *******************/void start_i2c()//启动i2c总线{SDA=1;//发送起始条件的数据信号_Nop();SCL=1;_Nop();//起始条件建立时间大于4.7us,延时_Nop();_Nop();_Nop();_Nop();SDA=0;//发送起始信号_Nop();//起始条件锁定时间大于4μ_Nop();_Nop();_Nop();_Nop();SCL=0;//钳住I2C总线,准备发送或接收数据_Nop();_Nop();}void stop_i2c()//结束总线{SDA=0;//发送结束条件的数据信号_Nop();//发送结束条件的时钟信号SCL=1;//结束条件建立时间大于4μ_Nop();_Nop();_Nop();_Nop();_Nop();SDA=1;//发送I2C总线结束信号_Nop();_Nop();_Nop();_Nop();}void sendbyte(uchar c)//发送数据传递函数,注意这里发送的是一个字节的数据8bit {unsigned char BitCnt;for(BitCnt=0;BitCnt<8;BitCnt++)//要传送的数据长度为8位{if((c<<BitCnt)&0x80)SDA=1;//判断发送位elseSDA=0;_Nop();SCL=1;//置时钟线为高,通知被控器开始接收数据位_Nop();_Nop();//保证时钟高电平周期大于4μ_Nop();_Nop();_Nop();SCL=0;}_Nop();_Nop();SDA=1;//8位发送完后释放数据线,准备接收应答位_Nop();_Nop();SCL=1;_Nop();_Nop();_Nop();if(SDA==1)ack=0;elseack=1;//判断是否接收到应答信号SCL=0;_Nop();_Nop();}uchar rcvbyte()//接受数据传递函数,注意这里发送的是一个字节的数据8bit {uchar retc;uchar BitCnt;retc=0;SDA=1;//置数据线为输入方式for(BitCnt=0;BitCnt<8;BitCnt++){_Nop();SCL=0;//置时钟线为低,准备接收数据位_Nop();_Nop();//时钟低电平周期大于4.7us_Nop();_Nop();_Nop();SCL=1;//置时钟线为高使数据线上数据有效_Nop();_Nop();retc=retc<<1;if(SDA==1)retc=retc+1;//读数据位,接收的数据位放入retc中_Nop();_Nop();}SCL=0;_Nop();_Nop();return(retc);}void noack_i2c(void)//非应答子函数{SDA=1;_Nop();_Nop();_Nop();SCL=1;_Nop();_Nop();//时钟低电平周期大于4μ_Nop();_Nop();_Nop();SCL=0;//清时钟线,钳住I2C总线以便继续接收_Nop();_Nop();}/********************************************************************** *******************定时器定义*********************************************************************** *******************/void time0_init()//定时器初始化{TMOD|=0x01;//使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响TH0=(65536-2000)/256;//重新赋值2msTL0=(65536-2000)%256;EA=1;//总中断打开ET0=1;//定时器中断打开TR0=1;//定时器开关打开}void time0_irq(void)interrupt1//定时器中断函数{TH0=(65536-2000)/256;//重新赋值2msTL0=(65536-2000)%256;num1=ADC(0);num2=ADC(1);num3=ADC(2);num4=ADC(3);display();}uchar ADC(uchar ch)//读AD转换模拟值的数字量{uchar Val;start_i2c();//启动总线sendbyte(AddWr);//发送器件地址if(ack==0)return(0);sendbyte(ch);//发送器件子地址if(ack==0)return(0);start_i2c();sendbyte(AddRd);if(ack==0)return(0);Val=rcvbyte();noack_i2c();//发送非应位stop_i2c();//结束总线return(Val);}/********************************************************************** *******************1602液晶显示函数*********************************************************************** *******************/void writezl(unsigned char zl){rs=0;rw=0;//满足写指令的条件;P0=zl;delayms(5);eg=1;delayms(5);eg=0;}void writesj(unsigned char sj){rs=1;rw=0;//满足写数据的条件;P0=sj;delayms(5);eg=1;delayms(5);eg=0;}void init_1602(){eg=0;writezl(0x38);//显示模式设置;delayms(1);writezl(0x0c);//开显示,不开光标,光标不闪烁;delayms(1);writezl(0x06);//写数据时,每写一个数据,指针后移动一位,但是整屏不动;delayms(1);writezl(0x80+0x00);//在显示器的第一行第一位开始写数据;delayms(1);}程序基本上大同小异,其中液晶显示采用简易写法,不提倡三、作业利用PCF8591设计一个函数信号发生器,通过按键可以选择三角波,正弦波,矩形波,锯齿波四个波形的输出加分功能:1、可以通过按键调节三角波,正弦波,矩形波,锯齿波的信号频率2、可以通过按键调节信号的输出幅值(0~5V)步进精度为0.1V3、可以通过按键调节矩形波的占空比做出来的同学可以联系我:85891240(非诚勿扰)只答疑推出的课程部分(答疑时请提交晶龙电子电子订单号,谢谢合作,非24小时在线,呵呵~~~每天都上线,最好发邮件因为太忙了,留言不一定都能及时回复,有问题的话还是群里大家讨论来得效果更好,请利用我们机器猫老板给大家提供的交流平台)感谢:普中科技有限公司,上海晶龙电子有限公司该课程配套视频有空再发上来,敬请关注~~~~。
重庆科技学院学生实习(实训)总结报告学院:电气与信息工程学院专业班级: XXX学生姓名: XXX 学号: XXX实习(实训)地点: 逸夫科技大楼I512报告题目:单片机简易信号发生器设计报告日期: 2014 年 3 月 10 日指导教师评语:_________________________________________成绩(五级记分制):指导教师(签字):目录一、实验目的和意义 (1)1.1设计目的和意义 (1)1.2任务 (1)二、方案设计 (1)2.1系统分析 (1)2.2器件选择 (2)2.2.1 微处理器 (2)2.2.2 显示器 (3)2.2.3 按键 (3)三、系统硬件设计 (3)3.1 单片机数据处理系统 (3)3.2最小的系统设计 (4)3.3 按键控制电路 (5)3.4 数码管显示电路 (5)3.5 LED报警灯电路 (6)3.6 IICEEROM模块 (6)3.7 实时时钟电路(扩展功能) (6)四、系统软件设计 (7)4.1 操作功能设计 (7)4.2程序编制思想 (7)4.3 主程序设计 (8)4.3.1系统工作流程图 (9)4.3.2独立按键流程图 (10)4.3.3中断服务程序流程图 (11)五、程序调试 (11)5.1.1 硬件调试: (11)5.1.2软件调试: (12)5.1.3 波形与显示的调试: (12)六、技术小结 (12)七、心得体会 (13)八、参考文献: (13)附录1 系统硬件电路图 (14)附录2 程序清单 (15)关于单片机简易信号发生器设计的实习(实训)报告一、实验目的和意义1.1设计目的和意义波形发生器亦称函数发生器,作为实验用信号源,是现今各种电子电路实验设计应用中必不可少的仪器设备之一。
目前,市场上常见的波形发生器多为纯硬件的搭接而成,且波形种类有限,多为锯齿、正弦、方波、三角等波形。
本系统利用单片机AT89S52采用程序设计方法产生正弦波、方波、三角波三种波形,再通过D/A转换器DAC0832将数字信号转换成模拟信号,滤波放大,最终由示波器显示出来,能产生1Hz—3kHz的波形并且可调。
红外遥控智能小车设计袁铭【摘要】设计了基于红外无线控制的智能小车,本文主要针对智能小车的系统结构和原理进行探讨和研究.重点研究了以80C51单片机为控制芯片,运用红外控制小车的运动方向,可以自动躲避障碍物.同时还研究了光电传感器的使用方法,使得智能小车具有自动头灯的功能,增加了液晶显示功能,可以显示环境和运动状态参数.【期刊名称】《电子世界》【年(卷),期】2018(000)003【总页数】2页(P124-125)【关键词】红外;单片机;液晶显示【作者】袁铭【作者单位】苏州工业园区工业技术学校【正文语种】中文1 引言物质生活水平的提高,一些比较有危险系数的工作人们越来越不想参与,随着智能设备的发展,这些设备完全可以代替人类去完成一些危险的或者难以到达的位置的工作任务。
当然,设备必须具有一定的智能性,能够独立的判断所处环境的所有有用信息,并加以判断,予以归类,捕捉实时性的信息,然后进行实时反馈,让我们可以更加客观地采取判断,不至于因环境的变化或者不适应等各种外界因素影响我们的主观意识。
这类智能设备很大程度解放了劳动力,并且提高了安全生产方面的安全系数。
智能小车就属于这类智能设备,人们可以通过无线遥控控制小车完成各种前进转弯等动作,同时小车具有环境感知能力,自行作出判断进行下一步动作,完成实时环境数据采集。
目前市面上有各种技术来控制小车,而本小车采用红外线遥控控制,结构简单,成本较低。
本文重点研究了基于单片机控制,红外遥控的小车系统及其硬件系统的设计和软件流程的设计。
2 系统整体结构方案本系统是通过红外线进行远距离控制,当小车的红外接收模块接收到远端发射的红外控制信号后进行信息处理解析,驱动直流电机完成前进、后退、加速和转弯等运行动作;小车安装液晶显示模块,可以显示小车所处的环境、时间和运行状态等参数;同时,当小车具有红外避障模块,当遇到前方的障碍物时可以自动倒退,躲避障碍物。
本系统采用80C51单片机作为小车的控制核心,电路由红外接收模块,红外避障模块,电机驱动模块,液晶显示模块,时钟模块等几部分构成,系统整体框图如图1所示。