基于MAXQ3120微控制器的电表(EM)参考设计
MAXQ3120电表(EM)参考设计构建了一款多功能、多费率电表,它符合世界范围的全部可用标准。参考设计构成了一款能够适合各地要求和各种性能要求的电表原型。这篇文档将指导软件工程师,通过定制代码实现一些特殊的需求。
目标读者
本文档假定读者熟悉C语言、MAXQ20微控制器架构以及汇编语言。读者也需熟知全电子式电表的基理。
工具
电表参考设计采用IAR Embedded Workbench工具进行编译。为便于将软件移植到其它开发环境中,除了一种例外情况外,整个软件避免了与IAR相关的语言特性。这种例外情况位于汇编语言文件中,其中包括了一些对标准汇编伪指令集的特定IAR扩展。这些特定IAR扩展命令,不仅可告知连接器各不同段的分配情况,而且告知调试器有关某些机器资源的变化情况。在其它开发环境下构建工程,可将这些伪指令去除。
高层硬件描述
硬件的核心器件是MAXQ3120微控制器。MAXQ3120几乎囊括了实现多功能、多费率电表所需要的所有功能,这些功能包括:双通道、高精度A/D转换器(ADC),一个乘法累加器(MAC),通信端口和一个显示控制器。完成一个电表设计,仅需要少量的外部元件。
在参考设计中,提供两个通信通道:一路红外通道,包含一个可解码38kHz载波频率的接收模块和一个直接由微控制器驱动的红外LED,一路完全隔离的RS-485通道;用作非易失存储器的128kb I2C EEPROM;一个可视LED和一路隔离光耦通道,用于指示电表脉冲;一个用于设置网络地址的按钮;和一个用于显示的LCD。
这种硬件构成预示着以下一些应用信息。选择一个外置I2C EEPROM,意味着系统中必须包含I2C软件,而不提供硬件I2C主机。电表脉冲硬件意味着软件必须能够产生极为精确的脉冲定时。两路通信端口表明,微控制器有限的资源要被两路通道所共享。
软件系统综述
软件系统必须同时跟踪多个进程。首先也是最重要的一点,软件系统必须监测ADC,计算用电量并报告其它额外信息,这些信息包括RMS电压和电流、功率因数和峰值功率。这个基本进程非常关键,其它任何进程都不能干扰这个最重要的基础任务。在持续监视用电量的同时,软件还必须驱动显示、监视两路通信端口、监视按钮以及电力线路上的电源失效事件,完成从外部EEPROM获取信息的请求,并跟踪费率时段的变化。
任务管理方式
初始一看,要完成以上多个实时任务,迫切需要某种实时操作系统(RTOS)来进行调度管理和资源分配。但进一步分析后,就会发现不用传统RTOS的两个充分理由。
首先,要求即时响应ADC中断。当ADC有可用的采样数据时,必须在48μs内提取该采样数据。并且,当检测到一个过零点时,电源周期处理程序为了在下一个电源周期之前完成执行操作,必须独占CPU资源。(电源周期处理程序将占用CPU运算能力的25%到30%。) 尽管RTOS可以满足这些要求,却不能最有效地利用资源。
其次,用于保存任务上下文的空间非常有限。大多数RTOS都要给每个任务提供一个完整的虚拟处理器,以在其中执行操作,而这需要保存各个任务的上下文。由于仅有256个16位字RAM可供使用,少量任务就会耗尽存储器空间。
所以,本参考设计选择了一个简单的任务轮。在这种配置方式下,任务会被按顺序调用,而每个任务在锁定事件发生时,都要释放CPU的控制权。锁定事件是指所有其它任务都必须等待的事件,它包括:从EEPROM中提取数据,等待一个电源周期或是等待通信通道上的字符。如果当前任务需要等待其它任务完成时才能结束自身任务,这时也会产生一个锁定事件。在任何锁定事件中,任务必须存储它的当前状态并返回任务轮。这种协作式多任务机制,使得一个处理能力相对低些的控制器就能够胜任工作。
任务间的通信是通过一组公共数据结构来完成的,这些数据结构要根据一套严格的规则才允许被修改。这些数据结构中最重要的部分是消息板,当发生某个事件时,一个任务要设置消息板中的一组数据位以通知另一个任务。例如,假设接收到一个消息并将其正确译码,则消息译码器任务会告知另一个需要该消息的任务(比如寄存器管理器)已经收到了消息,并要求第二个任务必须执行某些操作。
缺省任务列表
以下是参考设计中采用的缺省任务列表:
DSP:对应每个电源周期,这个程序会计算电力线路的所有参数,并累加本电源周期的用电量。
串口驱动器:检测两路通信通道的状态,并将第一个发出字符的通道置为“活动”通道。在消息检查器任务确定消息完成或产生超时之前,通道将始终保持活动状态。
消息检查器:验证输入字符串符合协议规范,并在完整接收消息后通知消息译码器。
消息译码器:解释接受到的消息并执行相应的请求操作。
异步事件管理器:执行那些不是按照时间表进行的事件任务,比如峰值检测和电能累计。
时段表管理器:周期性检查时钟,并按照时段表调整费率寄存器的值。
显示管理器:根据时间和其它事件刷新LCD显示。
消息格式器:为消息译码器解释的消息准备回复信息。
消息构建器:接收格式化后的消息并加上用于传输的消息头和消息尾。
寄存器管理器:执行读/写EEPROM操作。
计时管理器:通告按固定时基启动的任务。
负载曲线记录器:被请求时,向EEPROM记入用电量,便于将来报告这些数据。
添加任务
如电表参考设计中所定义,任务是一段单线程代码,它执行电表要求的某项功能,并快速(通常只有几毫秒)返回调用函数。然而,大多数任务都需要比这更长的时间才能完成。比如,在任何合理的速率下发送一个消息都需要多个周期。因此,大多数任务都需要一个状态变量,以便将其分解为数个子任务。
一旦任务编写完成,你就可以在spintaskwheel.c文件的任务列表中加入该调用。注意,你可以将任务加在执行流程的任何位置,并根据你的需要多次频繁调用它。你将发现,DSP任务调用非常频繁,串口驱动器SerialPortDriver任务也被调用了几次。因为要保持电能测量的完整性,DSP任务不允许被搁置数个周期,同时不允许SerialPortDriver任务错过输入字符。
最后,测试你的代码。任务轮循环时,你的新任务将伴随其它任务被调用。
全局变量
由于未使用真正意义上的多任务操作系统,也就意味着不会有编程人员所熟知的、真正意义上的消息传递、信号量或其它机制。通信是通过上文提到的消息板以及一组全局变量实现的,各个任务必须按照严格的规则来设置和读取这些变量信息。这些全局变量列举如下:
g_CommSystEMState: 这个变量包括一组通信通道控制位。具体来说,每个通道包括:一个active (活动)位,用于指明某个特定通道处于活动状态(从而可丢弃到达另一个通道的字符);一个TBE位,用于使闲置通道做好工作准备;以及一个data loss (数据丢失)位,当闲置通道收到字符而另一通道正忙于通信时,该位被置高。
g_TransmitByte; g_ReceiveByte: 分别保存着下一个要传送的字节和最新接收到的字节。
g_CommBuffer: 一个50字节数组,包含刚接收到的消息或要发送的消息。注意系统仅有一个通信缓存。它不仅被两个通信通道所共享,也被发送和接收通道所共享。
g_MeterAddress: 一个包含电表网络地址的6字节数组。初始化时从EEPROM内读取该信息,并存放在RAM中。
g_MessageFormatterData; g_DispFormatterData; g_ScheduleManagerData; g_AEMData; g_LCLRegData: 这些寄存器在寄存器管理器和各种任务间传送数据。例如,一个需要发送的寄存器内容,会被寄存器管理器放入g_MessageFormatterData中。
g_AEMRegisterNeeded; g_DispFormatterRegRequest; g_RequestScheduleManager; g_LCLRegRequest: 这些寄存器里,包含了特定任务需要读或写的寄存器。注意,消息译码器没有全局地址寄存器:寄存器管理器可以智能地从消息缓存中找出这个信息。
g_LCDMode: 包含显示器的模式字节。见下面的显示定制部分。
g_TariffInEffect: 包含当前有效的费率号码。这个函数有自己的全局变量,以便每次累计电能时,无需通过多次EEPROM读操作来确定将采样值存在什么位置。
加入微信
获取电子行业最新资讯
搜索微信公众号:EEPW
或用微信扫描左侧二维码