基于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读操作来确定将采样值存在什么位置。
g_PW: 包含当前有效的各个通信通道的口令号码。
g_irTimer; g_rsTimer: 用于计数各个通道口令有效时间的定时器。一旦接收到口令后,它的有效期限是60秒。一个口令的有效时间结束后,g_PW中相关的4位数据就会被清零。
g_LoadCurveUsage; g_LoadCurvePeak; g_LoadCurveTimeStamp: 与负载曲线记录任务相关的变量。g_LoadCurveUsage累计用电量,并会最终报告给负载曲线记录任务。负载曲线记录任务会定
期地将该值写入EEPROM并随后清除该变量。
g_LoadCurvePeak和g_LoadCurveTimeStamp跟踪负载曲线的最大功率值,并记录峰值功率产生的间隔和时间。
AEMState: 包含一组与异步事件相关的变量。当接收到一个设置电表地址消息时,msg_rx标志被置为高。地址设置逻辑电路被激活后,变量timer包含恢复正常显示所需的秒数。DSPState和Register变量跟踪寄存器用电量信息从DSP逻辑传送到用电量报告函数的过程。通常,寄存器变量包括所有用电类型(有功、无功、正功率和负功率等)。
g_new_baud: DL/T 645协议规范提供了一种只改变单个消息波特率的机制。当收到波特率变更请求并得到确认后,下一个消息就会以更高的波特率传送。随后,波特率恢复到正常值(本设计中采用1,200bps)。g_new_baud总是保存下一个消息的波特率。
g_TransmitDelay: 一些RS-485转换器在发送完最后一个字符后会延迟一段固定时间,随后切换回接收模式。因此,当主机传送完一个请求后,它可能会丢失电表发送的前几个字符,因为与主机串口相连的RS-485转换器仍处在发送模式下。这个变量保存了发送状态保持的固定延时,延时结束后主机的RS-485转换器切换回接收模式。
current_temp: 如果引用该变量,它将包含从DS3231 RTC/温度传感器中读出的最新数值。
定制功能
本参考设计符合DL/T 645-多功能、瓦时电表通信协议。但这篇文档不仅仅对通信协议进行说明。DL/T 645确实对一个多功能电表需要执行的操作进行了规定,包括测量、时段管理和报告功能。因此,如果你要选择其它电表协议,你必须替换掉寄存器管理器以及除串口管理器之外的所有消息函数,或者至少对其进行重大修改。修改的细节不在本文讨论范畴内。
本文档将着重讨论三个定制领域:显示定制、寄存器映射定制和DSP函数定制。
显示定制
显示器完全由显示管理器控制。其它任何任务都不会向MAXQ3120的LCD寄存器写入数据。DisplayFormatter.c模块包含了显示管理器及其主要子程序UpdateLCD。
如果你只是想在电表中使用一个不同的LCD模块,则只需修改UpdateLCD。所以我们将从这个模块的定制开始说起。如果你想改变显示信息的类型,你就要修改DisplayManager,并且可能需要给电表的其它部分提供额外的钩子(hook)函数。
定制UpdateLCD
UpdateLCD接收两个参数:一个待显示的32位数值和一个8位信号指示器数值 。32位显示值包括8个4位数值。因此,UpdateLCD支持8位、7段显示器。注意,MAXQ3120支持112段显示,所以可以定制该程序以支持更大规模的显示器。 如果想用不同的显示器,你需要修改LCDFont结构。它被定义为static const类型。这样定义的结构进行编译和连接后,将驻留在程序空间,而不是数据空间。
LCD空间分配表:
参考 设计 EM 电表 MAXQ3120 控制器 基于 相关文章:
- 参考设计到底都包含了些什么?(12-09)
- 2013年TI 排名前12的电源参考设计(12-09)
- 访问电源参考设计库的众多理由(12-09)
- 信号链基础知识 68:探讨可编程增益放大器驱动参考引脚(01-28)
- Silicon的电源参考方案(12-07)
- 用于多电平逆变器的多载波PWM技术的研究(08-13)