📄 zlg500commu.c
字号:
#include <string.h>
#include "zlg500Commu.h"
#include "UART0.h"
#include "zlg500.h"
// zlg500模块的I2C地址
#define I2C_ADDR 0xB2
// 通信帧各字段在帧内的位置(以字节为单位)
enum FrameFieldPosition
{
FFP_FRAME_LEN = 0, // 整个帧数据的总长度
FFP_CMD_TYPE = 1, // 命令类型,与帧号位于同一字节,占用低4位
FFP_SEQ = 1, // 帧号,与命令类型位于同一字节,占用高4位
FFP_CMD_CODE = 2, // 命令码,主机发送时为命令字段
FFP_STATUS = 2, // 状态码,从机回应帧为状态字段
FFP_INFO_LEN = 3, // 信息长度
FFP_INFO = 4, // 信息
FFP_BCC = 4, // 校验码,当帧内没有信息字段时的位置
FFP_FRAME_END = 5 // 帧结束,当帧内没有信息字段时的位置
};
#define PROTOCOL_LEN 6 // 除信息字段外帧协议各部分的总长度
#define STX 0x20 // 开始符
#define ETX 0x03 // 结束符
#define ACK 0x06 // 应答
#define NAK 0x15 // 无应答
static uint8 g_SEQ = 0; // 帧号
// 设置波特率
static uint8 SetBaudrate()
{
int i, j;
uint8 nData;
for (i = 0; i < 3; i++)
{
// 发送一个开始符,隔至少60us后再发送一个,最后看是否能
// 接收到应答字符,如能模块的波特率即同步成功,否则失败。
nData = STX;
UART0_Send(&nData, 1);
for (j = 2000; j > 0; j--); // 延时至少60us
UART0_Send(&nData, 1);
if (UART0_Receive(&nData, sizeof(nData)) != 0 || nData == ACK)
{
return TRUE;
}
else
{
continue;
}
}
return FALSE;
}
// 计算校验码,对各数据异或,最后取反
uint8 CheckSum(const void *pData, uint8 nDataLen)
{
const uint8 *_pData = (const uint8 *) pData;
uint8 nCheckSum = 0; // 校验码
while (nDataLen-- > 0)
{
nCheckSum ^= *_pData++;
}
return ~nCheckSum;
}
// 初始化与ZLG500模块的通信
uint8 ZLG500_COM_Init(void)
{
// 初始化UART通信
UART0_Init(BAUDRATE, UART_DEFAULT_CFG);
// 设置ZLG500模块的波特率
return SetBaudrate();
}
// 发送数据到ZLG500模块
BOOL ZLG500_COM_Send(uint8 nCommType, uint8 nCommCode, const void *pInfo, uint8 nInfoLen)
{
uint8 SendBuf[40]; // 发送缓冲区
if (nInfoLen + PROTOCOL_LEN > sizeof(SendBuf))
{
return FALSE;
}
// 帧号在0~15范围内循环加1
if (++g_SEQ > 15)
{
g_SEQ = 0;
}
// 组装数据
SendBuf[FFP_FRAME_LEN] = nInfoLen + PROTOCOL_LEN; // 帧长
SendBuf[FFP_SEQ] = (g_SEQ << 4) | nCommType; // 帧号(高4位)/ 命令类型(低4位)
SendBuf[FFP_CMD_CODE] = nCommCode; // 命令码
SendBuf[FFP_INFO_LEN] = nInfoLen; // 信息长度
memcpy(&SendBuf[FFP_INFO], pInfo, nInfoLen); // 信息
SendBuf[FFP_BCC + nInfoLen] = CheckSum(SendBuf, SendBuf[FFP_FRAME_LEN] - 2); // 校验码
SendBuf[FFP_FRAME_END + nInfoLen] = ETX;
// 发送数据
UART0_Send(SendBuf, SendBuf[FFP_FRAME_LEN]);
return TRUE;
}
// 从ZLG500模块接收数据
BOOL ZLG500_COM_Receive(uint8 *pCommType, uint8 *pStatus, void *pInfoBuf, uint8 nBufSize, uint8 *pRecvInfoLen)
{
uint8 ReceiveBuf[40]; // 接收缓冲区
// 接收数据
uint32 nRecvLen = UART0_Receive(ReceiveBuf, sizeof(ReceiveBuf));
// 检验各字段的合法性
// 检验总数据长度
if (nRecvLen < PROTOCOL_LEN)
{
return FALSE;
}
// 检验帧数据长度
if (ReceiveBuf[FFP_FRAME_LEN] != nRecvLen)
{
return FALSE;
}
// 检验帧信息长度
if (ReceiveBuf[FFP_INFO_LEN] != nRecvLen - PROTOCOL_LEN)
{
return FALSE;
}
// 检验帧结束符
if (ReceiveBuf[nRecvLen - 1] != ETX)
{
return FALSE;
}
// 检验帧号
if ((ReceiveBuf[FFP_SEQ] >> 4) != g_SEQ)
{
return FALSE;
}
// 检验校验码
if (ReceiveBuf[FFP_BCC + ReceiveBuf[FFP_INFO_LEN]] != CheckSum(ReceiveBuf, ReceiveBuf[FFP_FRAME_LEN] - 2))
{
return FALSE;
}
// 检验信息缓冲区是否足够大
if (nBufSize < ReceiveBuf[FFP_INFO_LEN])
{
return FALSE;
}
// 解装数据
*pCommType = ReceiveBuf[FFP_CMD_TYPE] & 0x0F; // 命令类型
*pStatus = ReceiveBuf[FFP_CMD_CODE]; // 状态码
memcpy(pInfoBuf, &ReceiveBuf[FFP_INFO], ReceiveBuf[FFP_INFO_LEN]); // 信息
*pRecvInfoLen = ReceiveBuf[FFP_INFO_LEN]; // 信息长度
return TRUE;
}
// 发送命令并接收回应,此函数是ZLG500_COM_Send()和ZLG500_COM_Receive()两函数的结合。
uint8 ZLG500_COM_SendReceive(uint8 nCommType, uint8 nCommCode,
const void *pSendInfo, uint8 nSendInfoLen,
void *pRecvInfoBuf, uint8 nRecvInfoBufLen)
{
uint8 bResult;
uint8 nStatus;
uint8 nReceiveLen;
ZLG500_COM_Send(nCommType, nCommCode, pSendInfo, nSendInfoLen);
bResult = ZLG500_COM_Receive(&nCommType, &nStatus, pRecvInfoBuf, nRecvInfoBufLen, &nReceiveLen);
if (!bResult)
{
return COMM_ERR;
}
else
{
return nStatus;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -