• 665.50 KB
  • 2022-04-22 11:32:23 发布

CAN总线的温室控制系统设计

  • 86页
  • 当前文档由用户上传发布,收益归属用户
  1. 1、本文档共5页,可阅读全部内容。
  2. 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,可选择认领,认领后既往收益都归您。
  3. 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细先通过免费阅读内容等途径辨别内容交易风险。如存在严重挂羊头卖狗肉之情形,可联系本站下载客服投诉处理。
  4. 文档侵权举报电话:19940600175。
'CAN总线的温室控制系统设计第一章绪论1.概述在工农业生产、冶炼、锻造、环保、国防、科研、航天等部门,经常需要对温度进行测量及控制。准确测量温度对于生物制药、食品加工、造纸等行业更是至关重要的。有些场合控制过程复杂,测控点相距较远,不适合人工现场操作,因此为了保证温度测控的准确和实时,近年来广泛采用自动温度测控系统来代替人工进行温度测控。本次设计将设计出一种自动温度采集与控制系统,要求该系统的温度采集模块不仅可以按照设定独立地进行温度采集,而且能够将分布在不同地点的温度测控模块通过CAN现场总线连接起来,接入PC机进行集中监控和管理。2.国内外研究现状及发展趋势目前,CAN接口芯片的生产厂家众多,协议开放,价格低廉,并且使用简单。可以预计,CAN总线将成为今后众多领域的发展方向。随着现代通信行业的发展,无线通信技术越来越多地应用在过去是有线通信统治的领域。CAN总线这种有线通信方式也将与无线技术相结合,开拓其新的应用天地。CDMA、GPRS、蓝牙技术的发展己将它们连接在一起。CDMA、GPRS、蓝牙是一种无线技术规范,其设计宗旨是以无线方式传输数据,从而为广泛的移动计算、通信和其他设备提供一种更加简单的方式,使其无需线缆即可与另外一台设备进行通信。随着无线技术的完善和将无线技术应用到CAN总线系统中研究的不断深入,可以乐观地预计,未来CAN总线技术的应用将无处不在,虚拟的CAN总线即将诞生。3.设计任务86 运用所学专业课知识设计出一个基于CAN总线的温室控制系统。要求系统至少包含两个温度采集和控制点,并且这两节点处的温度值可以经过网络中的主节点远传到上位机。上位机接收到数据后在显示器上显示温度值,并可以根据此温度值发送命令控制电动机的启停。整个系统的运行状态由上位机进行控制,比如要启动某节点温度测量或者控制某节点上电动机的启停时只需发送通过上位机发送相关命令信息即可。系统设计具体要求如下:1)要求网络中从节点可以准确的测量现场的温度值,并能够将温度值通过CAN通信协议格式传给网络中的主节点。主节点可以与上位机通信也可以与从节点通信,从而实现将从节点的温度值传给上位机和将上位机发送来的命令信息传给从节点。2)上位机要求能够准确及时的显示下位机从节点所上传温度值,并能够发送命令来控制下位机的运行状况。在实现基本要求的基础上尽量将控制界面设计的美观。3)基于上述要求,使用Protel99se绘制出系统硬件原理图。4)基于上述要求,使用C语言或者汇编语言完成下位机程序驱动,使用VB或VC语言或用C+API(应用程序接口调用)实现上位机人机界面的设计,要尽量保证系统的稳定性和可靠性以及实用性。4.论文研究的意义本系统采用CAN现场总线进行通讯,由于一条CAN总线上的节点个数在理论上不受限制,实际应用则主要取决于总线驱动电路,目前可达110个。所以,基于CAN的分布式测控系统适合各种规模的应用场合,由于CAN现场总线采用非破坏总线仲裁技术,大大节省了总线冲突的仲裁时间,尤其是在网络负载很重的情况下,也能稳定通讯,不会出现网络瘫痪,从而提高整个系统的稳定性。CAN协议采用CRC检验并可提供相应的错误处理功能,保证了数据通信的可靠性。同时,由于CAN总线的系统灵活,其节点可以在不要求现存节点及其应用层改变任何软件或硬件的情况下,接入CAN网络,大大提高了系统的可扩充的能力。第二章系统设计方案86 1.系统设计原则1)扩展性能下位机系统板能动态扩展多种用户接口、其他温度传感器等。通信方式的扩展,由CAN总线的形式扩展到RS232、RS485、USB等。2)成本控制设计系统时应尽量使用成熟的、通用的技术实现系统,降低软硬件投入及人力成本。通过加强系统的稳定性,从而降低维修、维护的成本。3)性能要求系统设计完成后,用于现场时,应该能够做到上位机控制界面与下位机系统所在温度采集与控制点通信正常,并且保证通信过程中数据的安全性、可靠性、准确性。2.系统设计分析2.1系统硬件设计根据设计系统的要求,系统硬件设计也就是下位机系统的硬件设计。我们可以将系统硬件设计分为主节点系统设计和从节点系统设计。主节点所实现的主要功能有:可以实现单片机与PC机之间的通信;可以实现主从节点基于CAN通信协议格式的通信。从节点所实现的主要功能有:可以测量节点所处环境的温度并能显示温度值;可以与主节点实现基于CAN通信协议格式的通信。因此我们可以将主节点系统设计主要分为单片机与PC机通信电路设计和单片机与CAN控制器接口电路的设计,可以将从节点系统设计主要分为温度采集电路设计以及数据显示电路设计和单片机与CAN控制器接口电路的设计。鉴于以上分析,进行下位机系统硬件设计时我们的单片机芯片使用51系列STC89C52单片机,该单片机工作性能稳定,同时也是在单片机课程设计中经常使用到的控制芯片。单片机与PC机通信电路设计中我们采用RS232通信协议,这时我们可以使用MAX232系列芯片实现两者之间的电平转换。设计单片机与CAN控制器接口电路时我们采用SJA1000独立CAN控制器。SJA1000是Philips半导体公司PCA82C200CAN控制器(BasicCAN)的替代产品,功能更强,主要用于移动目标和一般工业环境中的区域网络控制[2]。温度采集电路中所使用的温度传感器我们选用DS18B20。它是美国86 Dallasgon公司继DS1820之后推出的增强型单总线数字温度传感器。它在测温精度、转换时间、传输距离、分辨率等方面较DS1820有了很大改进。由于DS18B20输出是数字量,有时候根据需要可能需要模拟量信号,所以我们可以在设计时加入AD590、LM35DZ等输出为模拟量的温度传感器的接口。显示电路设计中我们采用四位共阴极数码管来实现采集到的该节点温度值的显示。然后就是电动机接口电路,我们可以使用一个开关型的三极管外加一个固态继电器来控制电动机的运行状态。各部分电路大体确定后,我们使用Protel99SE来绘制原理图,检查错误并修改。无误后,再生成PCB并据此制作下位机系统板子。2.2系统软件件设计系统的软件设计包括上位机系统软件设计和下位机系统软件设计。上位机的软件设计主要是就是PC机控制界面的设计,要实现与下位机通信和显示下位机系统运行状况及温度采集点温度值的功能。下位机的软件设计分为主节点软件设计和从节点软件设计。主节点主要实现接收上位机命令并解释然后发送给从节点并再将从节点接收到命令后的所回传的数据信息发送给上位机的功能。从节点软件主要实现根据命令作出相应的动作的功能,比如,采集温度、启停电动机等。第三章系统硬件设计86 1.网络构架CAN总线模块采用STC89C52RC作为微处理器,在CAN总线通信接口中采用PHILIPS公司的SJA1000和TJA1050芯片,SJA1000是独立CAN通信控制器,82C250为高性能CAN总线收发器。网络构架如图3-1所示,系统主要由从机CAN节点、CAN总线、主机CAN232节点和上位机三部分所构成。其中从机CAN节点上载有温度传感器和电动机设备等[3]。图3-1基于主从式CAN总线的网络构架2.单片机与CAN控制器接口电路在本系统中基于CAN总线通信协议的节点与节点之间的通信是至关重要的。在设计方案中我们提到此系统中使用的是STC89C52RC单片机和CAN独立控制器SJA1000,下面我们首先了解下SJA1000的内部结构和引脚排列以及其各个引脚的定义,然后就可以方便的进行单片机与控制器的接口电路设计了。2.1SJA1000内部结构SJA1000的内部结构如图3-2所示,主要由接口管理逻辑IML、信息缓冲器(含发送缓冲器TXB和接收缓冲器RXFIFO)、位流处理器BSP、接收过滤器ASP、位时序处理逻辑BTL、错误管理逻辑EML、内部振荡器及复位电路等构成。IML接收来自CPU的命令,控制CAN寄存器的寻址并向控制提供中断信息及状态信息。CPU的控制经IML把要发送的数据写入TXB,TXB中的数据由BSP处理后经BTL输出到CANBUS。BTL始终监视CANBUS,当检测到有效的信息头“隐性电平-控制电平”的转换时启动接收过程,接收的信息首先要由位流处理器BSP处理,并由ASP过滤,只有当接收的信息的识别码与ASP检验相符时,接收信息才最终被写入RXB或RXFIFO中。RXFIFO最多可以缓存6486 字节的数据,该数据可被CPU读取。EML负责传递层中调制器的错误管制,它接收BSP的出错报告,促使BSP和IML进行错误统计。图3-2SJA1000内部结构2.2SJA1000的管脚图及管脚说明SJA1000的芯片引脚排列与名称如图3-3所示。图3-3SJA1000管脚图86 SJA1000的引脚定义如表3-1所列。了解了SJA1000的引脚定义我们就可以根据需要设计出关于SJA1000的应用电路。比如我们这次设计中的温室控制系统要采用CAN通信协议进行数据传输其从节点当中就涉及到SJA1000与CPU的连接。表3-1SJA1000管脚说明符号引脚说明AD7-AD02,1,28-23多路地址/数据复合总线ALE/AS3ALE输入信号(Intel模式),AS输入信号(Motorola模式)/CS4片选输入,低电平允许访问SJA1000(/RD)/E5微控制器的/RD信号Intel模式或E使能信号Motorola模式/WR6微控制器的/WR信号Intel模式或RD//WR信号Motorola模式CLKOUT7SJA1000产生的提供给微控制器的时钟输出信号,时钟信号来源于内部振荡器且通过编程驱动,时钟控制寄存器的时钟关闭位可禁止该引脚VSS18接地XTAL19输入到振荡器放大电路,外部振荡信号由此输入XTAL210振荡放大电路输出,使用外部振荡信号时左开路输出MODE11模式选择输入:1=Inter模式;0=Motorola模式VDD312输出驱动5V电压源TX013从CAN输出驱动器0输出到物理线路上TX114从CAN输出驱动器0输出到物理线路上VSS315输出驱动器接地/INT16中断输出,用于中断微控制器/INT在内部中断寄存器各位都被置位时低电平有效/INT是开漏输出且与系统中的其它/INT是线或的,此引脚上的低电平可以把IC从睡眠模式中激活/RST17复位输入用于复位CAN接口,低电平有效,把/RST引脚通过电容连到VSS通过电阻连到VDD可自动上电复位,例如C=1uF;R=50kΩVDD218输入比较器的5V电压源续表3-186 符号引脚说明RX0,RX119,20从物理的CAN总线输入到SJA1000的输入比较器,支配控制电平将会唤醒SJA1000的睡眠模式,如果RX1比RX0的电平高就读支配控制电平反之读弱势电平,如果时钟分频寄存器的CBP位被置位就旁路CAN输入比较器以减少内部延时,此时连有外部收发电路这种情况下只有RX0是激活的,弱势电平被认为是高而支配电平被认为是低VSS221输入比较器的接地端VDD122逻辑电路的5V电压源注:XTAL1和XTAL2引脚必须通过15pF的电容连到VSS1。2.3STC89C52RC与SJA1000的接口设计将SJAl000的ADO~AD7连接到AT89C5l的P0口,CS连接到AT89C5l的P20,这样,当P20为O时,CPU片外存储器地址即可选中SJAl000,CPU则通过这些地址对SJAl000执行相应的读写操作。设计时,可将SJAl000的RD、WR、ALE分别和AT89C5l的对应引脚相连,INT接AT89C51的IN-T0,这样,CPU可以通过中断方式来访问SJAl000。图3-4CAN总线系统智能节点硬件电路原理图如图3-4所示为CAN总线系统智能节点硬件电路原理图。从图中可以看出,电路主要由四部分所构成:微控制器89C51、独立CAN通信控制器SJA1000CAN86 、总线收发器82C250和高速光电耦合器6N137。微处理器89C51负责SJA1000的初始化,通过控制SJA1000实现数据的接收和发送等通信任务。为了增强CAN总线节点的抗干扰能力,SJAl000的TX0和RX0并不直接和收发器82C250的TXD和RXD相连,而是通过高速光耦6N137后再和82C250相连,这样就可以很好的实现各CAN节点间的电气隔离。应当注意的是光耦部分采用的电源VCC和VDD最好完全隔离,可以用小功率的电源隔离模块来实现,这样就可以提高节点的稳定性和安全性[4]。3.单片机与PC机的通信电路本通信过程采用RS232方式进行,由于单片机中的UART和电脑串口RS232的区别仅在于电平的不同,电脑串口采用232电平,而单片机UART则采用TTL电平,如果不进行电平转换,单片机跟电脑串口就不能进行直接通信,RS232是UART的一种就意味着通信协议的格式是一样的,只要电平统一了,两者之间就可以直接通信,此处应用了MAX232这一芯片,MAX232对两者之间通信的数据没有任何作用,仅仅是中介而已,而其只是负责将两者之间的电平进行统一,使两者之间没有通信障碍[5]。另外,MAX232芯片采用单+5V电源供电,仅需几个外接电容即可完成从TTL到RS232电平的转换,共两路。其中13脚(R1IN)、12脚(R1OUT)、11脚(T1IN)、14脚(T1OUT)为第一数据通道。8脚(R2IN)、9脚(R2OUT)、10脚(T2IN)、7脚(T2OUT)为第二数据通道。TTL/CMOS数据从T1IN、T2IN输入转换成RS-232数据从T1OUT、T2OUT送到电脑DP9插头;DP9插头的RS-232数据从R1IN、R2IN输入转换成TTL/CMOS数据后从R1OUT、R2OUT输出。使用Protel99SE绘制出串行通信模块原理图如图3-5。图3-5单片机与PC机的通信电路图86 4.温度采集电路4.1DS18B20的主要特性1)适应电压范围更宽,电压范围:3.0~5.5V,在寄生电源方式下可由数据线供电。  2)独特的单线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯。  3)DS18B20支持多点组网功能,多个DS18B20可以并联在唯一的三线上,实现组网多点测温。  4)DS18B20在使用中不需要任何外围元件,全部传感元件及转换电路集成在形如一只三极管的集成电路内。  5)温范围-55℃~+125℃,在-10~+85℃时精度为±0.5℃。  6)可编程的分辨率为9~12位,对应的可分辨温度分别为0.5℃、0.25℃、0.125℃和0.0625℃,可实现高精度测温。  7)在9位分辨率时最多在93.75ms内把温度转换为数字,12位分辨率时最多在750ms内把温度值转换为数字,速度更快。  8)测量结果直接输出数字温度信号,以“一线总线”串行传送给CPU,同时可传送CRC校验码,具有极强的抗干扰纠错能力。9)负压特性:电源极性接反时,芯片不会因发热而烧毁,但不能正常工作。4.2DS18B20的内部结构及引脚功能描述DS18B20内部结构主要由四部分组成:64位光刻ROM、温度传感器、非挥发的温度报警触发器TH和TL、配置寄存器。DS18B20的内部结构如下图3-6。图3-6DS18B20内部结构图86 DS18B20的引脚功能描述如下表3-2。表3-2DS18B20引脚功能描述序号名称引脚功能描述1GND地信号2DQ数据输入输出引脚,开漏单总线接口引脚。当被用在寄生电源下,也可以向器件提供电源。3VDD可选择的VDD引脚,当工作于寄生电源时,此引脚必须接地。4.3DS18B20与单片机的连接从控制器到DS18S20的连接仅需一条数据线,完成温度采集与转换所需的电源可以由数据线本身提供而无需外部供电,功耗较低。对于每一个DS18S20,在其内部ROM中具有唯一的64位序列号,因此多个传感器可以同时接于总线,构成分布式的多点温度测控系统[6]。DS18B20与单片机的连接如图3-7所示。图3-7STC89C52与DS18B20的连接需要注意的是连接DS18B20的总线电缆是有长度限制的。试验中,当采用普通信号电缆传输长度超过50m时,读取的测量数据将发生错误;当将总线电缆改为屏蔽双绞线时,正常通信距离可达150m;当采用带屏蔽层且每米绞合次数更多的双绞线电缆时,正常通信距离进一步加长。这种情况主要是由总线分布电容使信号波形产生畸变造成的,因此,在用DS18B20进行长距离测温系统设计时,要充分考虑总线分布电容和阻抗匹配问题。另外,在DS18B20的单总线上所挂DS18B20数量超过8个时,需要解决微处理器的总线问题,因此,在进行多点测温系统设计时要加以注意。86 5.交流电动机接口设计图3-8交流电动机接口图如图3-8所示,当P33为低电平时三极管Q7集电极导通。我们可以通过控制交流电动机的供电电源的通断来控制交流电动机的运行状态。然后控制电动机电源的通断,我们可以通过一个交流固态继电器。继电器的输入端接到图3-8中的JP2,输出端串联到交流电动机的供电电源。6.系统抗干扰设计1)加大电源线截面,合理走线、接地,三总线分开。使用完全光耦隔离的方法来提高抗干扰能力,减少互感振荡,光耦器件应该选择高速类型。2)CPU、RAM、ROM等芯片VCC和GND引脚间接电解电容及瓷片电容:去掉高、低频干扰脉冲。3)独立系统结构,减少接插件与连线,提高可靠性,减少故障率。4)在外部供电的输入接口应加入二极管桥依据电路,防止在一些特殊条件下出现的电流逆向问题,同时也使得内外电路的地线隔离,起到抗干扰作用。5)加复位电压检测电路。防止复位不充分CPU就工作,尤其有EEPROM(电可擦可编程只读存储器)的器件,复位不充分会改变EEPROM存储的内容。86 第四章下位机程序设计系统中CAN节点的程序设计可以分为单片机与PC机通信程序设计和CAN节点之间的通信程序设计以及温度传感器DS18B20的软件设计。1.单片机与PC机通信程序设计本系统中单片机与PC机通信采用的是RS232串行协议。PC机端设置好通信中所用串口的属性,如通信端口、波特率、数据位等,单片机程序据此编写驱动程序,程序主要包括串口的初始化和中断接收数据以及发送数据。部分程序代码如下,其他程序部分见附录三。voidserial()interrupt4using1//串行中断接收一个字节数据{if(RI)//等待一个字节数据接收完{unsignedcharredata;//定义一个无符号字符变量存放接收到数据RI=0;//清除标志位redata=SBUF;//读取数据{//将接收到的数据(命令)放在dabuf[0],以备作为命令发给从节点dabuf[count]=redata;//将接收到的数据放入数组count=count+1;//数组下标指针变量加1if(count==1){count=0;CAN_Send_anylength(dabuf,1);//调用CAN节点之间发送数据}}}}86 2.CAN节点系统软件设计CAN总线节点的软件设计主要包括三大部分:SJA1000初始化、SJA1000数据发送和SJA1000数据接收。2.1SJAl000初始化软件设计SJAl000的初始化程序设计主要是通过对SJAl000的寄存器写入相应的控制字,从而确定SJAl000的工作方式。在对SJAl000的寄存器写入控制字时,要在SJAl000的复位模式下采用软件复位模式。其初始化流程图如图4-1所示。图4-1SJA1000初始化流程图根据图4-1依次编写程序,部分程序代码如下,其他程序代码见附录一。BCAN_ENTER_RETMODEL(void)//置位复位请求{unsignedcharTempData;SJA_BCANAdr=REG_CONTROL;TempData=*SJA_BCANAdr;*SJA_BCANAdr=0x09;if((*SJA_BCANAdr&0x01)==1)86 return0;//设置成功elsereturn1;//设置失败}2.2SJAl000数据发送软件设计报文的发送通常是由CAN控制器根据CAN协议规范自动完成的。首先由CPU将要发送的报文传送到发送缓冲器中,并置位命令寄存器中的发送请求标志。其发送流程图如图4-2所示。发送缓冲区释放?禁止CAN中断将报文写入发送缓冲区置位发送请求是否处于发送完状态YY做其它任务或简单循环NN结束开始图4-2CAN节点数据发送流程图根据以上图示编写程序代码,部分程序代码如下,其他程序代码见附录一。voidCAN_Send_anylength(unsignedchar*CAN_TX_Buf,unsignedcharlength){//CAN节点之间发送数据unsignedchartemptt;loop:SJA_BCANAdr=REG_STATUS;temptt=*SJA_BCANAdr;if((temptt&0x04)==0x00)gotoloop;86 {SJA_BCANAdr=REG_RXBuffer1;*SJA_BCANAdr=length;//帧信息SJA_BCANAdr=REG_RXBuffer2;*SJA_BCANAdr=0x00;//标识码SJA_BCANAdr=REG_RXBuffer3;*SJA_BCANAdr=0x00;//标识码SJA_BCANAdr=REG_RXBuffer4;memcpy(SJA_BCANAdr,CAN_TX_Buf,length);//多个数据复制BCAN_CMD_PRG(TR_CMD);//启动发送数据}}2.3SJAl000接收数据软件设计CPU以一定的周期读取CAN控制器的状态寄存器,从而检查接收缓冲区的状态标志,指示是否至少接收到一个报文。当接收缓冲区状态标志指示为“空”时,表示没有接收到报文;在没有新的检查接收缓冲区状态的要求前,CPU则继续当前的任务。当接收缓冲区状态标志为满的时候,即表明已接收一个或者多个报文。此时CPU将从CAN控制器取出第一个报文,并置位命令寄存器中的释放接收缓冲区标志。其接收流程图如图4-3所示。N接收缓冲区状态=“满”?释放接收缓冲区(设置命令寄存器)处理接收到的报文Y从接收缓冲区读取新报文并保存开始结束图4-3CAN节点数据接收流程图86 根据图示编写程序程序代码如下。voidex0_int(void)interrupt0using1{//通过单片机外部中断0来接收CAN节点之间数据unsignedcharaddr,length,i;SJA_BCANAdr=REG_INTERRUPT;if((*SJA_BCANAdr)&0x01){SJA_BCANAdr=REG_RXBuffer1;//接收缓冲区首地址addr=*SJA_BCANAdr;//取接收缓冲区首地址内容length=addr&0x0F;//取数据长度if((tt&0x40)!=0x40){SJA_BCANAdr=REG_RXBuffer4;memcpy(RevceData,REG_RXBuffer4,8);//读出要一帧中八个字节数据memcpy(RevceData,SJA_BCANAdr,length);//读出需要的length个字节数据for(i=0;i>4;returnb;}DS18B20软件设计中注意事项:1)根据DS18B20的通信协议,主机控制DS18B20完成温度转换必须经过3个步骤:每一次读写之前都要对DS18B20进行复位操作,复位成功后发送一条ROM(只读存储器)指令,最后发送RAM(随机存储器)指令,这样才能对DS18B20与微处理器间采用串行数据传送,因此,在对DS18B20进行读写编程时,必须严格地保证读写时序,否则,将无法正确读取测温结果。2)在DS18B20测温程序设计中,向DS18B20发出温度转换命令后,程序总要等待DS18B20的返回信号,一旦某个DS18B20接触不好或断线,当程序读该DS18B20时,将没有返回信号,程序进入死循环。4.系统下位机软件设计调试程序代码编写完成以后再开发环境中编译看是否通过,如检查到有错误编译系统就会报错,然后再根据提示进行修改,至没有错误时,再重新编译文件并生成.hex文件。将此文件烧录到STC89C52RC单片机中,连接好硬件电路,给系统上电。观察四位共阴极数码管上面是否显示出我们想要显示的温度数据,如不是再修改程序代码,重新编译,重新烧录程序,观察结果……86 此过程重复进行,直到所采集温度数据能在数码管上面稳定显示并且准确度较高。此模块疏通后再加入串行通信部分代码,首先用串口助手测试数据的收发,看单片机与上位机之间能否正常收发数据,如不能修改代码,再编译、烧录、观察,直到数据收发正常为止。如果测试通信没有问题,我们再将下位机系统连接好,通过串口发送命令(比如采集1号节点温度值),看看串口助手能否接收到数据并且正确。如果不行的话,就查看CAN转232节点的程序代码和CAN主节点与从节点之间通信的相关代码并进行修改。另外还有个问题需要注意就是保证CAN节点之间的通信波特率一致和CAN转232端波特率设置与上位机端波特率设置一致。就这样反复调试程序,直到下位机系统能正确的按照我们的意愿对某个按键进行响应为止。此三个模块都疏通之后,下位机的软件设计工作也就基本完成,接下来要做的就是简化、优化程序代码、整理相关文档。86 第五章上位机程序设计上位机程序设计主要包括VisualBisic界面设计和代码编写以及VisualBasic程序设计中问题处理。要求上位机程序能够完成与下位机的基本的通信的功能,设计完成后可以用来显示下位机的测量数据以及发送控制命令。1.VisualBisic界面设计VisualBisic界面设计即为系统上位机人机界面设计。设计时针对系统所要实现的功能添加一些相应的控件,如Label控件、PictureBox控件、CommandButton控件、Text控件、Shape控件Timer控件、OptionButton控件以及MSComm控件。其中与通信相关的控件为MSComm控件要求在实现系统要求的基础上尽量将界面设计的美观得体。界面设计完成后运行效果如图5-1所示。图5-1系统上位机窗体设计效果图2.代码编写86 代码编写就是针对窗体中所加的控件的属性和行为进行设置和控制,这部分内容在VB工程的代码窗口中。程序代码编写可以分为几个主要的部分:窗体加载事件、定时器事件(定时读取数据或者读取系统时间以及用来延时等)MSComm控件的OnComm事件、画动态钟表程序等。2.1窗体加载事件窗体加载事件是程序运行时首先执行的,里面要包括一些提示信息和一些控件或者变量的初始化信息,当然有时候这些信息通过设置控件属性设置比较好。窗体加载事件的程序代码如下:2.2定时器事件设计中共用到5个定时器,定时器Timer1用来定时读取下位机发送过来的数据(此处不再附录代码),Timer2用来定时将PictureBox控件中的Label控件由右向左移动以实现标题栏由右向左移动效果,Timer3用来读取系统时间为动态走针钟表提供时间基准,Timer4和Timer5分别用来模拟两个电动机的动态仿真通过定时画扇形来实现(限于篇幅仅附录其中Timer4事件代码)。相关程序代码如下:2.3MSComm控件的OnComm事件MSComm控件的OnComm事件在使用VB进行通信设计中是至关重要的,此处我们只用其中的一种情况,即CasecomEvReceive。当接收缓冲区中数据个数与MSComm控件的Rthreshold属性设定的一样时触发该事件。在该事件中不仅要完成数据接收还要进行数据处理,如将接收到的数据在相应的控件中进行显示,相关程序代码见附录四。2.4画动态走针时钟为了时使界面看上去更加美观这里显示当前系统时间时采用的是走针式时钟。用代码实现时可以将其分为画时钟的表盘和画走针两个部分。画走针是和时间相关的,已经在定时器事件中的Timer3处提到。所以,这里就只是考虑画时钟表盘了,相关程序代码如下:3.系统上位机软件设计调试86 系统上位机软件设计调试只是检查程序运行时有没有语法错误和窗体上面的控件能否按照要求实现其功能或者显示其效果。调试方法是:按照以上窗体设计和代码设计,程序单步运行,直到整个程序都仿真运行完成之后,看窗体的反应是否和代码的控制相对应,二者结合所实现的人机操作界面能否达到要求。如果不能则修改其中代码或者修改窗体的控件的相关参数,直到能使系统稳定运行为止。然后再将上位机与下位机用通信线连接起来,首先编写简单的下位机程序(可以使单字节或者双字节数据的收发)来进行上位机与下位机之间的通信状况,直到测试结果为,上位机接收到并显示的数据正好就是下位机上传的数据和下位机接收到的数据正好是上位机发送的数据为止,此间一定要注意上位机上面的端口号的选择和波特率的设置,要保证上位机和下位机的通信方式保持一致。4.系统上位机软件设计时常见问题1)上位机显示的数据与预想的效果不一致,或者出现严重错误。在进行上位机和下位机之间的通信时,我们首先要保证通信线已连接好,并且串口号选择正确和波特率保持一致,数据位、停止位,奇偶校验这些保持一致。在此基础上出现上述问题时,我们先检查下位机相关通信的程序代码,看是否有错误,然后再检查是否上位机发送数据的格式与上位机接收和显示数据的格式一致。2)编写上位机代码时,对某些控件的属性或者方法不了解。在VB中编写程序代码时,我们遇到上述问题时,可以从有关VB的MSDN中获取帮助,里面给我们提供了相关控件的属性或者方法以及相应的参考程序示例。如果没有安装MSDN系统,我们也可以从有关VB程序设计的教材中获取解决问题的方法,这里尤其要特别提出的时,遇到问题时,不防到网上查找下相关资料。网上的资料很多,这给我们提取出对我们用的资料增加了难度,但是它确是特别方便的,其中的资料有时候能给我们解决问题的直接答案,有时候是给我们指了一条如何解决问题的思路。86 结论本设计将CAN总线技术、温度传感器DS18B20及STC89C52RC单片机应用于温室控制系统中,文章重点介绍了基于主从式CAN现场总线独立控制器SAJ1000和总线收发器PCA82C250的智能温度采集模块的硬件设计,并简要介绍了CAN节点软件系统的设计思路。实践表明,SJA1000是一种较好的CAN总线控制器件,它的抗干扰性能优良,通信速率较高,电路也比较简单。在PeliCAN模式下,其识别码达29位,因而可满足各种应用场合。在自动化控制系统中,合理安排这29位识别码可以使许多问题得以简化。PeliCAN模式增加的各种功能,大大地方便了通信的调试。DALLAS公司的数字单总线温度传感器DS18B20是目前最新的测温器件,以其线路简单、硬件开销少、成本低廉,集温度测量、A/D转换于一体,具有单总线结构,数字量输出,直接与微机接口等优点,即可用它组成单路温度测量装置,也可用它组成多路温度测量装置,有着无可比拟的应用前景。本设计采用控制器STC89C52RC与DS18B20构成的温度采集系统,经采集测试,证实可以实现准确测量,且系统集成度较高,满足最简的要求。该温度采集模块不仅能够更方便地获取通信数据,并把数据通过CAN现场总线发送到PC机,而且系统结构简洁、扩展方便、抗干扰能力强、可靠性高、实时响应性好。86 参考文献[1]邬宽明.现场总线技术应用选编[M].北京:北京航空航天大学出版社,2003.[2]饶运涛.现场总线CAN原理与应用技术[M].北京:北京航空航天大学出版社,2003.[3]邬宽明.CAN总线原理和应用系统设计[M].北京:北京航空航天大学出版社,1996.[4]周凤余.CAN总线系统智能节点设计与实现[J].微计算机信息,1999,6.[5]李华.MCS-51系列单片机应用接口技术[M].北京:北京航空航天大学出版社,1993.[6]金伟正.单线数字温度传感器的原理与应用[J].电子技术应用,2000.[7]赵景波,张伟.电路设计与制作——Protel99SE高级应用[M].北京:人民邮电出版社,2012.[8]周立功.iCAN现场总线原理与应用[M].北京:北京航空航天大学出版社,2007.[9]王化祥,张淑英.传感器原理与应用[M].北京:天津大学出版社,2007.[10]范逸之,陈立元.VisualBasic与RS-232串行通信控制(最新版)[M].北京:清华大学出版社,2002.[11]赵亮,候国锐.单片机C语言编程与实例[M].北京:人民邮电出版社,2003.86 致谢光阴似箭,日月如梭。四年的读书生活伴随着我们毕业设计的完成将在这个季节画上一个句号。在这次毕业设计中,我要感谢很多给予我过帮助的老师和同学。其中我要特别感谢的是我的专业课老师也是我的毕业论文的指导老师张明海老师。从最初的定题,到资料收集,到系统设计,到论文写作,到最终的论文定稿,张老师都是给我耐心的指导和无私的帮助。尽管他现在的课程任务很多,但是总能抽出时间来为跟着他做毕业设计的同学辅导。张老师不仅教会了我专业知识,还教会了我如何学习,教会了我如何做人。在此向所有曾帮助过我的老师表示我由衷的谢意,并祝愿我的老师们培养出越来越多的优秀人才,桃李满天下!同时也非常感谢帮助过我的同学们,愿他们步入社会后工作顺利,前程似锦!86 附录一1号CAN节点程序代码#include"string.h"#include"reg51.h"#include"sja1000.h"#defineucharunsignedchar#defineuintunsignedintunsignedcharser,shi,ge,xiao;unsignedinttemp;//存放温度值unsignedcharcodetable[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,x83,0xc6,0xa1,0x86,0x8e};unsignedcharxdata*SJA_BCANAdr;unsignedchardataRevceData[10];unsignedcharinbuf1[8];sbitDS=P2^4;//定义DS18B20接口DS=P2^4sbitP2_0=P2^0;//数码管位选sbitP2_1=P2^1;sbitP2_2=P2^2;//数码管位选sbitP2_3=P2^3;sbitCS=P2^0;voidinit_serialcomm(void){SCON=0x50;TMOD|=0x20;//定时器T1方式2定时PCON|=0x80;//波特率倍增TH1=0xFA;//波特率9600初始值86 TL1=0xFA;IE=0x90;//开中断总允许,开串行中断TR1=1;//启动定时器1}//向串口发送一个字符voidsend_char_com(unsignedcharch){SBUF=ch;while(!TI);TI=0;}voiddelay(uintcount)//delay{uinti;while(count){i=200;while(i>0)i--;count--;}}/*1.复位:对DS18B20操作之前,首先要将它复位。复位时序为:(1)主机将信号线置为低电平,时间为480~960μS。(2)主机将信号线置为高电平,时间为15~60μS。3)DS18B20发出60~240μS的低电平作为应答信号。主机收到此信号后,才能对DS18820作其它操作。*/voiddsreset(void)//sendresetandinitializationcommand{uinti;//DS18B20初始化86 DS=0;i=103;while(i>0)i--;DS=1;i=4;while(i>0)i--;}/*读操作:主机将信号线从高电平拉低至低电平1μS以上,再使数据线升为高电平,产生读起始信号。从主机将信号线从高电平拉低至低电平起15~60μS的时间内DS18820将数据放到信号线上,供主机读取。从而完成了一个读周期。在开始另一个读周期前,必须有1μS以上的高电平恢复期。*/bittmpreadbit(void)//readabit读一位{uinti;bitdat;DS=0;i++;//i++fordelay小延时一下DS=1;i++;i++;dat=DS;i=8;while(i>0)i--;return(dat);}uchartmpread(void)//readabytedate读一个字节{uchari,j,dat;dat=0;for(i=1;i<=8;i++){j=tmpreadbit();dat=(j<<7)|(dat>>1);//读出的数据最低位在最前面,这样一个字节在DAT里86 }return(dat);//将一个字节数据返回}/*写操作:主机将信号线从高电平拉至低电平,产生写起始信号。从信号线的下降沿开始,在15~60μS的时间内DS18820对信号线检查,如信号线为高电平,则写1如信号线为O,则写0,从而完成了一个写周期。在开始另一个写周期前,必须有1μS以上的高电平恢复期。*/voidtmpwritebyte(uchardat)//writeabytetods18b20{//写一个字节到DS18B20里uinti;ucharj;bittestb;for(j=1;j<=8;j++){testb=dat&0x01;dat=dat>>1;if(testb)//write1写1部分{DS=0;i++;i++;DS=1;//在15~60μS的时间内DS18820对信号线检?i=8;while(i>0)i--;}else{DS=0;//write0写0部分i=8;while(i>0)i--;//在15~60μS的时间内DS18820对信号线检?DS=1;i++;i++;86 }}}voiddelay_ms(unsignedchart){unsignedchari,j;for(i=0;i0)i--;count--;}}/*1.复位:对DS18B20操作之前,首先要将它复位。复位时序为:(1)主机将信号线置为低电平,时间为480~960μS。(2)主机将信号线置为高电平,时间为15~60μS。(3)DS18B20发出60~240μS的低电平作为应答信号。主机收到此信号后,才能对DS18820作其它操作。*/voiddsreset(void)//sendresetandinitializationcommand{uinti;//DS18B20初始化DS=0;i=103;while(i>0)i--;DS=1;i=4;while(i>0)i--;}86 /*读操作:主机将信号线从高电平拉低至低电平1μS以上,再使数据线升为高电平,产生读起始信号。从主机将信号线从高电平拉低至低电平起15~60μS的时间内DS18820将数据放到信号线上,供主机读取。从而完成了一个读周期。在开始另一个读周期前,必须有1μS以上的高电平恢复期。*/bittmpreadbit(void)//readabit读一位{uinti;bitdat;DS=0;i++;//i++fordelay小延时一下DS=1;i++;i++;dat=DS;i=8;while(i>0)i--;return(dat);}uchartmpread(void)//readabytedate读一个字节{uchari,j,dat;dat=0;for(i=1;i<=8;i++){j=tmpreadbit();dat=(j<<7)|(dat>>1);//读出的数据最低位在前,这样刚好一个字节在DAT里}return(dat);//将一个字节数据返回}/*写操作:主机将信号线从高电平拉至低电平,产生写起始信号。从信号线的下降沿开始,在15~60μS的时间内DS18820对信号线检?如信号线为高电平,则写1,如信号线为O,则写0,从而完成了一个写周期。在开始另一个写周期前,必须有1μS以上的高电平恢复期。*/86 voidtmpwritebyte(uchardat){//写一个字节到DS18B20里uinti;ucharj;bittestb;for(j=1;j<=8;j++){testb=dat&0x01;dat=dat>>1;if(testb)//write1写1部分{DS=0;i++;i++;DS=1;//在15~60μS的时间内DS18820对信号线检?i=8;while(i>0)i--;}else{DS=0;//write0写0部分i=8;while(i>0)i--;//在15~60μS的时间内DS18820对信号线检?DS=1;i++;i++;}}}voiddelay_ms(unsignedchart){unsignedchari,j;for(i=0;i102)Then"判断发送内容是否为0到9或是A到F,否则弹出错误信息x=MsgBox("发送数据只能为单字节十进制数(0-9A-Fa-f),十六进制后不要加H")ExitSub"跳出EndIf86 If(AscB(s2)<48)Or((57102)Then"判断发送内容是否为0到9或是A到F,否则弹出错误信息x=MsgBox("发送数据只能为单字节十进制数(0-9A-Fa-f),十六进制后边不要加H")ExitSub"跳出EndIfIfAsc(s1)<=57Then"为0到9时n1=Asc(s1)-48ElseIf65<=Asc(s1)AndAsc(s1)<=70Then"为A到F时n1=Asc(s1)-55Else:n1=Asc(s1)-87"为a到f时EndIfIfAsc(s2)<=57Thenn2=Asc(s2)-48ElseIf65<=Asc(s2)AndAsc(s2)<=70Thenn2=Asc(s2)-55Else:n2=Asc(s2)-87EndIfz3=n2"地址编号送给整型变量z3n3=n1*16+n2"十六进制转换为十进制TT(1)=n3"将n3的值赋给字节型数组TTText5.Text=Text5.Text+Format(Hex(TT(1)),"00")+"""Text5文本框显示发送的数据Fork=1To20000Step1"两个For循环嵌套,实现延时一段时间Forl=1To4Step1NextNextbuf=MSComm1.Input"清除缓冲区MSComm1.Output=TT"发送数据86 NextElseIfOption2.Value=TrueThenMSComm1.InputMode=comInputModeTextIfText4.Text=""Then"判断Text1文本框中内容是否为空,为空则弹出提示窗口x=MsgBox("发送地址数据不能为空",16)ExitSub"跳出EndIfbuf=txt4.Text"Text1文本框中的内容给buf字符串变量k2=Len(buf)"取buf字符串变量的长度(字符个数)Ifk2>1Then"判断十六进制发送数据时,字符串长度是否为大于两个字符x=MsgBox("请输入待发送单个字符")ExitSub"跳出EndIfs1=Left(buf,1)"取buf字符串最左边一个字符送字符串变量s1TT(1)=AscB(s1)"将n3的值赋给字节型数组TTText5.Text=Text5.Text+s1+"""Text5文本框显示发送的数据Buf=MSComm1.Input"清除缓冲区MSComm1.Output=TTIfTT(1)=81ThenTimer4.Enabled=TrueElseIfTT(1)=84ThenTimer4.Enabled=FalseEndIfMSComm1.InputMode=comInputModeBinaryEndIfEndSubPrivateSubCommand11_Click()"清除命令Text4.Text=""EndSub86 PrivateSubCommand12_Click()"清除记录Text5.Text=""EndSubPrivateSubCommand13_Click()Text7.Text=""EndSubPrivateSubCommand2_Click()"停止温度测量DimTT(1To1)AsByteTT(1)=71MSComm1.Output=TTEndSubPrivateSubCommand3_Click()"结束系统MSComm1.PortOpen=FalseEndEndSubPrivateSubCommand4_Click()"启动1号电机DimTT(1To1)AsByteTT(1)=81"QMSComm1.Output=TTTimer4.Enabled=TrueEndSubPrivateSubCommand5_Click()"停止1号电机DimTT(1To1)AsByteTT(1)=84"TMSComm1.Output=TTTimer4.Enabled=FalseEndSubPrivateSubCommand6_Click()"启动2号电机DimTT(1To1)AsByte86 TT(1)=3MSComm1.Output=TTTimer5.Enabled=TrueEndSubPrivateSubCommand7_Click()"停止1号电机DimTT(1To1)AsByteTT(1)=4MSComm1.Output=TTTimer5.Enabled=FalseEndSubPrivateSubCommand8_Click()"重置温度下限值Text2.Text=""Text2.SetFocusEndSubPrivateSubCommand9_Click()"重置温度上限值Text3.Text=""Text3.SetFocusEndSubPrivateSubForm_Load()Form1.ShowOption2.Value=True"启动时字符型发送Combo1.ListIndex=3"启动时选择串口4Combo2.ListIndex=3"启动时选择波特率9600x1z=0"全局变量初始值x1z1=0.2x2z=0x2z2=0.04Text1.Text="""启动时清空Text1/Text2/Text3/Text4/Text5Text2.Text=""86 Text3.Text=""Text4.Text=""Text5.Text=""Text6.Text="中国石油大学胜利学院2009级信息与计算科学系自动化专业毕业设计--基于主从式CAN总线的温室控制系统上位机控制面板功能简介:发送十六进制01H采集1#节点温度值发送十六进制;发送03H或者单击启动测量命令按钮跟踪2#节点温度值;发送04H或者单击停止测量按钮停止2#节点温度测量;发送05H启动节点1上电动机(06H停止);发送07H启动2#节点电动机(08H停止)。下位机能根据2#节点温度变化改变电动机转速上位机能仿真出电动机运行状态"Text7.Text=""Text2.SetFocus"设置焦点label4_speed=50Label4.FontSize=20sngCX=ScaleWidth/2"时钟显示在窗体中央sngCY=ScaleHeight/2Scale(-sngCX,sngCY)-(sngCX,-sngCY)FillColor=vbWhiteCircle(-2500,-1800),600,vbWhiteFillColor=QBColor(10)Circle(-2500,-1800),550,QBColor(10),-0.001,-1.05"1号电机扇叶Circle(-2500,-1800),550,QBColor(10),-2.1,-3.15Circle(-2500,-1800),550,QBColor(10),-4.2,-5.25FillColor=vbWhiteCircle(100,-1800),600,vbWhiteFillColor=QBColor(10)Circle(100,-1800),550,QBColor(10),-0.001,-1.05"2号电机扇叶Circle(100,-1800),550,QBColor(10),-2.1,-3.15Circle(100,-1800),550,QBColor(10),-4.2,-5.25blnBeginFlag=True86 sngRClock=910"设置时钟半径sngHLen=sngRClock*0.45"设置时针长sngMLen=sngRClock*0.6"设置分针长sngSLen=sngRClock*0.8"设置秒针长timecol=QBColor(15)EndSubPrivateSubMSComm1_OnComm()"MSComm1_OnComm事件中接收数据DimRR()AsByteDimk%,buf$MSComm1.InputMode=comInputModeBinarySelectCaseMSComm1.CommEventCasecomEvReceive"收到一组数据个数由RThreshold决定buf=""RR=MSComm1.InputFork=LBound(RR)ToUBound(RR)Ifk=0ThenIfStr(RR(k))=1Then"判断正负buf1=""ElseIfStr(RR(k))=2Thenbuf1=""EndIfElseIfk=3Then"加小数点buf1="."+Str(RR(k))Else:buf1=Str(RR(k))EndIfbuf=buf+buf1NextIfRR(0)=1ThenText7.Text=Str(Val(buf))&"℃"86 ElseIfRR(0)=2ThenIfVal(buf)Val(Text2.Text)Then"温度大于上限值Shape2.FillColor=vbWhiteShape1.FillColor=vbRedx2z2=0.19-(Val(buf)-Val(Text3.Text))/1000Text1.Text=Str(Val(buf))&"℃"Else"温度处于上下限值之间Shape1.FillColor=vbWhiteShape2.FillColor=vbWhitex2z2=0.04EndIfEndIfEndSelectEndSubPrivateSubOption1_Click()"二进制MSComm1.InputMode=comInputModeBinaryEndSubPrivateSubOption2_Click()"字符MSComm1.InputMode=comInputModeTextEndSubPrivateSubTimer1_Timer()"定时器定时接收数据,使用时将窗体中Timer1.Enabled设置为TrueDimRR()AsByteDimk%,buf$86 MSComm1.InputMode=comInputModeBinaryIfMSComm1.InBufferCount=0ThenText1.Text=""ExitSubEndIfbuf=""RR=MSComm1.Inputk=Len(MSComm1.Input)Fork=LBound(RR)ToUBound(RR)Ifk=0ThenIfStr(RR(k))=10Then"判断正负buf1="-"ElseIfStr(RR(k))=11Thenbuf1="+"Else:buf1=Str(RR(k))EndIfElseIfk=3Then"加小数点buf1="."+Str(RR(k))Else:buf1=Str(RR(k))EndIfbuf=buf+buf1NextMSComm1.InBufferCount=0"清空缓冲区IfVal(buf)=111.1Then"下位机返回的电机状态1111--运行Timer4.Enabled=TrueExitSubElseIfVal(buf)=222.2Then"下位机返回的电机状态2222--停止Timer4.Enabled=FalseExitSub86 EndIfIfVal(buf)Val(Text2.Text)Then"温度大于上限值Shape2.FillColor=vbWhiteShape1.FillColor=vbRedText1.Text=Str(Val(buf))&"℃"Else"温度处于上下限值之间Shape1.FillColor=vbWhiteShape2.FillColor=vbWhiteText1.Text=Str(Val(buf))&"℃"EndIfEndSubPrivateSubTimer2_Timer()"标题移动IfLabel4.Left>-14280ThenLabel4.Left=Label4.Left-20"左移ElseLabel4.Left=8115"标题初始位置EndIfEndSubPrivateSubTimer3_Timer()DimintXAsInteger,intYAsIntegerDimintHrAsInteger,intMinAsIntegerDimintSecAsIntegerDimsngHAsSingleDimvntBlack,vntGrayIfblnBeginFlag=TrueThen86 DrawClock‘调用画表盘函数EndIfCurrentX=0.35*sngRClock+3320CurrentY=80+400+600PrintWeekdayName(Weekday(Now))‘输出星期CurrentX=-0.32*sngRClock+3610CurrentY=0.4*sngRClock-100+550+600PrintYear(Date)&"年"‘输出年CurrentX=-0.32*sngRClock+3590CurrentY=-0.4*sngRClock+450+600PrintMonth(Date)&"月"&Day(Date)&"日"‘输出月日intHr=Hour(Now)intHr=intHrMod12intMin=Minute(Now)DrawWidth=2vntBlack=vbBlackIfblnBeginFlag=TrueThenDrawMode=13sngH=intHr*5+intMin/12intX=sngHLen*Sin(sngH*pi/30)intY=sngHLen*Cos(sngH*pi/30)intPreHr=intHr‘画时针Line(3550,400+600)-(intX+3550,intY+400+600),vntBlackintX=sngMLen*Sin(intMin*pi/30)intY=sngMLen*Cos(intMin*pi/30)‘画分针Line(3550,400+600)-(intX+3550,intY+400+600),vntBlackintPreMin=intMinEndIfIfintPreMin<>intMinThenDrawMode=10‘判断分钟是否改变86 sngH=intPreHr*5+intPreMin/12intX=sngHLen*Sin(sngH*pi/30)intY=sngHLen*Cos(sngH*pi/30)‘擦除旧时针Line(3550,400+600)-(intX+3550,intY+400+600),RGB(0,0,0)intX=sngMLen*Sin(intPreMin*pi/30)intY=sngMLen*Cos(intPreMin*pi/30)‘擦除旧分针Line(3550,400+600)-(intX+3550,intY+400+600),RGB(0,0,0)DrawMode=13sngH=intHr*5+intMin/12intX=sngHLen*Sin(sngH*pi/30)intY=sngHLen*Cos(sngH*pi/30)intPreHr=intHr‘绘制新时针Line(3550,400+600)-(intX+3550,intY+400+600),vntBlackintX=sngMLen*Sin(intMin*pi/30)intY=sngMLen*Cos(intMin*pi/30)‘绘制新分针Line(3550,400+600)-(intX+3550,intY+400+600),vntBlackintPreMin=intMinEndIfintSec=Second(Now)‘取得当前时间秒信息intX=sngSLen*Sin(intSec*pi/30)intY=sngSLen*Cos(intSec*pi/30)DrawWidth=1DrawMode=10vntGray=QBColor(8)‘擦除旧秒针,绘制新秒针Line(3550,400+600)-(intPreX+3550,intPreY+400+600),vntGrayLine(3550,400+600)-(intX+3550,intY+400+600),vntGrayintPreX=intXintPreY=intYblnBeginFlag=False86 EndSubPrivateSubTimer4_Timer()"绘制1号电机扇叶DrawMode=13FillStyle=0FillColor=&H80000005"画背景圆Circle(-2500,-1800),600,&H80000005x1z=x1z-x1z1FillColor=QBColor(10)Ifx1z>-1.001Then"画扇形Circle(-2500,-1800),550,QBColor(10),-0.001+x1z,-1.05+x1zCircle(-2500,-1800),550,QBColor(10),-2.1+x1z,-3.15+x1zCircle(-2500,-1800),550,QBColor(10),-4.2+x1z,-5.25+x1zElseIfx1z>-2ThenCircle(-2500,-1800),550,QBColor(10),-0.001+x1z,-1.05+x1zCircle(-2500,-1800),550,QBColor(10),-2.1+x1z,-3.15+x1zCircle(-2500,-1800),550,QBColor(10),-4.2+x1z,-5.25+x1z+6.28Else:x1z=0Circle(-2500,-1800),550,QBColor(10),-0.001,-1.05Circle(-2500,-1800),550,QBColor(10),-2.1,-3.15Circle(-2500,-1800),550,QBColor(10),-4.2,-5.25EndIfEndSubPrivateSubTimer5_Timer()"绘制2号电机扇叶DrawMode=13FillStyle=0FillColor=&H80000005"画背景圆Circle(100,-1800),600,&H80000005x2z=x2z-x2z2FillColor=QBColor(10)86 Ifx2z>-1.001Then"画扇形Circle(100,-1800),550,QBColor(10),-0.001+x2z,-1.05+x2zCircle(100,-1800),550,QBColor(10),-2.1+x2z,-3.15+x2zCircle(100,-1800),550,QBColor(10),-4.2+x2z,-5.25+x2zElseIfx2z>-2ThenCircle(100,-1800),550,QBColor(10),-0.001+x2z,-1.05+x2zCircle(100,-1800),550,QBColor(10),-2.1+x2z,-3.15+x2zCircle(100,-1800),550,QBColor(10),-4.2+x2z,-5.25+x2z+6.28Else:x2z=0Circle(100,-1800),550,QBColor(10),-0.001,-1.05Circle(100,-1800),550,QBColor(10),-2.1,-3.15Circle(100,-1800),550,QBColor(10),-4.2,-5.25EndIfEndSub86 86'