引言
随着电子技术、通信技术的发展,仪表行业取得了快速的发展,而全球又缺乏统一的协议标准,例如目前我国主要的电表抄表协议是DLT614(多功能电表通信协议),而欧洲的主要标准是MBUS。为了统一全球的抄表协议,IEEE又推出了IEC62056抄表协议[13]。为了适应不同国家和地区的抄表协议,有时同一块仪表需要内置几种通信协议;但是目前大部分单片机只有两个串口,因此如何使用有限的串口来支持多种通信协议成为设计的难点。针对这个问题,本文设计了一种支持多协议的串口程序,对程序设计流程做了详细的阐述[45]。
1 支持多协议的智能仪表软件架构
支持多协议的智能仪表软件架构如图1所示,支持多协议的智能仪表软件构架分为3层:物理层、通信协议层和应用层。物理层主要包括物理层数据实体和物理层管理实体,物理层数据实体主要实现串口数据的收发,物理层管理实体主要实现串口的配置、通信协议在串口发送列表中的注册和通信协议在串口接收列表中的注册。物理层通过物理层数据实体服务接口(PDSAP)和物理层管理实体服务接口(PLMESAP)为通信协议层提供数据服务和管理服务[67]。通信协议层主要实现对从物理层接收的数据帧和命令帧按照通信协议的帧格式进行解析,以及对从应用层接收到的数据和命令按照通信协议的帧格式进行组帧。应用层主要实现智能电表和抄表客户端应用对象之间的通信[810]。

图1 支持多协议的智能仪表软件架构
2 串口发送和接收协议列表
系统初始化时,每个通信协议都需要在串口接收协议列表注册,将自己注册到单个串口或者同时注册到多个串口。当某个通信协议需要从串口发送消息时,需要在串口发送协议列表中注册。其中串口发送协议列表和串口接收协议列表如下:
UartTxNode UartTxList[UART_MAX_NUM];//串口发送协议列表
UartRxNode UartRxList[UART_MAX_NUM];//串口接收协议列表
其中,UartTxNode的结构体如下:
typedef struct {
uint8channel;
uint8* Tx _Pdata;
uint8Tx_len;
uint8Status;
void(*Uart_Tx)(uint8 channel);
} UartTxNode;
其中,channel为通信协议注册的串口号;*Tx_Pdata为所要发送数据的指针;Tx_len为所要发送数据的长度;Status为当前串口的状态;Uart_Tx为串口的发送回调函数,当所有需要发送数据发送完成后,调用该函数来改变串口状态和对通信协议层进行响应。串口的发送状态包括空闲、忙、发送等待。
其中UartRxNode的结构体如下:
typedef struct {
uint8channel;
void (*Uart_Rx)(uint8 channel,uint8 Data);
} UartRxNode;
其中,channel为通信协议注册的串口号;Uart_Rx为串口的接收回调函数,每接收一个字节都会调用该函数一次。
3 支持多协议的串口程序设计
3.1 支持多协议的串口接收程序设计
对于支持多协议的串口接收程序设计以物理串口1为例,串口1的接收中断流程图如图2所示。
设UartRxList(串口接收协议列表)数组元素的标号为 i。当串口1接收到一个字节后,首先设i=0并在UartRxList[i]中搜索已经注册过通信协议,如果UartRxList[i].channel_ID和串口1的串口号相同,那么调用UartRxList[i].Uart_Rx(接收回调函数),在接收回调函数中对接收的字节进行判断,判断该字节是否符合该通信协议的帧格式,如果符合那么将该字节写入该协议的接收缓冲区中,如果不符合则将该字节丢弃。然后设置i=i+1,重复上述过程,直到 i等于UART_MAX_NUM,退出中断程序。
通过这种搜索方式对每个串口接收的字节进行判断,判断其属于哪个通信协议,实现支持多协议的串口数据接收。
3.2 支持多协议的串口发送程序设计
对于支持多协议的串口发送程序设计以物理串口1为例,当某个通信协议需要从串口1发送消息时分为3个步骤:
① 首先将该消息以及相关信息注册到串口发送协议列表中,其中注册过程为:首先搜索当前串口发送协议列表UartTxList中处于空闲状态的通道i;如果通道i处于空闲状态则将发送的消息以及相关信息填充到UartTxNode结构体中;将当前通道i的Status置为发送等待状态。

图2 物理串口1接收中断流程图
② 注册完成后进入串口发送程序,串口1的数据发送程序如图3所示。设串口发送协议列表UartTxList数组元素的标号为i。当串口1接收到一个字节后,首先设i=0并搜索在UartTxList[i](串口发送协议列表)中已经注册过的消息,如果UartTxList[i].channel_ID和串口1的串口号相同,那么首先将UartTxList[i].Tx _Pdata所指向消息的第一个字节通过串口1发送出去;然后发送长度减1,UartTxList[i].Status置为忙,UartTxList[i].Tx_Pdata加1。当发送完一个字节后进入串口1发送中断服务程序,所有UartTxList[i]. Tx_Pdata所指向消息后续字节的发送都在发送中断服务程序中完成。

图3 物理串口1发送消息流程图
③ 发送中断流程图如图4所示,主要完成后续字节的发送。

图4 物理串口1发送中断流程图
由于步骤②只发送了消息的第1个字节,就进入发送中断程序,所有后续字节的发送都在中断程序中完成。当进入串口1发送中断服务程序后,首先读出步骤②中的UartTxList[i],然后判断UartRxList[i].channel_ID是否等于串口1且UartRxList[i].Status是否为忙。如果是则判断剩余发送长度是否为0;如果不是则继续发送一个字节的消息,然后再进入发送中断。如果是则说明该消息已经发送完毕,将UartRxList[i].Status置为空闲,再转入步骤②(即跳入串口1发送消息程序入口)来查看串口发送协议列表UartTxList是否有其他消息需要发送。
通过以上3个步骤实现了支持多协议的串口数据发送。几个通信协议可以同时通过串口1发送消息,它们首先会在串口发送协议列表中注册消息,串口1会根据消息注册的先后顺序,待串口空闲后,依次从串口1中发送出去。
结语
文章针对智能仪表串口程序设计存在的问题,阐述了设计支持多协议的串口程序的必要性。给出了支持多协议的智能仪表软件构架、支持多协议的串口程序设计流程图。它可以解决目前智能仪表通信协议的多样性与单片机串口数量有限之间的冲突。提高了智能仪表对不同通信协议的兼容性。该方案可以广泛地应用于智能仪表行业,推动我国仪表行业的发展和国际化。