?? 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 + -