利用单片机分时电价系统设计.doc_第1页
利用单片机分时电价系统设计.doc_第2页
利用单片机分时电价系统设计.doc_第3页
利用单片机分时电价系统设计.doc_第4页
利用单片机分时电价系统设计.doc_第5页
已阅读5页,还剩24页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

一、课题说明随着经济的快速发展,电力需求的不断增长和能源价格的不断提升。用电紧张已经成为突出的问题摆在我们面前。而电力又不是可以储存的特殊商品,某些时段用电多,其他时段用电少。用电高峰时电力供不应求,用电低谷时又电力过剩。为了应对这样的难题,可以采用分时电价来缓解供需矛盾,提高电力利用效率。分时电价是指在不同时段采用不同电价,根据用电需求和电网负荷将每天的时间划分为用电高峰时段(6:0022:00)和用电低谷时间段(22:006:00),高峰时段执行较高电价(0.8元/度),低谷时段执行较低电价(0.6元/度)。通过价格杠杆调节电力资源。从而提高电力利用效率。本设计利用单片机控制普通电能表,实现分时计费的功能。本系统可以作为额外的模块安装到普通电能表,这样用户已安装的普通电能表不需要更换为新的电能表,仅仅另外安装了本系统后就可以作为一个标准的智能电能表使用。本系统实现以下功能:1、 记录高峰用电量2、 记录低谷用电量3、 记录总用电量4、 计算并记录高峰时段用电电费5、 计算并记录低谷时段用电电费6、 计算并记录总电费7、 显示高峰用电量8、 显示低谷用电量9、 显示总用电量10、 显示高峰时段用电电费11、 显示低谷时段用电电费12、 显示总用电电费13、 清除电量记录和电费记录记录和计算用电量、电费都由单片机编程完成,显示功能由单片机控制lcd实现。相应的显示功能选项由键盘按键选择。二、系统整体设计本系统的设计时将整个系统划分为多个模块,简化设计流程。同时便于团队协作,将多个任务分配给多人完成。本系统可以简单的划分为5个模块:1、光电转换模块,用于将普通电能表的转数通过光电器件转换为电脉冲,送入cpu的t1端口。2、键盘模块,用于将按键转换为按键编码,并用中断的方式通知cpu有键被按下。3、lcd显示模块,用于显示必要的提示信息和电量、电费的数值。4、时钟模块,为cpu模块提供精确的时刻计数5、核心控制模块,由sst公司的89c58单片机和必要的外围芯片构成,用于接受光电模块送来的电脉冲,对脉冲进行计数,将计数值转化为电量,根据由时钟模块中取得的小时,判断用电的时段,计算相应时段的电量和电费,并记入总电量和电费;接受键盘的中断,根据不同的按键显示不同的功能;控制lcd显示模块,将cpu内部的数据送到lcd上显示,并显示必要的提示信息。各个模块的原理框图下图所示。三、各个分系统的设计原理(共7点)1、 光电转换模块用于获取普通电能表记录的用电量,在普通电能表的旋转铝盘上打一个很小的检测孔提取光脉冲。铝盘每旋转一圈,模块会检测到一个光脉冲,经光电耦合并加以整形放大后转换成电脉冲,送到cpu的t1端用作计数触发脉冲。普通电能表的铭牌上标有每kwh多少转,其含义为电能表转数每达这一数值就是用了一度电(即1kwh)。将从电能表上提取转换后的的脉冲信号送入单片机的t1端并进行计数,编程时将t1计数器的计数模值设为电能表的转数,当计数器计数溢出时就可以判断电能表已经用了一度电。测试时可以使用实验室普通的信号发生器送出脉冲信号代替电能表的转数脉冲,送入单片机的t1端。2、 键盘模块由普通的16键非编码键盘与intel 8279可编程键盘/显示接口芯片组成完整的编码键盘电路。当键盘上有键按下时intel 8279会将按键转换为键码存储在一个fifo(first in first out,先入先出)队列中,并向cpu申请中断。cpu得知中断以后,从intel 8279的存储区读出键码,判断相应的按键,决定执行相应的功能。3、lcd显示模块通过8255外围接口扩展芯片连接到cpu。lcd显示模块规格为12232像素,在显示时分为上下两行。每行占12216个像素,设计显示8个1616的字符。严格的说要显示8个1616的字符,至少要12816个像素,设计时第四个字符和的8个字符各少3个像素列,虽然少了3个像素列,但是由于像素大小极其微小,人的肉眼是很难分辨出来的。这样的设计简化了编程需要考虑的问题。上行一般显示标题、提示、出错信息等,下行一般显示数值。使用时只需要cpu通过8255芯片将显示用的字码存储在lcd模块的内部存储区,lcd就可以显示出相应的字符。4、 在本系统中要记录不同时段的用电量,并计算出不同时段的电费。这就需要一个比较精确的时间标准,通常可以使用motorola公司的mc146818可编程时钟芯片,将计费段的时间存储起来,在各时间段开始向单片机的int0端口申请中断,在不同的时段使系统执行不同的计费程序。在本系统中采用课题1的电脑时钟代替,将课题1的电脑时钟附加额外功能,在整点向外部ram区的一个存储单元写入当前的钟点。cpu在计数满一度电的时候执行中断程序,此时cpu读取外部ram中存储的钟点,判断不同的时段。执行不同的任务。5、 功能设置智能识辨技术:本系统的编码键盘每按下一个键,就中断一次。假如设置某个功能时需要按功能键b和输入数字24,就需要按键3次,键盘模块会发出3次中断申请。这样就带来一个问题:由于每次中断都是调用同一个中断函数,这样,在按下功能键b后,如何将接下来按下的2和4识别为一个整数24并放入相应变量中,而不是认为按下2键是显示总电量,按下4键是显示低谷时段电费?智能识别技术的原理是在b键别按下时系统将标记一个标志位,表明b键已经被按下,然后2键被按下时,系统首先查看标志位有没有被设置,当它发现标志位已经被标记为b时,它即了解到这是一个功能设置,将2放入一个输入缓冲区,而不是显示总电量。并等待下次按键。接着4键被按下后,系统发现标志位被标记为b,它将4放入2后面的缓冲区,等待下次按键。然后结束键(本系统中为e)被按下,系统发现标志位被标记为b,又发现e为结束键,系统利用算法将缓冲区中的2和4转换为一个整数送入到相应的变量中完成设置。然后系统中的标志位被清除,以后的按键回归到正常状态。系统利用智能识别技术,接受键盘输入,对内部的计费标准,如高峰电费、电表转数/kwh等进行设置。6、 功能设置超时自动复位技术:(侦探狗技术)此项技术解决一个实际应用中遇到的问题。设某人a按了键盘上的自定义设置功能键,此时系统功能键标志将被做上标记,系统处于等待设置数值状态。但此时a恰好有事离开,某人b,在不知情的情况下,按照系统的说明书按了09的数字键,以为是显示或者是相应的其他功能。但是系统认为此时输入的数值是对内部数据的设置。这样会产生两个问题:一方面,b因为按了某键而系统没有执行相应功能而莫明其妙;另一方面,b可能在不知情的情况下修改了内部计费、时段等标准,导致系统工作出错。侦探狗技术能够使功能设置在6.5s后超时,然后清除系统内部的功能设置标志,使系统恢复到正常状态。7、 四大关键辅助性算法:这里要说明的几个算法都不参与硬件的驱动,完全是纯软件的算法。虽然很短小,但是简练的完成了其目的。在整个系统控制程序中的地位,不亚于其他与硬件接触的函数。是整个系统中介于外部硬件数据与cpu数据之间的核心。1) 算法numstoarray:这个算法的功能是,将作为第一参数传递的int型整数的各位分离,按照由高位到地位的顺序依次放入作为第二参数传递的数组中。方便其他函数使用数组中的数字,利用字库得到相应的字型码。此算法中其实包含2个子算法。如传递一个整数54321到函数中,第一个子算法将54321的各位分离放入数组,但是此时得到的序列为倒序,即:数组下标0,1,2,3,4分别存放数字1,2,3,4,5。第二个子算法将数组中的元素进行倒序运算,得到需要的顺序,即:数组下标0,1,2,3,4分别存放5,4,3,2,1。2) 算法:arraytocharacters:此算法的功能是,将作为第一参数传递的,存放1位数字的数组,通过查字库,将得到的字型码按顺序放入作为第二参数传递的将要显示的字符库中。此算法运算后得到的字符库就可以送入lcd的显示缓存区,显示出相应的图形了。此算法利用numstoarray算法得到的数组,查找字库,产生字符库。这两个函数作为核心算法被显示电量电费等函数使用。3) 算法arraytodigitali:此算法的功能是将作为第一参数传递的存放一位数字的数组,转化为一个整数返回。此算法一般用来将存放在键盘缓存区的一位数字序列转化为一个整数。其他函数利用返回的整数设置相应变量的值。此函数被设置高峰时段,电表转数等函数使用作为核心算法。4) 算法arraytodigitalf:此算法的功能是将作为第一参数传递的存放一位数字的小数序列数组转换为一个浮点数返回。此算法一般用来将存放在键盘缓冲区的一个小数序列转化为浮点数返回给调用函数。此算法实现时将序列以小数点(系统中为d键)为轴心分成两半,每半都是一个一位整数序列,将两个序列传递给arraytodigitali,arraytodigitali返回两个整数。将小数点后面的整数转换成小数加到小数点前面的整数上完成到浮点数的转换。此函数被设置电费函数调用作为核心算法。整个系统的电路图五、系统软件设计本系统的软件编程同样是按照模块设计的。首先解释本系统软件的部分全局变量。软件的代码请参见ls图片或者pdf。initset结构用于保存高峰时段电价、低谷时段电价、高峰起始时间、高峰结束时间、低谷起始时间、低谷结束时间和普通电能表每度电的转数。这些变量用作电量计费的标准。键盘模块有修改这些变量的功能,以使智能电表系统可以适应不同环境。initset结构定义的全局变量为set,set将initset 结构中的变量实例化。coulometer 结构定义电能表在高峰时段使用的电量、低谷时段使用的电量和使用的总电量。coulometer结构定义的全局变量为coulo。fee结构记录当前使用的电费,包括高峰时段使用电量的电费,低谷时段使用电量的电费和使用的总电费。fee结构定义的全局变量为fee。在程序中由于要用到外部存储器或者io端口的直接地址,所以利用keil c51中绝对定址关键字_at_定义了各种外部端口和io端口的地址。其中ram6264定义为外部ram 中存储的时刻的地址。commandportof8279为键盘控制芯片8279的命令口地址,dataof8279定义为8279数据口的地址。commandportof8255定义为lcd接口芯片8255的控制口地址,aportof8255定义为8255的a口地址,cportof8255定义为8255的c口地址,但是在程序中没有直接使用c口地址,而是通过8255的命令口使c口的各位分别置位来控制c口的。全局函数init_cpu() 和init_8255andlcd()用来对cpu和液晶显示模块进行初始化。init_cpu()用于开放必要的中断允许,将t1口配置为计数器,用来检测电脉冲信号。init_8255andlcd()将8255的a、b、c口配置成方式0输出模式。打开lcd显示并清屏。1、键盘模块程序的设计:键盘模块包含两个中断函数,keyboard和dogsniffer,keyboard函数用于处理键盘按键事件,每次键盘按键中断,keyboad函数会检查按键的键值,根据不同的键值调用不同的功能函数。dogsniffer函数为侦探狗技术的实现函数,当在键盘上按下功能键时keyboard函数调用wakeupdog函数,唤醒侦探狗,其实质是向t0定时器送入定时初值,并使t0开始计时。当t0每65ms定时中断一次。每次中断后系统调用中断处理函数dogsniffer,dogsniffer函数判断功能键标志是否被标记,如果功能键标志被标记,而且按键时间超过t0的100次计数,即6.5s。则dogsniffer使功能键标志复位。如果功能键标志没有被标记,则dogsniffer使t0中断计数复位。并且不在向t0送入定时初值。如果功能键标志被标记,但是t0中断计数未达100次,则将t0中断计数加1,并向t0送入定时初值,开始下次定时。以下是键盘模块程序中使用的函数列表,其中numstoarray等四个辅助算法函数在第二部分,系统整体设计中已经详细描述,这里不在说明。键盘模块各函数间的调用关系图如图所示。void dogsniffer(void) interrupt 1 using 0;void keyboard(void) interrupt 2 using 0;void showhighcoulometer(void);void showlowcoulometer(void);void showallcoulometer(void);void showhighfee(void);void showlowfee(void);void showallfee(void);void clear(void);void wakeupdog(void);void sethighfee(uchar key);void setlowfee(uchar key);void setrotatespeed(uchar key);void sethighstart(uchar key);void sethighend(uchar key);void setlowstart(uchar key);void setlowend(uchar key);uchar numstoarray(int number,uchar array8) ;void arraytocharacters(uchar message8,uchar display832,uchar length);int arraytodigitali(uchar array8,uchar length);float arraytodigitalf(uchar array8,uchar length);keyboard中断处理函数首先将按键的键码读入一个变量中,然后判断功能键标志whichfunctionkey是否被作标记,如果已做标记,则进入一个switch语句,根据不同的键码,调用不同设置函数。如果whichfunctionkey未被标记,则进入标准状态的按键处理过程,此过程通过一个switch语句决定不同的执行方式。按下05键时,为显示相关信息的操作,则直接调用相关函数。按下c键时为复位语句,直接调用clear()函数。当按下功能键6d时,首先将功能键标志whichfunctionkey设置为相同的键码,然后唤醒侦探狗,进行设置超时探测。当下次按下按键时,由于whichfunctionkey已被标记,会转到相应的设置函数执行。如果长时间未按下任何键,当超过侦探狗的超时时间后,侦探狗会将whichfunctionkey标志的标记取消。showhighcoulometer,showlowcoulometer,showallcoulometer和showhighfee、showlowfee、showallfee两组函数用于显示coulometer和fee结构的变量中保存的高峰用电量、低谷用电量、总用电量和高峰电费、低谷电费、总电费的数值。这两组函数将内存中保存的数值转化为一个只存放单个位数字的数组,然后通过查字库numcharacters,将单个数字的字型码送到要显示的字符缓存区里。showhighfee一组函数在显示时,由于内部变量为float型,在lcd上显示时比较困难,而且在计算电费时按照整数结算也是比较容易接受的选择,所以在实现时首先利用标准库中的ceil()函数将float取整,然后再转化为整型数字显示sethighfee、setlowfee、setrotatespeed、sethighstart、和sethighend、setlowstart、setlowend函数用于设置initset结构定义的电价、转数、高峰时段、低谷时段等变量。这些函数被调用时一般将按键信息存储在一个输入缓冲区里面。输入小数点用按键d代替,输入结束用按键e代替。当这些函数检测到一个输入结束按键时,它们将输入缓冲区的数据传递给arraytodigitali或者时arraytodigitalf,由他们完成输入到数值的转化。然后将转化后的数值设为相应变量的当前值。做完这些工作后,这些函数将输入缓存区、缓存位置计数和whichfunctionkey标志复位。以备下一次设置。2、lcd显示模块程序设计:lcd模块部分包含下列几个函数:void sendcommandtolcd(uchar command);void display_left(uchar mdata);void display_right(uchar mdata);void display_all(uchar mdata);void displayselected(uchar pagenum,uchar column,uchar mdata16);void displayatrow(uchar row,uchar column,uchar mdata32);void displayaline(uchar line,uchar mdata832);display_all函数用于系统启动时清屏,不用作其他用途,其他任何函数都不应该调用。lcd模块的设计思想是尽力提供一个较为容易使用的、与硬件隔离的接口给其他调用函数。这一部分的编程模型如下图所示:lcd部分的实现与此模型相对应、sendcommandtolcd、display_left和display_right 函数位于此模型中的“lcd驱动层”中,这3个函数直接接触硬件,所有有关显示的调用都是基于这3个函数之上。sendcommandtolcd函数的功能是向lcd的驱动芯片发送命令字。其参数为要发送的命令字。display_left函数的功能是向lcd的第一块驱动芯片内写入一个字节的显示数据,其直接表现为在lcd的左半部分上显示字符。display_right函数能向lcd的第二块驱动芯片内写入一个字节的显示数据,表现为在lcd的右半部分显示字符。这3个函数都是利用作为全局变量定义的commandportof8255和aportof8255,命令或者数据端口直接读写的。本系统的lcd显示时一个字符占用1616个象素的显示单元,即其一个字符的显示数据为32个字节。displayselected函数和displayatrow函数位于此编程模型之“编程抽象层”,是对sendcommandtolcd、display_left、display_right函数的低层封装。它们使用低层的sendcommandtolcd等3个函数完成显示数据的功能。displayselected函数在指定的页和列开始送入16个字节的显示数据,即半个字符。lcd显示屏共32行,分为4页,每页8行,由于一个字高为16个像素,所以这个性质限制了displayselected函数只能显示半个字。此函数隐藏了一个列实现的细节,lcd由两块显示芯片控制,每一块控制61列,即060列为第一块芯片控制,要用display_left函数显示,第二块控制61121列,要用display_right函数显示,而此函数可以接受的列为00x7f。在函数中会对输入的列参数进行判断,小于0x40的列,函数会调用display_left函数显示,大于或者等于0x40的列,函数会调用display_right函数显示。这样就完成了列的平滑显示。displayatrow函数是对displayselected函数的进一步封装,此函数的意图是掩盖页的跨越,使之能够以一个函数在lcd上显示一个完整的、共32字节数据表示的字符。由于displayselected函数已经掩盖了列的跨越,所以displayatrow的列参数就直接传递给了displayselected函数。displayatrow函数将整个lcd分成了两个显示行,每个显示行包含2个页,16个像素行,可以显示一个完整的字符。其实现原理是对于位于第0显示行的字符,调用2次displayselected函数,将字符的上半数据送到第0页显示,将字符的下半数据送到第1页显示,这样就完成了整个字符的显示。对于位于第1显示行的字符,将字符的上半数据调用displayselected函数送到第2页显示,将字符的下半数据调用displayselected函数送到第3页显示。这样就完成了页跨越的掩盖。位于lcd显示驱动最高层,即“显示服务提供层”的函数只有一个,即displayaline,此函数是基于displayatrow函数的封装。由于displayatrow函数可以在指定位置显示一个字符,基于这种能力派生的displayaline函数的功能就是将一行字符显示在某一个显示行上。由于lcd最多可以显示8个1616的字符。所以displayaline函数显示字符串的最大字符限制也为8个字符。displayaline函数用来向其他需要显示的函数提供服务。一个需要进行显示的函数将它要进行显示的数据通过查表或者其他途径转换为lcd显示的显示码,然后将显示码保存在一个832的数组中传递给displayaline函数,然后displayaline函数将数组中的数据全部送入某行进行显示。两个提示函数showdefault和showerror用于显示必要的提示信息。showdefault函数设计成一个死循环,用于显示系统的待机画面。此待机画面用于向用户提示键盘上各个按键的功能。showerror函数在用户操作出错时向用户显示一个出错提示,以便防止用户误操作。六、总结这个系统是我所设计过的最为复杂的一个系统,虽然硬件部分比较简单,但是这个系统的软件完全是在我已经纯熟的c语言编程技巧的基础上开发的,除了为了了解某些硬件的命令字查看过示例程序外,其他的程序完全是自己开发的,没有参考、抄袭其他任何论文、报告。通过这个系统的设计,我对keil c51的语法,开发方法有了较深的认识,可以肯定的说,如果有第二次机会开发这样的系统,那么,在系统控制程序上所犯的错误,将会大大减少。在设计本系统之前,为单片机编写的程序都是较小的程序,一直用汇编语言写。本系统的复杂性使汇编语言程序不利于编写和阅读,所以采用c语言编写。由于我以前都是为intel 80586以上,安装windows操作系统的pc写c语言的应用程序。所以虽然程序完全符合标准c语言的要求,但是由于硬件平台的不同,还是出现了很多问题。现将各种问题一一描述:1、 中断函数寄存器组使用不当:程序中有3个中断函数,在最初每个中断函数使用的寄存器组都不相同,本意是为了提高寄存器的利用效率。定义侦探狗中断t0使用寄存器组1,键盘中断使用寄存器组2,电量中断使用寄存器组3。但是在调试中发生了一个错误。main函数和keyboard函数中都调用了displayaline函数显示一个字符串。main中的调用可以正常工作,将字符串显示在lcd上,但是keyboard函数中则只能显示字符串的上半行,下半行的字总是显示在lcd的最左边,从而造成这样一些乱码。这个问题对我们造成了相当的困扰,因为main和keyboard调用的是同一个函数。开始时以为是在传递参数时指针出错,后来使用断点调试时才发现,displayaline在显示下半行调用displayselected函数时,列column的实际值都为0,所以所有的字符的下半行都送到第一个字符下面去显示。其后分析认为,产生的错误中,最大的不同是调用displayaline函数的位置不同,即一个在mian中,另一个在keyboard中,它们两个函数使用了不同的寄存器组。main使用的寄存器组为第0组,keyboard使用第2组。由于displayaline函数的参数是通过寄存器组来传递的,所以推断使用其他的寄存器组会导致显示错误。将keyboard函数使用的寄存器组改为0组,错误消失。2、 数据段溢出错误:在最初的程序中,除了字库外,全局变量、静态变量都按照标准c语言方式默认定义,没有考虑到存储位置的问题。但是链接时发生错误,提示data段溢出。最初不明所以,其后查看c51的帮助文档时看到,如果不显式说明变量的存储位置,则变量会根据系统模式的设置存放到默认的数据区。本系统中使用的是89c58最小系统方式,默认情况下变量会存放到系统的data段,由于data段只有128个字节,而且还有寄存器组和位寻址区,难以容纳所有的变量。了解到这些以后,将所有的全局变量和静态变量都显式声明到idata段,idata段为256字节,足以容纳这些变量,问题得意解决。3、 编译器汇编语言与c语言交叉编译不完善:在本系统程序设计中,在某些位置需要用到汇编中的一条nop指令,由于c语言中并无与此功能相近的语句,所以我们求助于c51中的c语言与汇编语言的交叉编译。即在相应位置加入#pragma asm nop #pragma endasm汇编指令,执行空指令。在编译器中设置好相关选项并进行编译。在我的电脑上安装有keil c51 8.02试用版,利用此版本进行编译、链接通过,但是使用版有代码大小限制,无法生成执行文件。实验室安装的为keil c51 6.0版,在链接时无法通过,提示大堆的符号未定义。由于编译器版本老旧的问题,为了生成执行文件,只能将相应位置的汇编指令去除或者用与之近似的c语句代替。4、 编译器对预编译指令未正确解释:本系统程序设计时,由于字库比较大,所以最初是将字库定义在一个头文件characterlib.h中,与主程序隔离。这样的话,修改和阅读都比较方便。但是链接时产生错误,连接器抱怨说字库公开变量被多次定义。推断应该是头文件被多个模块包含产生了错误。然后修改了代码,将characterlib.h文件中所有的变量定义都包含在预处理指令#ifndef characterlib_h #define characterlib_h #endif中,但是在keil c51 6.0版本中仍然会产生错误。如果换用keil c51 8.0版本,则在头文件中不加预编译指令也不会报错。因为实际上只有main.c包含了characterlib.h。最后,只能将字库定义全部从characterlib.h中移到main.c中,问题解决。我可以容忍设计中出任何问题,但是不能容忍实验室的仪器出一点点问题。这是第一次课程设计时留下的痛苦回忆,设计的完全正确,但是结果完全错误。最后发现仪器装作可以正常工作的样子欺骗我们,那时真想扑上去咬它。这次使用的是湖北众友的单片机开发实验箱,总算是正常工作(并不是每个人的都正常工作,汗)。但是问题并不是没有。由于设计的系统中要用到一个lcd显示模块,而这个模块是国产的模块,除了厂家外,并没有标准使用说明书。只能参考实验箱的使用手册。在这个手册上提供了3个关于lcd的信息,一个是protel画的实验箱的lcd部分电路图,一个是手册上的lcd连线示例图,还有一个是lcd模块引脚说明表。但是,这3个资料中,任意两个对lcd引脚连线方法的说明都不同。 真是很无语,幸好这个问题只影响pcb电路图的绘制,对于编程没有影响,暂时将其忽略了。众友开发箱附带的使用手册也令人很无语,居然只有薄薄的58页,还没有我的设计报告长,国产产品的通病。幸好上面的电路图和随机附带的程序源码都还实用,不然的话。关于这个开发板的硬件呢,cpu是sst的89c58,256b可用内存(喜欢),32kb的flashrom(喜欢),时钟为33mhz。此单片机带的32kb的flashrom帮了大忙,我的设计中程序共2000多行,1000行为字库,一半存放于外部ram,一半存放于rom中。1000行为程序代码。这样加起来,代码大小为15kb,要不是他的rom足够大,还真的放不下。lcd为fm12232a 液晶显示模块,共12232个像素。以1616的像素显示一个字的话,这个模块可以勉强显示2行,每行8个字。但是比较郁闷的是,如果要完全以1616像素显示8个字,那么至少12816个像素,这个模块一行只有122个像素,哭。既然要显示汉字,为什么不用12832的啊,用122显8个汉字就会少6个像素,无语。只能将第四个字和第8个字各少3个像素。虽然肉眼不仔细看的话是看不出来的,总觉得不爽之至。还用到一个键盘,由intel 8279和16键的键盘组成。这个8279,intel官方出的使用手册共16页,赞,看人家的资料就是详细。自认为英文阅读还不错的我,(平时编程都是直接查msdn的英文文档练出来的,全英文的芯片手册也看过不少),看到intel的这个手册后呆了,好多词认识,好多词不认识。结果16页的手册没有几句话是我能看懂的。是我太低了,还是intel太高了?这个设计的题目其实很普通,但是据可靠消息,以前很少有人做这个题目,不幸做了这个课题的中途又改做其他的了。由于我班人积极得拼抢自认为简单的设计课题,结果我们这种沉稳的、看是不够积极的人就落下了这个看似很难的设计课题。本来如果以课程设计的观点来看,这个题目也不是很难。但是恰恰遇到了我这样一个人,在编程上超越了绝大部分做过这种课程设计的人,用以现实世界为依据的观点观察了这个课题,设想了一系列实用的、会在现实中遇到的功能。结果这个课题变得无比复杂了,以致于编写了1000行程序代码才解决了这个问题。一天同学告诉我说他用汇编写的程序都200行了,我说:我昨天晚上就写200行了。如此长的程序以致于有人听到后取笑:听说xxx写的程序2000行。我无法反驳,只是想,对于任何一个实用的系统来说,其控制程序没有短于2000行的吧。对于汇编,虽然我也很了解汇编,但是以前从没有试图比较c与汇编之间的效率问题。但是在这次设计中亲切的了解到了。程序中产生了某些问题,需要断点调试,将程序代码反汇编后吃了一惊。以前听说一般一条c语言一般会被解释为3条汇编指令,但是我以前从未想像到i=0;这样一条语句等于3条汇编指令,而i+;这样一条语句被解释为8条汇编指令。不由得脊背发冷,幸亏最初就决定用c写这个系统,不然的话,我这里共2000行的代码,有1000行是程序语句。如果用汇编写的话,至少要写5000行吧。对于keil c51,虽然是一个很有用的工具。但是现在不免存在着暇痣。程序中用到了汇编中的一条nop指令,所以使用了keil c51的c与汇编交叉编译。#pragma asmnop#pragma endasm但是keil c51 6中,居然出现了大堆了名称未定义出错提示。而且对于预编译指令#ifndef characterlib_h#define characterlib_h#endif居然未正确的解释,无语ing。很高兴这两个问题在keil c51 8.02版中已经解决了。关于这些,后面有详细的描述。正如我在题记中所说c51中的c语言,不是c语言。虽然c51中c语言的语法完全相同,但是编程方法和pc上编程有极大的不同。首先pc上面的内存海量,你不用考虑某个变量该放在data?idata?or xdata?当然,最好放在code段,只要你不准备修改这个变量,因为一般单片机的片内rom比ram要大很多,rom以kb衡量,ram以b衡量。data访问最快,但是最小,只有128b,只能放最最最常用的东西,比如你床头放的东西最方便,但是只能放很少的东西,不然你的床会变成猪窝。idata次之,xdata为外扩的存储器,容量最大,但是访问最慢。一般放极大但是不常用的东西。其次在安装操作系统的pc上编程,不用考虑usb的端口地址,硬盘的端口地址,显示器的中断之类的。但是在单片机上,控制程序本身就是一个操作系统。经常会用到各个外部芯片的端口地址,中断号之类的。这个时候c51中的_at_关键字就帮上忙了。这个关键字我找了好长时间的说。没有这个关键字,整个程序的设计就进行不下去了。因为标准c中并没有提供直接定位内存地址的关键字或者功能。而程序中必须对某些端口进行直接的读写。写到这里,不仅想起了微软。微软的系统一向以兼容性好而出名。单片机编程与pc编程最大的不同大概就是,单片机系统的软件本身就是一个操作系统,而pc编程是对操作系统公开的接口进行编程。简单的说就是,微软给我们很多积木,我们自己来设计其造型。微软为了让操作系统兼容各种硬件做了多少工作?付出了多少努力?创新了多少技术?这恐怕我们这些人难以了解的。但是我自己做这样一个简单的系统就必须加入许多的复杂的技术,完成许多复杂的转换。屏蔽许多硬件的特性,使之使用起来更加柔和,更加贴近硬件。实在难以想象像windows这样的系统会怎样的复杂。其实我一直迷惑微软是如何将windows制造出来,一直想微软是如何做到的。峰谷分时电价的现状分析与发展趋势探讨 电价是电力市场最有效的經济调节杠杆。随着电力经济体制改革与电力市场化,运用电价来调节电力经济运行,以优化电力资源配置,提高电力企业整体经济效益,已经势在必行。分时电价是在改革中逐步试点与推广的一种新型电价制度,它是根据不同时段发供电成本不同而制定的不同电价。它包括峰谷分时电价与丰枯分时电价。本文试图对峰谷分时电价的必要性、现状与发展趋势作些探讨。 1 实施峰谷分时电价的必要性 峰谷分时电价是电力产品的瞬时性及供求平衡的客观要求。电能产品作为一种特殊商品,其最大的特点是瞬时性,即电能的产、供、销是同时完成的。电能没有半成品,也不能大量储存。这一特点决定了电能产品供给弹性小,对即时需求依赖性很强。电力产品的特点决定电力企业生产特点是不论发供电设备使用情况如何,设施每天满负荷或轻负荷运行,设备都必须保持良好的状态。而且电力生产除保持电力供求平衡外,为保证安全供电,还必须留有足够的发电备用容量。因此电力企业的基本折旧费、大修理及维修费用、管理费用等固定费用,占电力企业总成本的50%至60%,使生产与供给较为稳定。而电力需求在一年四季与一天的不同时段呈现出波动频繁与波动幅度较大的特点。一年的用电高峰集中于最热与最冷的季节,其它季节为低谷用电;一天的用电高峰集中于18点至22点,低谷用电集中于23点至次日7点。电力生产的稳定性与需求波动性矛盾决定了实施分时电价成为最佳的选择。通过分时电价调节需求,实现供求平衡。 峰谷分时电价以均衡价格为理论依据,有利于运用价格机制均衡电力负荷,实现电力资源优化配置。就电力短期供给和需求而言,在某一时点,电力生产成本、物价指数、季节变化、政策变动等因素的影响视为既定,电价便成为调节负荷率、促进资源优化配置的唯一因素。如图所示: 假设均衡价格为p2,均衡需求量为q2,在高峰用电期,需求量为q1,且q1q2,此时若实行传统价格不变(假定为p3),则p3p2,一方面促使发电企业为追求超额利润而加大供电量,另一方面用户也将自觉避开电价高峰,调整负荷分布,从而降低高峰需求量,增加低谷用电量,自觉削峰填谷,均衡电力负荷。正是分时电价不同时段的价差在自动调节着电力供给与需求的均衡,从而实现电力资源的有效配置与优化组合。 在结构失衡、自然力制约、峰谷差拉大的情况下,实施峰谷分时电价更有必要。长期以来,我国电网建设滞后于电源建设,造成低压配电网多,网架结构薄弱,输配电能力不足,有电送不出;而电源结构较为单一,火电与水电比重较大,其它电源比重小,或刚开始建设起步,调峰电源较少,现有火、水电调峰性能差,加之受自然力影响,如遇酷冷、酷热、洪旱天气的影响,峰谷差急剧拉大,即使某些电网电能较为富余,高峰时也要拉闸限电,低谷时发电机组大量闲置或弃水调峰。在此情况下,实施分时电价,引导客户错峰用电与削峰填谷用电,以均衡电力负荷,实现供需平衡,并产生错峰效益与提高整体经济效益,其意义十分重大。 2 峰谷分时电价的现状分析 我国自1993年在上海市试行峰谷分时电价以来,逐步推广,现在全同绝大部分省市工业大用户中均已实施峰谷分时电价制。其一般做法是将一天分为三个时段:高峰时段(7:30至11:30;18:00至23:00),低谷时段(23:0055次日7:00),其余时间为平时段。高峰时段电价上浮5060%,低谷时段电价下浮5060%,平时段电价相当于基础电价不变。从上海等地实施分时电价的现实来看,效果明显。 2.1 使用效果分析 1993年至2000年,上海市在工业大用户中实行峰谷分时电价,削峰填谷效果明显,用电状况由,过去的结构失衡、高峰时段缺电现象严重转变为供需结构较为合理与供需基本平衡。2001年上海市电力公司扩大到对居民用户实行峰谷分时电价,居民的每日低谷用电量平均达到全日用电量的40%以上。由于低谷电价较低,居民得到更多的实惠。据有关统计数字显示,居民人均每月可节省12.7%的电费,提高了居民对电力消费的兴趣。在上海市居民中安装峰谷分时电表后,用电量增长了15%以上。同时,推动了其他能源用户改用电能的进程。 2.2 负荷转移与成本分析 上海市居民用户家中基本上都装有蓄热式电热水器,其功率9001800kw,一般都选择在低谷时段使用,高峰负荷向低谷转移效果明显,从已投入试点运行的10万户看,若按每户转移1kw计算,则可转移10万kw以上高峰负荷。按常规机组造价4000元kw计算,即可减少4亿元人民币的投入(还不含输配电设备投入和电能损耗的费用),这就降低了电价中的容量成本,提高了经济效益。湖北省在推行峰谷分时电价时测算,该省境内已有200万户有蓄热式电热水器,共计300万kw,若鼓励居民避开高峰时段用电,可削峰填谷20万kw,可减少20亿元人民币的投入,这将大大降低电力容量成本,提高电力行业的整体经济效益。 2.3 其它各项指标分析 2001年上海市将分时电价推广到居民用户中以来,电力运行状况良好。当年,发电量完成了323.38亿kwh,比上一年增长5.14%;售电量完成321.8亿kwh,比上一年增长5.02%;最高发电出力为633.5万kw,同比增长12.68%;日最高发电量为12303万kwh,同比增长10.04%;线损率比上一年下降0.31个百分点;供电煤耗率与上一年持平;供电可靠率达到99.76%,比上一年提高0.09个百分点。 总之,实行分时电价,能引导用户合理用电,优化资源配置,提高供电企业的市场份额,扩大电力销售收入。这对提高电力系统负荷率和发电设备的利用率,充分发挥夜间的供电能力,缓解高峰用电紧张局面,减少供电容量成本均可起到明显的作用。但现时的峰谷分时电价仍存在以下问题: (1)思想认识不足 某些至今仍未实行分时电价的供电企业领导认为,推行分时电价会引起购电成本增加、表计维护加大与平均电价下降,导致经济效益不佳。这是对前面所阐述的分时电价的优越性认识不足所造成的不必要的看法。实践证明,实行分时电价,有利于电力企业整体效益的提高。 (2)峰谷价差幅度小 据有关资料显示,峰谷价差在国外可拉大到8至10倍,而我国一般为2至3倍。由于峰谷价差小,客户削峰填谷的用电积极性虽有所调动,但调动得不很充分,削峰填谷用电仍有进一步挖掘的空间和潜力。 (3)时段划分长,缺乏灵活性 除个别地方实行尖峰、高峰、平段、低谷四时段外,一般为高、平、谷三时段,上海市对居民用户实施的分时电价还只分为峰谷二时段,时段划分太长,而且每一时段电价一经确定就难以改变,缺乏灵活性,不能随时精确地使电价反映发供电成本的变化。 (4)实施的范围比较窄 除上海等极少数地方外,我国目前的分时电价仅在工业大用户中实行,其对用户需求与电力负荷的调整只属于整个电力运行的一部分。同时,由于峰谷分时电价仅对电力用户实行,未能调动产、供、销、用协同推广峰谷分时电价的积极性。因此,峰谷分时电价发挥的作用极其有限。 3 峰谷分时电价改革与发展的趋势 3.1 完善峰谷分时电价运行机制 改革我国峰谷分时电价体制并使之日趋完善是我国当前电价改革的主要任务之一。笔者认为当前峰谷分时电价体制可以从以下几个方面进行改进与完善: (1)扩大峰谷分时电价差 对于已实行的峰谷分时电价,应根据实际需要进一步拉大峰谷电价差。可参照国外做法,逐步拉大到价差为8至10倍,以充分调动广大用户削峰填谷的用电积极性,尤其是低谷用电,其电价的制定应以电价临界点即完全竞争价格为下限,最大限度增加低谷用电量。 (2)加大峰谷分时电价实施的灵活度,改革原来的“一经定价,较长时间不变”的模式 尽最大努力,缩短分时时段与电价变更的时间,以快速应对发供电成本变化的市场需求,达到灵活有效调节的目的。 (3)扩大峰谷分时电价的实施范围 首先,峰谷分时电价应普遍推广到商业与居民用电的领域。虽然商业用电和居民生活用电在用电总量中所占的比重并不大,但其绝对数仍很大,而且是我国电力消费未来的热点与快速增长点。随着流通现代化、现代商业、电子商务与网络营销的发展,商业服务已突破时空限制,为商业用电负荷从高峰转移到低谷创造了条件;随着电热技术和低谷电蓄冰蓄热技术的发展,低谷蓄电成为可能。同时,空调、蓄热式热水器大量进入居民家庭,这些均为居民用户实施峰谷分时电价创造了条件。虽然峰谷分时电表的改造需要定的投资,但从长远看,其总体效益是好的。目前峰谷分时电价已率先进入上海市商业与城镇居民家庭,其成功的经验值得推广,我国峰谷分时电价应逐步从只在工业大用户中实行推广到城镇商业与居民家庭。 其次,峰谷分时电价应推广到上网电价与输配电价领域、我国自改革开放以来,已经打破了垂直垄断的管理体制,初步实行发电和输配电分离。在发电方面,已成立华能、大唐、华电、国电、中电投五大集团公司,还有其他独立发电厂;在输配电方面,已成立国家电网公司与南方电网公司。因此,必须从电厂开始,做到发、输、配电均实行峰谷分时电价,才能做到利益均衡,公平负担,充分调动产、供、销、用各个方面推广峰谷分时电价的积极性。例如,发、输电不实行峰谷分时电价,供电企业按平均电价购电,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论