为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

电能计量表设计

2017-11-19 50页 doc 352KB 69阅读

用户头像

is_841159

暂无简介

举报
电能计量表设计电能计量表设计 本科毕业论文(设计) 题 目:基于CS5460A的单相电能计量表的设计 学 院: 自动化工程学院 专 业: 电子信息工程 姓 名: 指导教师: 2012年 5 月 28 日 摘 要 本论文设计了一种可用于家庭用户的数字电能表计量系统,利用CS5460A电能芯片 采集电压、电流信号,再通过单片机对电能芯片的操作,读取用户所用的电能数据,并 能够进行远程抄表。 本次设计中,采用了STM32F03R6单片机作为系统的控制核心,具有超快的运行速 度、高集成度、工作可靠等优点。电能计量芯片CS5460A的应...
电能计量表设计
电能计量表 本科毕业(设计) 目:基于CS5460A的单相电能计量表的设计 学 院: 自动化工程学院 专 业: 电子信息工程 姓 名: 指导教师: 2012年 5 月 28 日 摘 要 本论文设计了一种可用于家庭用户的数字电能表计量系统,利用CS5460A电能芯片 采集电压、电流信号,再通过单片机对电能芯片的操作,读取用户所用的电能数据,并 能够进行远程抄表。 本次设计中,采用了STM32F03R6单片机作为系统的控制核心,具有超快的运行速 度、高集成度、工作可靠等优点。电能计量芯片CS5460A的应用大大减轻了微处理器的 负荷,与传统电度表相比,具有高灵敏度、准确度、防止窃电等特点,使电能表的整体 性能和可靠性大大增强。 本次设计是基于CS5460A的单相电能表是一种比较理想的电量计量仪表,可以实现 集中抄表,用电监测和信息统计等方面的计算科学管理,从而提高用电管理的工作效率 和管理层次,缓解用电矛盾,带来极大的经济效益和社会效益。 关键字 CS5460A 单片机 远程抄表 电能表 ABSTRACT This article designed a new kind of intelligent electric meter based on CS5460A chip. It elaborated its principle of work and the software and hardware design method. Its main functions includes: the electrical energy measurement, the time sharing duplicate expense, long-distance automatically copies the table, and the RS485 bus copies the table and so on. The system use MCU STM32F103R6 as the control core of the system which is low power consumption and high reliable work. The use of electricity power CS5460A chip reduces Microprocessor load and power greatly,compared with the tradition of watt-hour meter with high sensitivity and accuracy, to prevent stealing and so on, greatly enhanced theoverall performance and reliability of the energy meter. The design of intelligent electric meter is an ideal power measurement system. It can achieve concentration meter, power detection and information statistics, etc. The advantages improve the working efficiency and management level. So the intelligent electric meter brings enormous economic benefit and social benefit. KEY WORDS CS5460A SCM remote meter electric meter 目 录 前 言 ......................................................... 1 第1章 电能计量表的发展及意义 .................................. 2 1.1 电能表行业发展的状况 .............................................. 2 1.2 研究意义 .......................................................... 3 第2章 本课题的主要内容与比较 .............................. 4 2.1 课题的主要内容 .................................................... 4 2.1.1 电能计量表 ..................................................... 4 2.1.2 电能计量芯片 ................................................... 4 2.1.3 电能的测量原理及方法 ........................................... 5 2.2 离散采样电量测量的原理 ............................................ 5 2.3 CORTEX-M3与STM32 ................................................. 6 第3章 系统结构及原理 .......................................... 8 3.1 概述 .............................................................. 8 3.2 电能计量单元介绍 .................................................. 8 3.2.1 电能芯片的简介 ................................................. 8 3.2.2 电能芯片的工作原理 ............................................ 10 3.3 STM32F103R6单片机 ................................................ 13 3.2.1 单片机选取 .................................................... 13 3.3.2 单片机的工作原理 .............................................. 14 3.4 时钟电路 ......................................................... 15 3.4.1 芯片介绍 ...................................................... 15 3.4.2 芯片工作原理 .................................................. 16 3.5 电源电路 ......................................................... 17 3.5.1 数字电源 ...................................................... 17 3.5.2 模拟电源 ...................................................... 18 3.6 复位电路 ......................................................... 18 3.6.1 芯片介绍 ...................................................... 18 3.6.2 芯片工作原理 .................................................. 19 3.7 键盘输入电路 ..................................................... 20 3.7.1 电路工作原理 .................................................. 20 3.8 显示电路 ......................................................... 21 3.8.1 显示电路的实现原理 ............................................ 21 3.9 串口通信电路 ..................................................... 21 3.9.1 串口通信芯片介绍 .............................................. 21 芯片工作原理 .................................................. 22 3.9.2 第4章 软件部分 ............................................... 24 4.1 软件系统的介绍 ................................................... 24 4.2 各功能流程图 ..................................................... 25 结束语 ........................................................ 29 致 谢 ........................................................ 30 参考文献 ...................................................... 31 附 录 ........................................................ 31 附录1:CS5460A数据的读写 ............................................. 32 附录2:按键子程序 ..................................................... 35 附录3:显示子程序 ..................................................... 36 附录4:存储子程序 ..................................................... 37 附录5:通信子程序 ..................................................... 43 前 言 随着社会的不断进步和人们生活水平的不断提高,人均每户的用电量也得到大幅度的增加,使得“一户一表制”这样的得到大面积的推广,同时针对电能计量表的需求和要求也得到进一步的增加。采用智能化和全面化的远程控表系统,全自动计算电量、计算费用、自动控制原理等方法可解决在人工抄表当中存在的诸多问题,比如:它可以减轻劳动人员的劳动强度,提高综合管理水平等。所以这里需设计一种超低消耗的单相电能计量表。对于电能计量表的设计已有很多研究和相关论文的发表,本设计的优势在于功耗低、速度快。 传统的电能计量表的功能单一,准确性也低,频率使用范围窄,这些缺点都不利于未来人的社会生活,本设计介绍的是一种基于CS5460A的单相电能计量表。CS5460A电能芯片,是CIRRUS LOGICAL公司推出的用于测电流,电压,功率等的芯片,其精度高,性能强且成本低。该芯片具有自动引脚模式的功能,不仅能使芯片独立工作,而且得电 2时芯片能自动的初始化,再由外部的电可擦可编程只读存储器 EPROM引导开始工作,并输出从中读取数据,再将信号输送给单片机。假如用于高容量或家庭,为了降低成本,还可以不用微控制器而独立工作。 本设计还采用STM32F103R6单片机,所以另一个亮点就是超低功耗。节能低耗也是未来生活的一个重要的要求。同时增加了STM的高性能的外设设备资源,FLASH、SRAM等闪存存储器,并接有非常丰富的串行通信接口。多达51快速I/O接口,I/O资源是非常丰富的,因此可以节省很多器件以及可以降低功耗。 由于电子式电能计量表具有数字通信接口的功能,使得电能的计量和用电的管理等新型的自动化监测系统都得到了大量使用,在远程抄表系统中如果采用RS485串行通信系统,能够极大的提高系统的可靠性和稳定性。 1 第1章 电能计量表的发展及意义 1.1 电能表行业发展的状况 电能表在世界上出现已经有一百多年的历史了,最早的电能表是1881年根据电解的原理研制而成的,虽然这种电能表体积巨大,重量也十分惊人,而且又无精度的保证。但是它仍然成为世界科技史上的一项重要发明而受到研究者的重视和赞扬,并很快地被运用到工业设计中来。随着科学技术的不断发展,1888年,随着交流电的发现和应用,电能表又遇到了新的挑战。经过科学家的努力研制,感应式电能表应运而生了。由于感应式电能表与其相比结构更简单、操作更安全、而且便宜耐用、又便于人员维修和批量生产产品等一系列的优点,所以发展进程非常快。 随着日新月异的高新技术变化,特别是和电子相关技术的迅猛发展,电能计量表的产业的结构已经发生了翻天覆地的变化。电子计量表的高精度、多功能、自动抄表等优点,在未来的几年时间内,将逐步代替原有的传统的机械式或复杂的电子计量表而成为新的发展主流。 目前,在我国的电能计量表中感应式电能计量表仍然占有相当大的市场,由于价格和使用环境等不同因素的限制,预计城市用户则会逐步推广电子式电能计量表,而农村用户还将继续使用感应式单相表。而峰谷分时电价和避峰电价政策的相继出台,使得家庭电能计量表市场需求得到将进一步扩大。 由于国内电子计量表市场趋于饱和电子计量表生产从高速增长期进入适度增长期,整个行业生产能力也过剩,行业内竞争变得更加的激烈,市场相对利润也会有所下降;同时,由于市场的开放伴随更多国外企业参与国内电子计量表市场竞争,导致我国电子计量表企业经营环境发生巨大变化。但由于国内电子计量表设备的质量普遍较高和价格也较低廉,因而具有相当大的产业优势。因此近年来我国的电子计量表等电子产品大量 [9]出口到阿拉伯、东南亚和非洲等国家和地区,并逐步的打开欧美市场。 电子计量表具有的数字通信接口,使得电能计量及用电管理自动化系统都得到大量利用和开发,实用性和可靠性都得到了很大提高。近年来由于电力供求缩紧,电子计量相关产业得到发展。即使未来电力保持充足,从节能减排的当前的价值观点出发,这种对于能够严格控制电量使用和发展节约能源的方法具有非常实际的意义。 面对社会的不断进步,全面提高电能计量表的生产模式,尤其是技术含量高的产品的综合市场竞争力,重点是突破现有的开发困境,使电能表从价格、数量等低技术含量的方式转变为高新技术的优势,这是当前电能计量表行业的总体发展趋势,而技术含量高的产品经济效益更高,收益也更好,这必然成为今后发展的重中之重。所以要想发展 2 电子式电能表,关健还是在技术上。 1.2 研究意义 随着我国电力市场的完善和发展,供电已成为一种纯粹的商业行为,经济稳步发展促使各行各业及家庭用电量的增多,电费已成为企业、家庭和社会都不可忽视的生活成本和支出。电能计量设备的精准与否,关系到人民和企业的利益关系,也关系到电力部门的诚信问题。同时,社会发展也对电能测量的现代化也增加更多的要求,比如人机通信、远程抄表等。电能计量表专用芯片CS5460A集成A/D转换、计算、滤波、系统校准 [10]等多种功能,能够帮助人们测量多种电能参数,而且设计中还简化了单相电能表的软件部分和硬件设计,不仅提高测量时的精确度,其性能也远远优于同类的其他单相计量芯片,采用STM32F103R6运行速度快和低功耗,符合国家节能减排的未来趋势。所以用CS5460A设计的单相电能计量表,不仅能够满足电力部门的多种需要,而且满足家庭的需要,所以拥有广阔的市场前景。 3 第2章 本课题的主要内容与方案比较 2.1 课题的主要内容 2.1.1 电能计量表 普通单相电能表由驱动元件、制动元件、转动元件、上下轴承、计度器、接线端子盒、底座和表壳等构成。 (1)驱动元件:包括电流驱动元件和电压驱动元件。 (2)制动元件: 由永久磁铁钳制而成,圆盘转动时会产生制动力矩,能够控制圆盘的转速,从而使圆盘的转数能够反映出被测的电能量值。 (3)转动元件:由竖转轴和转盘用铝合金压铸在一起组成。 (4)轴承:分为上轴承和下轴承。上轴承主要有导向的作用,下轴承不仅用来支撑转动元件,还用来减少转动时产生的摩擦力矩。 (5)积算机构:用来累积圆盘的转数,计算或累计电能值。 (6)调整装置:用于改变制动力矩和补偿力矩的数值,改变和满足人们对于准确度的要求。 2.1.2 电能计量芯片 电能计量芯片主要由电压互感器和电流互感器、计算机系统及计算机显示部分、信号输入电路和按键部分等组成。电能芯片主要完成对输入进来的信号进行A/D转换,然后再对其电量的数据进行处理。采用电能计量芯片的电能计量表,从构成上看,比数字化的采样方案的会更具有优越性,它可以节约能源和设备省略一些不必要的单元。本设计要求设计单相电能计量表,显示和控制功能较多,需要的单片机I/O接口也较多,所以必须以单片机为中心组件。目前社会上的电能专用芯片有很多不同的特点,例如,有低功耗(一般为几十毫瓦);高性能(具有性能优越的A/D转换器,使转换误差更小);高精度(测量误差大多小 0.3%)及高度集成等,这些都为科学家设计可靠性更高、功能多样化的单相电能计量表提供了比较有利条件。因此,我们采用基于电能计量芯片的电能计量表作为本设计的方案。目前,市场上较为常见的单相电能计量芯片有美国AD公司的AD7751和7755、德国CIRRUS LOGICAL公司的CS5460A。我们在这里选用了基于Σ-?调制 A/D 转换技术的CS546OA芯片。 CS5460A可以用来测量瞬时的电流与电压、电压和电流的有效值、瞬时功率等电能参数,测量结果会以24位有符号或无符号的2进制码存储在内部寄存器当中,所以可 4 以用CS5460A设计单相电能计量表。另外,CSA5460A还提供了电能计量脉冲输出端口和功率方向端口,可以让我们很方便地将它与单片机连接构成简单的电能表。CS5460A性能优于其它单相计量芯片。目前,供电部门对用电客户的统计参数越来越多,如:有功、无功、瞬时电压和电流、瞬时功率等等。而CSA5460A芯片可以统计并提供这些电量参数,并将它设计在电能表中,其功能强大足以满足供电部门需求,所以市场前景非常的广阔。 2.1.3 电能的测量原理及方法 对于单相电能计量表来说,最重要的功能就是实现对电能的测量。有功电能测量可以描述为:在 t 时刻内流过元件负载两端的交流电压和交流电流的表达式为: (2.1) u(t),Umsinwt,2sinwt (2.2) itwtwt()Isin()2sin(),,,,m,, 其中,u (t) 、i (t)分别为 t 时刻电压的瞬时值和电流的瞬时值;Um 为电压的峰值;Im为电流的峰值;U为电压的有效值;I为电流的有效值;?代表电流与电压的相位差;ω代表角频率。则在一个周期以内平均有功功率 P 为: T1putit,()(),T0 T1sinI(),,Uwtwtdtmm,, (2.3) T0 T1,,,,UIwtdt[cos(2)cos],,,T0 ,UIcos, 一个周期以内的电能 W 为 T (2.4) WutitdtTUI,,()()cos,,0 电能测量单元都是以式(2.4)为理论基础推导而形成的。实际上用户在使用电能计量表的过程中,数值是不断变化的,根本无法快速而准确地测得每个周期的电压有效值、和电流有效值,所以我们只能采用离散采样来测量。 2.2 离散采样电量测量的原理 电压和电流是测量电能中两个最基本的电量,要想计算电压有效值、和电流有效值,我们往往需要将连续电量离散采样,得到电量的离散表达式。根据电工理论原理 5 可以得出,一个周期T时间内变化的交流电压信号、交流电流信号,电压有效值和电流有效值分别表示为 ,12 (2.5) ,Uutdt(),t0 ,12 (2.6) ,Iitdt(),T0 我们将在时间上连续的的电压信号 U(t) 和电流信号 I(t),通过A/D转换和采样保持的方式,将其转化为在时间和幅度上均为离散数字信号的U(n)或I(n) 。离散形式的电压有效值和电流有效值分别可表示为 N,112 (2.7) Uun,(),Nn,0 N,112 (2.8) Iin,(),Nn,0 上式中 N 表示为电压信号 u(t)或电流信号 i(t)在一个周期内分布的均匀采样的点数。我们只需根据采样定律就可以得出,要想不失真地恢复出被测的信号,N所对应的采样频率必须高出输入的模拟信号频率的两倍。同理,可得出功率P和电能E的计算表达式 T1Putitdt,,,()(),T0 (2.9) T Eutitdt,,,()() (2.10),0 N,11Punin,,()() (2.11),Nn,0 N,1 Eunin,,()() (2.12) ,n,0 这样,我们就能测量出我们需要的电能了。 2.3 CORTEX-M3与STM32 CORTEX-M3是2005年ARM公司发布其最新一代ARM v7内核,在以往的架构上有 [11]了革命性的突破,性能上更是有了本质的飞越。Cortex-M3采用了目前最新的单线调试技术,它专门拿出一个引脚做调试用,从而进一步节约了调试费用。与此同时, 6 Cortex-M3中还集成了存储器、控制器等,这样我们可以直接在MCU上外连Flash存储器,这样可以降低设计难度与应用障碍。 STM32是STM公司在目前最新推出的基于ARM 的Cortex-M3内核产品,继承了Cortex-M3内核的优点,同时又增加了STM高性能的外设资源,有FLASH、SRAM存储器和丰富的串行通信接口,如IIC、SPI、USART、CAN、USB,以及12位的ADC和DAC创建模块,支持单片机外部存储器更灵活的访问静态存储器控制器FSMC。 7 第3章 系统结构及原理 3.1 概述 本设计系统结构如图3.1所示,通过CS5460A读取用户所用的电能数据,实现电能计量。然后由微控制器STM32F103R6进行处理并通过显示模块进行电流、电压、变比和功率的显示。同时把数据存储于存储芯片以便于日后查看。 复位电路 存储器 电压采集 电能计量系统 微控制器 时钟芯片 CS5460A STM32F103R6 电流采集 RS485总线 键盘模块 显示模式 图3.1 原理框图 3.2 电能计量单元介绍 3.2.1 电能芯片的简介 CS5460A是美国Cirrus Logic公司最近推出的,带有串行接口的单相双向功率/电能计量高度集成的电路芯片,目前CS5460A主要被运用在单相电子计量表和三相电子计量表中的设计中。不同于以往的CS5460芯片,该芯片具有的自动引脚模式功能,能使 2芯片脱离单片机单独工作,当得电时又能自动开始初始化,由外部的EPROM引导后独立开始运作,并从中结果读取出数值,如果是为了其高容量和降低生产成本,用于家庭中 8 时,在此模式下,CS5460A芯片也可以与微控制器连接,直接让它独立工作。除了这些以外,CS5460A芯片的综合性能也比其他同类计量芯片更好,其主要表现在: (1)芯片的转换精度之高,测量功能之强。芯片的转换精度不仅达到了0.1级,也可以实现0.2级的测量仪表。它是可以测量瞬时电压与电流、电流与电压有效值、瞬时功率、功率有效值等多种不同的电量参数的电能计量芯片,这在现在的测量芯片中是并不多见的。 (2)芯片外围元器件非常少,它具有的内部电源监视器和片内看门狗定时器(WatchDog Timer),只需用很少的外围元器件便可以实现所需要的转换功能,这为确保了仪表的转换精度和仪表功能的稳定性提供保障。 (3)芯片接口方便。芯片内部寄存器阵列,而接口是双向串行接口,通常我们只需要 可将它与单片机连接起来,这样对于使用者来说更便利,同时它用很简单的几根连线就 还具有的内部寄存器数组,它的功能很强大,使得我们能更好的拓展功能。针对上述这些特点,我们选择CS5460A芯片,可以达到我们要的效果。 (4)CS5460A管脚图。 晶体输入 晶振输出 串行数据输入 CPU时钟输出 能量方式指示 正数字电源 能量输入 数字地 中断 串行时钟输入 复位 串行时钟输入不连接 片选 掉电监视器 模式选择 差模电流输入 差模电压输入 差模电流输出 差模电压输出 正模拟电源 电压参考输出模拟地 电压参考输入 图3.2 CS5460A管脚图 (5)CS5460A原理图。 9 图3.3 CS5460A原理图 3.2.2 电能芯片的工作原理 CS5460A是基于??Σ调制的A/D转换技术,??Σ调制A/D转换器是近几年来发展 【1】起来的一种有别于传统的模数转换器。它是对单频正弦信号和噪声成型滤波、数字信号的一种过滤技术。它的优点在于高分辨率、高速度、高线性度,而且成本低。目前这项技术已经成为主流技术,并运用到高分辨率A/D转换器上。CS5460A内部结构如图3.3所示,CS5460A包括了一个固定的电压增益放大器和可编程增益放大器,一个功率计算引擎和一个串行接口和两??ΣA/D转换器(包括数字滤波器)。当输入电压和电流转化成数字信号后,??Σ的A/D转换器对输入功率进行数字信号处理,这样就可以计算出瞬时电压和瞬时电流、瞬时功率、电能、电压有效值、电流有效值等。CS5460A自动将测量结果存储在24位寄存器中,但它不是真正的测量的结果,这还需要乘以相应的系数才会是最终结果。将测量结果通过串行接口,经过三个总线可以同微控制器和数字信号处理器(DSP)连接。其连接图如3.4。 10 图3.4 单片机与CS5460A连接图 CS5460A在,5v电源下运行。电流通道输入范围为30mV或150 mV,电压通道输入范围为150 mV。在VA,中用,5v电源供电时,CS5460A可以承受范围为,0(25v 【12】到VA,的共模信号。由于总功耗,500mW;(VA,),(VA,)?,6(0v。所以电压通道和电流通道中需要连接电压互感器和电流互感器单。电流、电压均采用差分输入方式,为实现最佳差分输入,R10和R11、R8和R9采用温度系数小、阻值严格匹配电阻串联而成,R13阻值由被测信号最大值决定。 11 图3.5 采集电路图 本设计采用脉冲500个来代表一个千瓦时(kwh),当给定的最大电源线电压为250V,最大电源电流为20A(此时CS5460A的管脚Iin+和Iin-之间电压有效值为150mV),脉冲速率的设定值不由额定线电压和线电流来决定,但是必须考虑到最大线电压和线电流的值,所以我们能算出传感器增益常数Kv和Ki的值分别为: (3.1) KmVV,,150/2500.0006V (3.2) KmVA,,150/200.0075I 电能计量芯片最大的电源线电压与电源线电流对应的电压有效值和电流有效值寄 【13】存器的值均为0.6。这样我们可以计算出脉冲速率的寄存器PR的设定值为: pulselshrKWMvmV11250250 (3.3) PRHz,,,,,,,5001.929KWhrsWKvKi,36001000 但脉冲速率寄存器的值不能被精确的设置为1.929Hz,最接近的设置为0x0003E=1.9375。为了提高我们计算的精度,我们把所有增益寄存器都设定为可编程的,用此方法可矫正PR产生的四舍五入的误差。 12 再由电压通道的增益寄存器为Vgn,电流通道的增益寄存器增益为Ign,此值可计算如下: PR (3.4) 1.0044140404830IV,,,,gngnX1.929 3.3 STM32F103R6单片机 3.2.1 单片机选取 在此设计中单片机作为系统的核心部分,所以它的选择也是非常重要的。由于设计的是单相电能计量系统,所以他的运行速度及功耗是必须考虑在内的。由于STM32F103R6 【2】具有一下特点,在此,选用STM32F103R6作为单片机设计单相电能计量表。 单片机特点: a.内核。ARM 32位的Cortex-M3 CPU,最高工作频率72MHZ,具有单周期乘法和硬件除法,超快运行速度。 b.存储器。它具有64K字节的闪存程序存储器,高达20K字节的SRAM时钟、复位和电源管理,2.0-3.6V供电,上电/断电复位(POR/PDR)、可编程电压监测器(PVD)。 c.低功耗。具有睡眠、停机和待机模式3种模式。 d.模数转换器。2个12位模数转换器,1us转换时间(多达16个输入通道),转换范围:0至3.6V。双采样和保持功能。温度传感器。 f.DMA。具有7通道DMA控制器。 e.多达80个快速I/O端口,几乎所有的端口均可容忍5V信号。 g.调试模式。串行单线调试(SWD)和JTAG接口。 h.多达7个定时器。3个16位定时器、1个16位带死区控制和紧急刹车、2个看门狗定时器(独立的和窗口型的)和1个系统时间定时器。 i.多达9个通信接口。 j.CRC计算单元。 kECOPACK封装。 l.STM32F103R6管脚图。 13 图3.6 STM32F103R6管脚图 所以在此系统中选择STM32F103R6作为设计的核心。虽然它的价格比89C51的高,但是它的运行速度及功耗低之低是无法比拟的,也可以方便我们未来继续拓展其功能,我们选STM32F103R6做为本次课题所需的单片机。 3.3.2 单片机的工作原理 通过附图可以看出,单片机的接口非常简单,分别采用单片机的一般I/O口实现与 [3]其它电路的接口,该系统的时钟部分都是采用两个晶体振荡器实现的。为了考虑到电源的输入对单片机的影响,在电源的管脚增加一个0.1uF的电容来实现滤波,它可以减少输入端收到的干扰,进而增加精确度。 在完成软件设计以后需要把程序下载到单片机当中,所以需要安装JTAG,其接口如图3.7. 14 图3.7 单片机电路图 3.4 时钟电路 3.4.1 芯片介绍 电能计量表中必须要添加实时时钟。实时时钟通常分为软时钟与硬时钟两种。硬时钟由独立的实时时钟芯片组成,其准确度与单片机无关,不易产生误差,增加精确度。本设计就采用这种方法选用了PHILIPS公司的PCF8563。PCF8563是一款针对低功耗而优化的CMOS实时时钟/日历芯片,符合本设计中低功耗的要求。PCF8563提供一个可编程时钟输出、中断输出和掉电(voltage-low)检测器。芯片通过一条双线双向的IIC [4]总线串行传输所有的地址和数据。芯片内置的地址寄存器在每次写入或读取数据字节后会自动加1。 芯片特点: a.芯片提供年、月、日、星期、时、分和秒等信息。 b.工作电压:1.8V,5.5V。 c.低后备电流:0.25μA(VDD,3.0V,Tamb,25?时)。 e.400 kHz的双线IIC总线接口(VDD,1.8V,5.5V时)。 f.外围设备的可编程时钟输出(32.768kHz,1024 Hz,32Hz和1Hz)。 g.报警和定时器。 h.内部集成了振荡电容。 i.片内上电复位。 15 j.IIC总线从地址:读:A3H;写:A2H。 k. 开漏中断引脚 PCF8563芯片具有多种功能:定时器功能、报警功能、中断输出功能及中断输出功能时钟输出功能,以及可以独立完成系统设定的各种各样的复杂的定时服务。另外该芯片还具有看门狗电路, 内部含有时钟电路、低电压检测电路(110V)、振荡电路以及还有两线制的IIC 方式的总线通讯功能,尤其是该芯片采用的IIC总线串行的传输方式,不仅可以使外围电路变得更加简单,而且它还增加了该芯片的可靠程度。 3.4.2 芯片工作原理 SDA是PCF8563芯片的双向引脚,可将其用于串行数据的输入输出;SCI为PCF8563芯片的时钟输入端,系统数据从时钟信号的同步输入器或者从芯片的器件中输出;OSCO为反相放大器的输出端;OSCI为反相放大器的输入端;INT为系统中断信号的输出端,INT为低电平有效,系统可以通过给它设置报警寄存器的功能使之按其在指定的时间内让引脚产生连续的报警信号。SDA、SCI、INT都是漏极开路,并负有上拉电阻等元器件。 [5]本系统PCF8563与STM32F103R6接口采用附图所示接口方案。接口部分可以采用3根口线方式连接,连通后PCF8563的INT引脚会产生周期为1s的脉冲中断信号,再由STM32F103R6的引脚作为其中断触发信号,当产生中断后,PCF8563的基准时间就会被IIC总线读取。其电路图如3.8。 图3.8 时钟电路 [6]从图3.8可以看出电路中使用3V的纽扣电池,这是为了防止断电后时钟电路停止计时。纽扣电池,也叫扣式电池,是指外形尺寸像一颗小纽扣的电池,一般来说直径较大,厚度较薄。在系统中用的是3V可充锂离子扣式电池。锂电池是一种由锂金属或者锂合金材料组合为负极,并使用非水电解质的溶液与材料混合而组成的电 16 池。电池内部则采用了一种螺旋绕制的结构,并且利用一种渗透力极强而且非常精细的聚乙烯薄膜,放入电池的正、负两极间并将其间隔而成。电池的正负极两级的电流收集级分别由铝薄膜和铜薄膜组成组成。而电池的正负两级的锂离子收集极则由锂金属和二氧化钴等氧化物和片状的碳原子材料组成。并且向电池内充上有机的电解质溶液。另外电池内还装有PTC元件和安全阀,以便于当电池处于不正常的工作状态及输出短路时能保护电池不受电量瞬时变化的损坏。 锂电池的特点: a.具有更高的能量重量比和体积比; B.电池电压高,单节锂电池电压为3.6V,约等于3只镍镉或镍氢充电电池的串联电压; C.电池自放电小,可长时间存放,这是该电池最突出的优点; 3.5 电源电路 3.5.1 数字电源 整个计量表采用5V和3.3V供电,由于电能计量芯片和单片机硬件系统都对电源要求比较高,包括了需具有稳压功能和纹波小这些具体的要求,另外我们也必须考虑到采用STM32F103R6这样的硬件系统的超低功耗等特点。因此该硬件系统部分采用7805和TPS76033芯片来实现我们的功能要求,该芯片能很好的满足我们设计的要求,并提供+5V和3.3V的稳压电源。 该系统首先通过变压器使220V的交流电变成12V的交流电,再通过整流电路使交流电变成直流电,进而通过一系列的滤波电路使7805的输入端为稳定的10V直流电,通过7805芯片后电源变成+3.3V的直流电,此系统为其他芯片提供+3.3V稳压电源。其电路图如3.9。 图3.9 +3.3V电路图 17 在2V稳压电源的电路中为了使输出电源的纹波小,在输出部分用了一个C27和C28,另外在芯片的输入端也放置另一个C26,都作为滤波电容,以减少输入端收到的干扰,这样可以让纹波变得更小。电路图如3.1。 图3.10 2V稳压电源图 3.5.2 模拟电源 本设计中电能计量芯片CS5460A的VA+和VA-需要+5V和0V电源,所以设计里要为芯片CS5460A提供模拟的+5V稳压电源。其电路图如3.11。 图3.11 模拟电源 3.6 复位电路 3.6.1 芯片介绍 本设计的单片机系统中,通常单片机的复位电路可采用R-C复位电路,也可以采用复位芯片。由于R-C复位电路采用的单一电阻元件,相比之下采用复位芯片来说,更便宜,但是可靠性不高。故而本设计采用MAX809芯片,虽然价格增加却保证了复位电路的可靠性。MAX809芯片是一种只有单一功能的微型处理器的复位芯片,可将此芯片用于 18 监控微处理器的运转或者监控其它逻辑控制系统的电源电压。它可以在上电、掉电和节电情况下向单片机提供复位的信号。当电源的供电电压低于所限定的门槛电压时,芯片就会发出使其芯片复位的复位信号,这一阶段会一直持续到电源的供电电压又恢复到高出我们所限定的门槛电压为止。 MAX809芯片采用17uA的低电流使其能便携的为电池供电,并且芯片是低电平有效的RESET方式输出。芯片其特性为: a. 芯片可监控5.0V、3.3V和3.0V电源。 b. 芯片的复位延时的时间最小值为140ms。 c. 芯片具有能抗电源的瞬态干扰方式,即使芯片电压低于1.1V时仍能产生使电路复位 的复位信号。 23封装,采用小型3管脚。 d. 芯片采用SOT- e. 不需要外部配件使得芯片更简化。 3.6.2 芯片工作原理 MAX809芯片的连接非常简单,它只有三个管脚,GND接地,VCC接3.3V的电源,RESET接到单片机STM32F103R6的复位端即可就可以实现复位工作。为了减少电源的干扰,还需要在复位芯片的电源芯片的电源输入加一个电容来实现滤波,这样可以减少输入端受到的干扰。 图3.12 复位电路图 19 3.7 键盘输入电路 3.7.1 电路工作原理 键盘电路是用于人们向单片机等硬件设备输入数据,从而实现人机交互的一种电路设计。本设计的键盘电路采用扫描方式从而实现的矩阵键盘。键盘的电路图3.13。 由图可以看出,该矩阵扫描键盘是由行线和列线所组成。键盘的列线由PA3和PA4组成,键盘的行线由PA5,PA6构成。键盘的行线被用于键盘的控制输出端,键盘的列线被用于键盘的输入端。为了保证本设计的方便性,在我们设计的过程中,采用PA3,PA4作为键盘列线,可以利用该管脚的中断功能。PA3,PA4通过上拉电路将该两个管脚拉高,这样当没有人按键的情况下,该两个管脚依然保持高电平,按键一旦被按下时,则变化为低电平,这时通过设置PA3,PA4为低电平触发的中断方式,低电平就触发中断进入中断的服务程序,从而获得输入的数据。 图3.13 键盘电路图 在本设计中使用个四按键。功能分别是变比(包括电压变比,变流变比),上翻键,下翻键,确认键。当按键被按下时,会根据程序指令的不同执行不同的功能,显示电路就会有相应显示。 20 3.8 显示电路 3.8.1 显示电路的实现原理 本设计的显示电路采用的是简单的LED显示方式,而LED选用共阴极。这样的方式不但能满足该系统的要求,也可以减低系统的成本。显示电路图3.14。 本设计让显示电路直接与单片机的数据I/O口进行连接,由于STM32F103R6具有丰富的I/O口资源,所以采用并行的接口方式非常容易,不仅减少了系统的设计的复杂性,也可以增加系统的可靠性。 图3.14 显示电路 3.9 串口通信电路 3.9.1 串口通信芯片介绍 本设计采用RS-485收发器,RS-485收发器采用的是平衡发送与差分接收,即而在接收端,接收器将接收到的差分信号变成TTL电平,而在发送端中,驱动器又将接收到的TTL电信号转换成差分信号并将其向其他元器件输出;因此RS-485收发器具有抑制共模干扰的能力。 该芯片的主要技术参数为: A.芯片工作电源为3,3.6V。 B.芯片工作电流为1mA。 c.数据的传输速率为12Mbps。 本设计在通信电路中使用了隔离器6N137光耦合器。6N137光耦合器是一款用于单通道的高速光耦合器,具有温度、电流和电压的补偿功能,高效的输入、输出隔离,5mA的极小的输入电流,LSTTL/TTL兼容与高速(典型为10MBd)。 6N137光耦合器特性: a.转换速率高达10MBit/s、扇出系数为8。 21 b.摆率高达10kV/us。 c.逻辑电平输出。 d.为集电极开路输出。 3.9.2 芯片工作原理 RS-485接口芯片用于完成将TTL电平转换为RS-485接口电平的任务,这里采用 [7]MAX3485作为RS-485接口芯片。 MAX3485芯片与单片机的连接图如3.12。DE作为芯片的发送器使能端,当DE为1时发送器就可以工作。DI为芯片发送器输入端,RE,A,B都为输出端。当DE为0时,发送器停止工作,且输出端为高阻。RE为输入使能端,当RE为0时允许接收器工作, [8]A,B为输入端,RO为输出端。当为1时接收器被禁止,RO为高阻状态。STM32F103R6单片机通过PB,两端口来控制收发器的工作状态,从而达到与主机通讯的目的。 6N137的工作原理,当输入信号从管脚2与管脚3输入时,信号经过片内光通道会直接被传到片内光敏二极管中,当反向偏置的光敏管受电导通,发光二极管就开始发光。由于与门有两个输入端,我们把转换后的电流和电压输送到与门的其中一个输入端,那么与门的另一个输入就为使能端。当使能端的输出为高电平时,与门输出就会为高电平,再经过输出三极管的反向作用后,光电隔离器就相应会输出低电平。当输入的信号的电流小于触发阈值或使能端输出为低电平时,就会显示为高电平,这个高电平是集电极开路产生的,可针对接收电路加上拉电阻或电压调整电路。 在微机控制系统中,经常用到开关量的输入/输出通道中使用光电隔离技术,最常 [7]用的是隔离方式就是光电隔离器件,本设计就是采用这种设计。 光电隔离的原理如图3.12,其注意的是传输单向性以及使用要求——输入、输出端电源分离。所以本设计中设置了两路电源来解决光电隔离器件两端电压要分离的问题。 22 图3.12 串行通信电路 23 第4章 软件部分 4.1 软件系统的介绍 IAR Systems是一家全球领先的嵌入式系统开发工具和服务的供应商,它成立于1983年,距今天已有超过29年的历史了,提供的产品和服务涉及到嵌入式系统的设计、开发和测试的各个阶段和环节,包括:带有C/C++ 编译器和调试器的开发集成环境(IDE)、各类开发套件、实时操作系统和硬件仿真器以及状态机建模工具等。 公司总部设在北欧的瑞典,在全世界很多地方都设有其分公司。它最著名的产品是C编译器-IAR Embedded Workbench, 基本上所有的知名半导体公司的微处理器都支持。可以说是一家成功的供应商。基本上全球著名的公司都在使用IAR SYSTEMS提供的开发工具,用以开发属于他们自己的产品,目前世界上的各类高新技术里都能看到它的身影。 2003年6月,IAR Systems在中国成立办事处以来,不断加强对中国以及部分东亚国家的产品销售和技术支持。使得公司在中国也有很大的发展。 24 4.2 各功能流程图 开始 系统初始化 显示总电能 电量采集 电量处理模块 Y保存数据,数据存储N Y按键中断,按键处理N Y通信呼叫,通信处理N 图4.1 主程序框图 25 子程序入口 接受电能表地址 N判断地址是否正确 Y 接收主站的请求帧 N判断是否读数据请求帧, 发送异常帧Y 填写发送缓冲区 进行电能表的设调用发送子程序置和控制 调用接受子程序接受主 站应答帧 Y 是否重发, N 退出通信 图4.2 RS485通信流程图 26 中断信号 读取瞬间电流值 Y 过流, N 读取瞬间电压值 Y 过压或次压 停止供电N 读取瞬时功率值 中断返回 图4.3 采集子程序流程图 27 子程序入口 N显示LED Y 扫描键盘是否有键按 下, 延时处理 功能键处理程序执行操作 返回 图4.4 键盘扫描 开始 端口初始化 上电显示子程序 N是否有选通指 令 Y 功能键处理程序 返回图4.5 显示流程图 28 结束语 随着科学技术发展,电子式电能计量表制造成本低、精度高、体积小、功能更齐全等优点,必将完全取代传统的机械式的电能计量表。本电能计量表采用CS5460A电能芯片,它集成了A/D转换、滤波、计算、系统校准等功能,并能够测量多种电能计量参数,不仅简化了单相电能表的硬件和软件的设计,而且还并提高了测量精度,其性能优于其他的单相计量芯片。使用CS5460A设计单相电能计量系统有很多优良的性能,能够满足电力部门和家庭的需要,有广阔的市场前景。 本次设计过程中,经指导老师的指导和本人的刻苦努力之下,基本完成了本次设计任务。通过三个月近三的毕业设计,我深深的感受到了,作为一名学生对基础知识掌握扎实的重要性。毕业设计中,本人将四年所学的知识重新梳理了一下,更有了一个系统化掌握,为以后的工作打下了坚实的基础。通过毕业设计,我受益匪浅,不仅锻炼了良好的逻辑思维能力,而且培养了弃而不舍的求学精神和严谨作风。回顾此次毕业设计,将大学四年所学知识更好的总结,更懂得了作为一名技术人员的艰辛和苦累,通过自身的努力,掌握了单相电能计量表等仪器设计的原则,提高了解决问题的能力。 29 致 谢 首先感谢自动化工程学各位院领导对我们毕业生的支持和关怀,同时也感谢你们为我们在毕业前提供了这样好的一个锻炼机会,让我们能够重新梳理大学所学到的知识,为我们以后踏入社会打上坚实的基础。 然后感谢我的指导丁军航老师,在我遇到困难的时候,他牺牲了自己的宝贵的时间来对我进行指导和帮助。无论什么时间,只要他看到我们问的问题,他都及时回答,答疑解惑,在他的身上,我们可以看到到一个学者的严谨和务实,这些都让我们受用终身。丁老师为了我们的毕业设计也耗费大量心血,无时无刻都对我们的进度表示关切,在他身上,我们学到了很多。 再次感谢在设计过程中帮助过我的同学和朋友,因为你们的支持和鼓励,我才能才遇到困难和瓶颈时能大胆的前进。 还要感谢的是我的父母,谢谢你们培养了我,我马上就要毕业了,在未来的日子里,我会更加努力的学习和工作,不辜负你们对我的殷切期望~我一定会好好孝敬和报答你们~ 最后感谢青岛大学四年以来对我的栽培,我踏入社会以后会严于律己,努力奉献,为社会贡献自己一份微薄的力量,造福社会。四年的读书生活在这个季节即将划上一个句号,但是我的人生才刚刚开始,我将面对又一次新征程。 30 参考文献 [1] 贺富堂基于《电子式单相复费率IC卡电能表的研制》 2008年 [2] 单片机STM32f103STM32F103系列中文手册 [3] 钱云.庄严.智能电能表的设计.电子技术.第五期 [4] 何立民 《I2C总线应用系统设计》 北京:北京航空航天大学出版社1995年 《基于DSP的数据采集及硬盘存储技术的研究与实现》 2007年 [5] 赵伟 [6] 康华光.电子技术基础.高等教育出版社,1998 [7] 《西安航空技术高等专科学校学报》 2009年3期 [8] 李浩哲《微控制器智能型电能计量仪表的设计》 [9] 金美星《电能表行业发展现状及前景分析》 [10] 杜晓《基于CS5460A的单相多费率电能表的设计》 [11] 卢修文 《基于Cortez内核嵌入式处理器的压磁传感信号检测技术研究》 2009年 [12] 李建炜 《CS5460A在电子式电能表中的应用》 2003年6月 [13] 钱云 《基于CS5460A芯片的智能电能表设计》 2006年7月 [14] 潘松峰、刘芳等《单片机原理,系统设计与应用》 [15] 潘永雄、刘殊《单片机原理与运用》 31 附 录 附录1:CS5460A数据的读写 CS5460A的串行接口部分集成了一个带有发送,接收缓冲器的状态机,状态机在SCLK上升沿解释8位命令字。根据对命令的解码,状态机将执行相应的操作,或者为把寻址的内部寄存器的数据传送到发送缓冲区,写操作在数据传输前要等24个SCLK周期。通过寄存器读,写命令,数据可被写入或从CS5460中读出。数据的读、写通过向串口SDI引脚写入相应的8位命令字(高位在前)来启动。一些命令字在执行时受周期计数寄存器和配置寄存器内容的影响,需要先对周期计数器和配置寄存器内容进行正确设置。寄存器写指令后必须跟24位数据,先写命令字启动写操作,然后随着24个连续的串行时钟脉冲,CS5460将从串行输入引脚SDI接收串行数据,一旦收到数据,状态机便将数据写入配置寄存器并返回到命令模式。通过SDI引脚写入命今后,可从SDO引脚读出数据。读,写时序如图1和图2所示。 下面依照时序分别给出读写的基本C程序。 Main() { charcdata , didata; Scanf(“%s,%s”,&cdata,&didata); IC?_writeCS5460(cdata); IC_ReadCS5460(didata);} 32 Void IC?_writeCS5460(unsigned char CData) { unsigned char i; CS5460_SCLK_0; //时钟置零 CS5460_CS_0; //片选置零 For(i=0;i<8;i++) //开始一个字节的CData { CS5460_SCLK_0; //时钟置零 Delay_us(5); //相当于5个NOP CS5460_SCLK_1; //时钟置1 Delay_us(5); //相当于5个NOP If ( CData&0x80) { CS5460_SDI_1;} else { CS5460_SDI_0;} //判断要写入的内容最高位是否为,,是,写,, CData,,CData;} //不是写,,再左移数据,循环写,次 Unsigned int IC_ReadCS5460(unsingned char DIDATA) { unsigned char i , j; Unsigned int DATA; //要返回的内容 DATA,,; //要返回的内容先清零 IC_WriteCS5460(DIDATA); // 写入程序状态字 CS5460_SCLK_0; //时钟置零 For(j=0;j<2;j++) { DATA+=DATA; // 2个字节的循环,根据需要可以改成3个字节 For(i=0;i<7;i++) //先循环要返回的内容(左移一位) { CS5460_SDI_1; 33 CS5460_SCLK_0; //以下开始读出一个字节的8b循环 Delay_us(5); //SDI口置1 If(PINC&(1< #include "fm24c16.h" /******************************************************** * 文件名称: * IIC_Fram.c * 文件说明: * 使用口线模拟IIC *********************************************************/ // P4.6-----SCL // P4.7-----SDA //********************************************************* unsigned char read_Buf; //读缓冲区 unsigned char ctrl_Buf; //用于存放控制指令等的中间缓冲区 unsigned char ack_Flag; //应答标识 //* 延迟 //************************************************ void iic_Delay(void) { _NOP(); _NOP(); _NOP(); } /********************************************************* * 启动IIC *********************************************************/ void start_IIC(void) { P4OUT &= 0x3f; //设置P4OUT P4DIR &= 0x7f; //SDA = 1 iic_Delay(); P4DIR &= 0xbf; //SCL = 1 iic_Delay(); P4DIR |= 0x80; //SDA = 0 iic_Delay(); P4DIR |= 0x40; //SCL = 0 iic_Delay(); } /******************************************************* * 停止IIC 37 *******************************************************/ void stop_IIC(void) { P4DIR |= 0x80; //SDA = 0 iic_Delay(); P4DIR &= 0xbf; //SCL = 1 iic_Delay(); P4DIR &= 0x7f; //SDA = 1 iic_Delay(); P4DIR |= 0x80; //SDA = 0 iic_Delay(); P4DIR |= 0x40; //SCL = 0 } /******************************************************* * 发送 0 *******************************************************/ void send_Zero(void) { P4DIR |= 0x80; //SDA = 0 iic_Delay(); P4DIR &= 0xbf; //SCL = 1 iic_Delay(); P4DIR |= 0x40; //SCL = 0 iic_Delay(); } /******************************************************* * 发送 1 *******************************************************/ void send_One(void) { P4DIR &= 0x7f; //SDA = 1 iic_Delay(); P4DIR &= 0xbf; //SCL = 1 iic_Delay(); P4DIR |= 0x40; //SCL = 0 iic_Delay(); P4DIR |= 0x80; //SDA = 0 iic_Delay(); } /******************************************************* * 发送一个字节数据 *******************************************************/ void send_Char(void) 38 { unsigned char cnt,tmp=0x80; for(cnt=0;cnt<8;cnt++) { if((ctrl_Buf & tmp )> 0) { send_One(); // 发送1 }else { send_Zero(); // 发送0 } tmp /= 2; // tmp右移一位 } } /******************************************************* * 读一个byte数据 *******************************************************/ void read_Char(void) { unsigned char cnt,tmp=0x80; read_Buf = 0x00; for(cnt=0;cnt<8;cnt++) { P4DIR &= 0x7f; //SDA = 1 iic_Delay(); P4DIR &= 0xbf; //SCL = 1 iic_Delay(); if((P4IN & 0x80) > 0x00) { // 收到 1 read_Buf |= tmp; } P4DIR |= 0x40; //SCL = 0 iic_Delay(); tmp = tmp/2; } } /************************************************* * 应答信号 *************************************************/ void iic_ACK(void) { ack_Flag = 0x00; 39 P4DIR &= 0x7f; //SDA = 1 iic_Delay(); P4DIR &= 0xbf; //SCL = 1 iic_Delay(); if ((P4IN & 0x80) == 0x80 ) { ack_Flag = 0x01; } P4DIR |= 0x40; //SCL = 0 iic_Delay(); } /*********************************************** * iic_NACK ************************************************/ void iic_NACK(void) { P4DIR &= 0x7f; //SDA = 1 iic_Delay(); P4DIR &= 0xbf; //SCL = 0 iic_Delay(); P4DIR |= 0x40; //SCL = 0 iic_Delay(); P4DIR |= 0x80; //SDA = 0 iic_Delay(); } /************************************************ * 写一个数据到FRAM ,入口参数为addr_Buf, write_Buf *************************************************/ void write_Fram(unsigned char addr_Buf,unsigned int write_Buf) { unsigned char step_Flag=0x00; while(step_Flag < 0x03) { if(step_Flag == 0x00) { start_IIC(); // 启动 I2c ctrl_Buf = 0xA0; // 设置控制位 send_Char(); // 发送控制位 iic_ACK(); // 确认 if (ack_Flag == 0) step_Flag += 1; }else if (step_Flag==1) { 40 ctrl_Buf = addr_Buf; // 设置地址 send_Char(); // 发送地址 iic_ACK(); // 读 确认 if (ack_Flag == 0) { // 检测是否地址发送成功 step_Flag += 1; }else{ step_Flag = 0; } }else{ ctrl_Buf = write_Buf; // 设置写内容 send_Char(); // 写 iic_ACK(); // 读响应信息 if (ack_Flag == 0) { // 检测是否写成功 step_Flag += 1; }else{ step_Flag = 0; } } } stop_IIC(); // 停止 IIC } /************************************************* * 从FRAM中读数据,入口参数位addr_Buf *************************************************/ unsigned char read_Fram(unsigned char addr_Buf) { unsigned char step_Flag=0; while(step_Flag < 0x03) { if(step_Flag == 0x00) { start_IIC(); //启动 I2c ctrl_Buf = 0xa0; //设置控制位 send_Char(); //发送控制位 iic_ACK(); //读取应答 if (ack_Flag == 0) step_Flag += 1; }else if (step_Flag==1){ // 如果控制位发送成功 ctrl_Buf = addr_Buf; // 设置读地址 send_Char(); // 发送地址 iic_ACK(); // 读响应 if (ack_Flag == 0) 41 { // 是否地址已经发送 step_Flag += 1; }else{ step_Flag = 0; } }else{ start_IIC(); // 启动 IIC ctrl_Buf = 0xa1; // 设置读模式 send_Char(); // 发送控制位 iic_ACK(); // 获取响应 if (ack_Flag == 0) { // 是否发送成功 step_Flag += 1; read_Char(); // 读字符 iic_NACK(); // 发响应 }else{ step_Flag = 0; } } } stop_IIC(); // 停止 IIC return read_Buf; } 42 附录5:通信子程序 #include #include "modbus.h" #include "crc_table.h" #include "type.h" #include "fm24c16.h" #include "yaoxin.h" #include "yaokong.h" #include "math.h" #include "Att7022A_Measure.h" #include "key.h" unsigned int Modbus_ReceDataCount; //接受数据的个数计数器 unsigned int Crc_ReceData; unsigned int crc16(unsigned char *puchMsg,unsigned char usDataLen); unsigned char Modbus_ReceBuffer[35]; //最大校表数据长度 unsigned char RestarFlag; //crc校验 unsigned int crc16(uint8 *puchMsg,uint8 usDataLen) // puchMsg message to calculate CRC upon { // usDataLen quantity of bytes in message uint8 uchCRCHi = 0xFF ; // high byte of CRC initialized uint8 uchCRCLo = 0xFF ; // low byte of CRC initialized uint16 uIndex ; // will index into CRC lookup table while (usDataLen--) // Pass through message buffer { uIndex = uchCRCHi ^ *puchMsg++ ; // calculate the CRC uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ; uchCRCLo = auchCRCLo[uIndex] ; } return (((uint16)(uchCRCHi) << 8) | uchCRCLo) ; } void Modbus(void) { if(Modbus_ReceBuffer[0]==ZpmAddress) { Crc_ReceData=crc16(Modbus_ReceBuffer,Modbus_ReceDataCount-2); if(Crc_ReceData==((Modbus_ReceBuffer[Modbus_ReceDataCount-2]<<8)|Modbus_ReceBuffer[Modbus_ReceDataCount-1])) { P3OUT|=0x20; //p3.5=high,MAX3485 DI enable 发送允 43 许 Rs_485(); } } P3OUT&=~0x20; //p3.5=low,MAX3485 } void Rs_485(void) { unsigned char k; unsigned int SendDataTemp; unsigned char YaoxinData[6],YaokongData[3]; unsigned char Modbus_i,Modbus_j; unsigned char Modbus_SendBuffer[80]; //该数组的体积决定了所能返回数据的个数 unsigned char Modbus_SendDataLenth; Modbus_SendBuffer[0]=Modbus_ReceBuffer[0]; //从机的地址 Modbus_SendBuffer[1]=Modbus_ReceBuffer[1]; // 功能码 switch (Modbus_ReceBuffer[1]) { case 0x01: YaokongData[0]=YaokongState&0x01; YaokongData[1]=YaokongState&0x02; YaokongData[2]=YaokongState&0x04; //发送数据处理 Modbus_SendDataLenth=6; Modbus_SendBuffer[2]=0x01; Modbus_i=Modbus_ReceBuffer[3]; //遥控的起始地址 Modbus_j=Modbus_ReceBuffer[5]; //遥控的路数 Modbus_SendBuffer[3]=YaokongData[Modbus_i]; for(k=1;k>8)&0xff; Modbus_SendBuffer[5]=(crc16(Modbus_SendBuffer,4))&0xff; break; case 0x02: //读取遥信信息 //遥信参数赋值 YaoxinData[0]=YaoxinState&0x01; YaoxinData[1]=YaoxinState&0x02; YaoxinData[2]=YaoxinState&0x04; YaoxinData[3]=YaoxinState&0x08; YaoxinData[4]=YaoxinState&0x10; YaoxinData[5]=YaoxinState&0x20; //发送数据处理 Modbus_SendDataLenth=6; 44 Modbus_SendBuffer[2]=0x01; Modbus_i=Modbus_ReceBuffer[3]; //遥信的起始地址 Modbus_j=Modbus_ReceBuffer[5]; //遥信的路数 Modbus_SendBuffer[3]=YaoxinData[Modbus_i]; for(k=1;k>8)&0xff; Modbus_SendBuffer[5]=(crc16(Modbus_SendBuffer,4))&0xff; break; 按读取一路或多路寄存器数据进行处理 case 0x03: // Modbus_i=Modbus_ReceBuffer[5]; Modbus_SendDataLenth=5+2*Modbus_i; Modbus_SendBuffer[2]=2*Modbus_i; // n路寄存器占2n个字节 SendDataTemp=Modbus_ReceBuffer[2]; SendDataTemp=(SendDataTemp<<8)|Modbus_ReceBuffer[3];//起始地址 for(Modbus_j=0;Modbus_j>8; break; case 0x101: Modbus_SendBuffer[4+2*Modbus_j]=URmsb; Modbus_SendBuffer[3+2*Modbus_j]=URmsb>>8; break; case 0x102: Modbus_SendBuffer[4+2*Modbus_j]=URmsc; Modbus_SendBuffer[3+2*Modbus_j]=URmsc>>8; break; //读取单相电流参数 case 0x106: Modbus_SendBuffer[4+2*Modbus_j]=IRmsa; Modbus_SendBuffe[3+2*Modbus_j]=IRmsa>>8; break; case 0x107: Modbus_SendBuffer[4+2*Modbus_j]=IRmsb; Modbus_SendBuffer[3+2*Modbus_j]=IRmsb>>8; break; case 0x108: Modbus_SendBuffer[4+2*Modbus_j]=IRmsc; Modbus_SendBuffer[3+2*Modbus_j]=IRmsc>>8; break; 45 //读取总有功功率参数 case 0x109: Modbus_SendBuffer[4+2*Modbus_j]=Pt; Modbus_SendBuffer[3+2*Modbus_j]=Pt>>8; break; //读取总无功功率参数 case 0x10A: Modbus_SendBuffer[4+2*Modbus_j]=Qt; Modbus_SendBuffer[3+2*Modbus_j]=Qt>>8; break; //读取总功率因数 case 0x10C: Modbus_SendBuffer[4+2*Modbus_j]=Pft; Modbus_SendBuffer[3+2*Modbus_j]=Pft>>8; break; //读取周波参数 case 0x10D: Modbus_SendBuffer[4+2*Modbus_j]=Freq; Modbus_SendBuffer[3+2*Modbus_j]=Freq>>8; break; //读取单相有功功率参数 case 0x10E: Modbus_SendBuffer[4+2*Modbus_j]=Pa; Modbus_SendBuffer[3+2*Modbus_j]=Pa>>8; break; case 0x10F: Modbus_SendBuffer[4+2*Modbus_j]=Pb; Modbus_SendBuffer[3+2*Modbus_j]=Pb>>8; break; case 0x110: Modbus_SendBuffer[4+2*Modbus_j]=Pc; Modbus_SendBuffer[3+2*Modbus_j]=Pc>>8; break; //读取单相无功功率参数 case 0x111: Modbus_SendBuffer[4+2*Modbus_j]=Qa; Modbus_SendBuffer[3+2*Modbus_j]=Qa>>8; break; case 0x112: Modbus_SendBuffer[4+2*Modbus_j]=Qb; Modbus_SendBuffer[3+2*Modbus_j]=Qb>>8; break; case 0x113: Modbus_SendBuffer[4+2*Modbus_j]=Qc; Modbus_SendBuffer[3+2*Modbus_j]=Qc>>8; 46 break; //读取单相功率因数 case 0x117: Modbus_SendBuffer[4+2*Modbus_j]=Pfa; Modbus_SendBuffer[3+2*Modbus_j]=Pfa>>8; break; case 0x118: Modbus_SendBuffer[4+2*Modbus_j]=Pfb; Modbus_SendBuffer[3+2*Modbus_j]=Pfb>>8; break; case 0x119: Modbus_SendBuffer[4+2*Modbus_j]=Pfc; Modbus_SendBuffer[3+2*Modbus_j]=Pfc>>8; break; //读取继电器输出状态与开关量输入状态 case 0x11A: Modbus_SendBuffer[4+2*Modbus_j]=YaoxinState; Modbus_SendBuffer[3+2*Modbus_j]=YaokongState; break; case 0x11C: Modbus_SendBuffer[4+2*Modbus_j]=EptSum>>16; Modbus_SendBuffer[3+2*Modbus_j]=EptSum>>24; break; case 0x11D: Modbus_SendBuffer[4+2*Modbus_j]=EptSum; Modbus_SendBuffer[3+2*Modbus_j]=EptSum>>8; break; //读取电能 case 0x11E: Modbus_SendBuffer[4+2*Modbus_j]=EqtSum>>16; Modbus_SendBuffer[3+2*Modbus_j]=EqtSum>>24; break; case 0x11F: Modbus_SendBuffer[4+2*Modbus_j]=EqtSum; Modbus_SendBuffer[3+2*Modbus_j]=EqtSum>>8; break; //读取SOE故障信息,每组4条命令,共8组 case 0x120: case 0x124: case 0x128: case 0x12C: case 0x130: case 0x134: case 0x138: case 0x13C: 47 Modbus_SendBuffer[4+2*Modbus_j]=read_Fram(0x61+((Modbus_ReceBuffer[3]-0x20)*9/4 )); Modbus_SendBuffer[3+2*Modbus_j]=read_Fram(0x5C+((Modbus_ReceBuffer[3]-0x20)*9/4 )); break; case 0x121: case 0x125: case 0x129: case 0x12D: case 0x131: case 0x135: case 0x139: case 0x13D: Modbus_SendBuffer[4+2*Modbus_j]=read_Fram(0x63+((Modbus_ReceBuffer[3]-0x21)*9/4 )); Modbus_SendBuffer[3+2*Modbus_j]=read_Fram(0x62+((Modbus_ReceBuffer[3]-0x21)*9/4 )); break; case 0x122: case 0x126: case 0x12A: case 0x12E: case 0x132: case 0x136: case 0x13A: case 0x13E: Modbus_SendBuffer[4+2*Modbus_j]=((read_Fram(0x5F+((Modbus_ReceBuffer[3]-0x22)*9 /4))<<2)|read_Fram(0x60+((Modbus_ReceBuffer[3]-0x22)*9/4))); Modbus_SendBuffer[3+2*Modbus_j]=read_Fram(0x64+((Modbus_ReceBuffer[3]-0x22)*9/4 )); break; case 0x123: case 0x127: case 0x12B: case 0x12F: case 0x133: case 0x137: case 0x13B: case 0x13F: 48 Modbus_SendBuffer[4+2*Modbus_j]=read_Fram(0x5D+((Modbus_ReceBuffer[3]-0x23)*9/ 4)); Modbus_SendBuffer[3+2*Modbus_j]=read_Fram(0x5E+((Modbus_ReceBuffer[3]-0x23)*9/4 )); break; 读取参数设置 // case 0x150: Modbus_SendBuffer[4+2*Modbus_j]=ZpmAddress; Modbus_SendBuffer[3+2*Modbus_j]=ZpmAddress>>8; break; case 0x151: Modbus_SendBuffer[4+2*Modbus_j]=Baudrate; Modbus_SendBuffer[3+2*Modbus_j]=Baudrate>>8; break; case 0x152: Modbus_SendBuffer[4+2*Modbus_j]=VoltageScale; Modbus_SendBuffer[3+2*Modbus_j]=VoltageScale>>8; break; case 0x153: Modbus_SendBuffer[4+2*Modbus_j]=CurrentScale; Modbus_SendBuffer[3+2*Modbus_j]=CurrentScale>>8; break; case 0x154: Modbus_SendBuffer[4+2*Modbus_j]=CurrentPoint; Modbus_SendBuffer[3+2*Modbus_j]=VoltagePoint; break; case 0x155: Modbus_SendBuffer[4+2*Modbus_j]=(VoltageUnit<<6)|(CurrentUnit<<4)|(PowerUnit<<2); Modbus_SendBuffer[3+2*Modbus_j]=PowerPoint; break; case 0x158: Modbus_SendBuffer[4+2*Modbus_j]=PulseLength; Modbus_SendBuffer[3+2*Modbus_j]=RelayOutState; break; //ZPM独自特性 case 0x159: Modbus_SendBuffer[4+2*Modbus_j]=VoltageOneSideScale; Modbus_SendBuffer[3+2*Modbus_j]=VoltageOneSideScale>>8; break; case 0x15A: Modbus_SendBuffer[4+2*Modbus_j]=VoltageTwoSideScale; Modbus_SendBuffer[3+2*Modbus_j]=VoltageTwoSideScale>>8; 49 break; case 0x15B: Modbus_SendBuffer[4+2*Modbus_j]=CurrentOneSideScale; Modbus_SendBuffer[3+2*Modbus_j]=CurrentOneSideScale>>8; break; case 0x15C: Modbus_SendBuffer[4+2*Modbus_j]=CurrentTwoSideScale; Modbus_SendBuffer[3+2*Modbus_j]=CurrentTwoSideScale>>8; break; case 0x15D: Modbus_SendBuffer[4+2*Modbus_j]=VoltageAlarmUp; Modbus_SendBuffer[3+2*Modbus_j]=VoltageAlarmUp>>8; break; case 0x15E: Modbus_SendBuffer[4+2*Modbus_j]=VoltageAlarmDown; Modbus_SendBuffer[3+2*Modbus_j]=VoltageAlarmDown>>8; break; case 0x15F: Modbus_SendBuffer[4+2*Modbus_j]=CurrentAlarmUp; Modbus_SendBuffer[3+2*Modbus_j]=CurrentAlarmUp>>8; break; default: Modbus_SendBuffer[4+2*Modbus_j]=0; Modbus_SendBuffer[3+2*Modbus_j]=0; break; } SendDataTemp++; } Modbus_SendBuffer[5+2*Modbus_i-2]=(crc16(Modbus_SendBuffer,5+2*Modbus_i-2)>>8) &0xff; Modbus_SendBuffer[5+2*Modbus_i-1]=(crc16(Modbus_SendBuffer,5+2*Modbus_i-2))&0xf f; break; case 0x05: //写开关量输出,控制继电器分合 Modbus_SendDataLenth=8; for(k=0;k<6;k++) Modbus_SendBuffer[k]=Modbus_ReceBuffer[k]; //从机返 回数据与主机下发数据完全相同 Modbus_SendBuffer[6]=(crc16(Modbus_SendBuffer,6)>>8)&0xff; Modbus_SendBuffer[7]=(crc16(Modbus_SendBuffer,6))&0xff; if((Modbus_ReceBuffer[3]==0x00)&&(Modbus_ReceBuffer[4]==0xff)) YaokongCommand=0x11; //Do1 合 if((Modbus_ReceBuffer[3]==0x00)&&(Modbus_ReceBuffer[4]==0x00)) YaokongCommand=0x10; //Do1 开 50 if((Modbus_ReceBuffer[3]==0x01)&&(Modbus_ReceBuffer[4]==0xff)) YaokongCommand=0x21; //Do2 合 if((Modbus_ReceBuffer[3]==0x01)&&(Modbus_ReceBuffer[4]==0x00)) YaokongCommand=0x20; //Do2 开 if((Modbus_ReceBuffer[3]==0x02)&&(Modbus_ReceBuffer[4]==0xff)) YaokongCommand=0x31; //Do3 合 if((Modbus_ReceBuffer[3]==0x02)&&(Modbus_ReceBuffer[4]==0x00)) YaokongCommand=0x30; //Do3 开 break; 写单路寄存器 case 0x06: // Modbus_SendDataLenth=8; SendDataTemp=Modbus_ReceBuffer[2]; SendDataTemp=(SendDataTemp<<8)|Modbus_ReceBuffer[3];//起始地址 switch (SendDataTemp) { case 0x513: //清除电能 for(k=0;k<8;k++) write_Fram(80+k,0); EptPulseSum=0; EqtPulseSum=0; //电能脉冲数为零 EptSum=0; EqtSum=0; EnergyClearFlag=1; break; case 0x150: //写仪表地址 ZpmAddress=ParaConvert(Modbus_ReceBuffer[4],Modbus_ReceBuffer[5],1); break; case 0x151: //写通讯波特率 Baudrate=ParaConvert(Modbus_ReceBuffer[4],Modbus_ReceBuffer[5],3); //UART重新初始化 Init_Uart(); break; case 0x158: //写继电器输出方式、脉冲长度的时间值 write_Fram(19,Modbus_ReceBuffer[4]); write_Fram(20,Modbus_ReceBuffer[5]); //更新继电器输出方式与脉冲长度时间 //0x00:继电器1.2.均为电平输出方式 0x01:继电器1脉冲输出方式,2电平输出 方式 //0x02:继电器1电平、2脉冲输出方式 0x03:继电器1、2均为脉冲输出方式 RelayOutState=Modbus_ReceBuffer[4]; //脉冲长度时间赋值,基本单位是100MS PulseLength=Modbus_ReceBuffer[5]; break; case 0x159: //写一次电压变比 //更新一次电压变比与电压变比 VoltageOneSideScale=ParaConvert(Modbus_ReceBuffer[4],Modbus_ReceBuffer[5],9); if(VoltageTwoSideScale==0) VoltageScale=1; 51 else VoltageScale=VoltageOneSideScale/VoltageTwoSideScale; //电压变比= 一次电压参数/二次电压参数 break; case 0x15A: //写二次电压变比 VoltageTwoSideScale=ParaConvert(Modbus_ReceBuffer[4],Modbus_ReceBuffer[5],11); 更新二次电压变比与电压变比 // if(VoltageTwoSideScale==0) VoltageScale=1; else VoltageScale=VoltageOneSideScale/VoltageTwoSideScale; //电压变比= 一次电压参数/二次电压参数 break; case 0x15B: //写一次电流变比 //更新一次电流变比与电流变比 CurrentOneSideScale=ParaConvert(Modbus_ReceBuffer[4],Modbus_ReceBuffer[5],5); if(CurrentTwoSideScale==0) CurrentScale=1; else CurrentScale=CurrentOneSideScale/CurrentTwoSideScale; //电流变比= 一次电流参数/二次电流参数 break; case 0x15C: //写二次电流变比 CurrentTwoSideScale=ParaConvert(Modbus_ReceBuffer[4],Modbus_ReceBuffer[5],7); //更新二次电流变比与电流变比 if(CurrentTwoSideScale==0) CurrentScale=1; else CurrentScale=CurrentOneSideScale/CurrentTwoSideScale; //电流变比= 一次电流参数/二次电流参数 break; case 0x15D: //写电压报警上限 VoltageAlarmUp=ParaConvert(Modbus_ReceBuffer[4],Modbus_ReceBuffer[5],13); break; case 0x15E: //写电压报警下限 VoltageAlarmDown=ParaConvert(Modbus_ReceBuffer[4],Modbus_ReceBuffer[5],15); break; case 0x15F: //写电流报警上限 CurrentAlarmUp=ParaConvert(Modbus_ReceBuffer[4],Modbus_ReceBuffer[5],17); break; } for(Modbus_j=2;Modbus_j<6;Modbus_j++) Modbus_SendBuffer[Modbus_j]=Modbus_ReceBuffer[Modbus_j]; Modbus_SendBuffer[6]=(crc16(Modbus_SendBuffer,6)>>8)&0xff; Modbus_SendBuffer[7]=(crc16(Modbus_SendBuffer,6))&0xff; break; case 0x10: //写多路寄存器 52 if((Modbus_ReceBuffer[3]==0x20)&&(Modbus_ReceBuffer[5]==0x1b)) { for(k=0;k<27;k++) write_Fram(0x20+k,Modbus_ReceBuffer[6+k]); write_Fram(0x1e,0x55); RestarFlag=1; } if((Modbus_ReceBuffer[3]==0x3b)&&(Modbus_ReceBuffer[5]==0x09)) { for(k=0;k<9;k++) write_Fram(0x3b+k,Modbus_ReceBuffer[6+k]); write_Fram(0x1f,0xaa); RestarFlag=1; } if((Modbus_ReceBuffer[2]==0x00)&&(Modbus_ReceBuffer[3]==0x1e)&&(Modbus_ReceBuffer[5]==0x4)&&(Modbus_ReceBuffer[6]==0x00)&&(Modbus_ReceBuffer[7]==0x00)) { write_Fram(0x1e,0); write_Fram(0x1f,0); RestarFlag=1; } if(RestarFlag) { Modbus_SendDataLenth=8; for(k=0;k<6;k++) Modbus_SendBuffer[k]=Modbus_ReceBuffer[k]; //从机 返回数据与主机下发数据完全相同 Modbus_SendBuffer[6]=(crc16(Modbus_SendBuffer,6)>>8)&0xff; Modbus_SendBuffer[7]=(crc16(Modbus_SendBuffer,6))&0xff; } break; } for(k=0;k
/
本文档为【电能计量表设计】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索