?? zlg500commu.c
字號(hào):
#include <string.h>
#include "zlg500Commu.h"
#include "UART0.h"
#include "zlg500.h"
// zlg500模塊的I2C地址
#define I2C_ADDR 0xB2
// 通信幀各字段在幀內(nèi)的位置(以字節(jié)為單位)
enum FrameFieldPosition
{
FFP_FRAME_LEN = 0, // 整個(gè)幀數(shù)據(jù)的總長(zhǎng)度
FFP_CMD_TYPE = 1, // 命令類型,與幀號(hào)位于同一字節(jié),占用低4位
FFP_SEQ = 1, // 幀號(hào),與命令類型位于同一字節(jié),占用高4位
FFP_CMD_CODE = 2, // 命令碼,主機(jī)發(fā)送時(shí)為命令字段
FFP_STATUS = 2, // 狀態(tài)碼,從機(jī)回應(yīng)幀為狀態(tài)字段
FFP_INFO_LEN = 3, // 信息長(zhǎng)度
FFP_INFO = 4, // 信息
FFP_BCC = 4, // 校驗(yàn)碼,當(dāng)幀內(nèi)沒(méi)有信息字段時(shí)的位置
FFP_FRAME_END = 5 // 幀結(jié)束,當(dāng)幀內(nèi)沒(méi)有信息字段時(shí)的位置
};
#define PROTOCOL_LEN 6 // 除信息字段外幀協(xié)議各部分的總長(zhǎng)度
#define STX 0x20 // 開(kāi)始符
#define ETX 0x03 // 結(jié)束符
#define ACK 0x06 // 應(yīng)答
#define NAK 0x15 // 無(wú)應(yīng)答
static uint8 g_SEQ = 0; // 幀號(hào)
// 設(shè)置波特率
static uint8 SetBaudrate()
{
int i, j;
uint8 nData;
for (i = 0; i < 3; i++)
{
// 發(fā)送一個(gè)開(kāi)始符,隔至少60us后再發(fā)送一個(gè),最后看是否能
// 接收到應(yīng)答字符,如能模塊的波特率即同步成功,否則失敗。
nData = STX;
UART0_Send(&nData, 1);
for (j = 2000; j > 0; j--); // 延時(shí)至少60us
UART0_Send(&nData, 1);
if (UART0_Receive(&nData, sizeof(nData)) != 0 || nData == ACK)
{
return TRUE;
}
else
{
continue;
}
}
return FALSE;
}
// 計(jì)算校驗(yàn)碼,對(duì)各數(shù)據(jù)異或,最后取反
uint8 CheckSum(const void *pData, uint8 nDataLen)
{
const uint8 *_pData = (const uint8 *) pData;
uint8 nCheckSum = 0; // 校驗(yàn)碼
while (nDataLen-- > 0)
{
nCheckSum ^= *_pData++;
}
return ~nCheckSum;
}
// 初始化與ZLG500模塊的通信
uint8 ZLG500_COM_Init(void)
{
// 初始化UART通信
UART0_Init(BAUDRATE, UART_DEFAULT_CFG);
// 設(shè)置ZLG500模塊的波特率
return SetBaudrate();
}
// 發(fā)送數(shù)據(jù)到ZLG500模塊
BOOL ZLG500_COM_Send(uint8 nCommType, uint8 nCommCode, const void *pInfo, uint8 nInfoLen)
{
uint8 SendBuf[40]; // 發(fā)送緩沖區(qū)
if (nInfoLen + PROTOCOL_LEN > sizeof(SendBuf))
{
return FALSE;
}
// 幀號(hào)在0~15范圍內(nèi)循環(huán)加1
if (++g_SEQ > 15)
{
g_SEQ = 0;
}
// 組裝數(shù)據(jù)
SendBuf[FFP_FRAME_LEN] = nInfoLen + PROTOCOL_LEN; // 幀長(zhǎng)
SendBuf[FFP_SEQ] = (g_SEQ << 4) | nCommType; // 幀號(hào)(高4位)/ 命令類型(低4位)
SendBuf[FFP_CMD_CODE] = nCommCode; // 命令碼
SendBuf[FFP_INFO_LEN] = nInfoLen; // 信息長(zhǎng)度
memcpy(&SendBuf[FFP_INFO], pInfo, nInfoLen); // 信息
SendBuf[FFP_BCC + nInfoLen] = CheckSum(SendBuf, SendBuf[FFP_FRAME_LEN] - 2); // 校驗(yàn)碼
SendBuf[FFP_FRAME_END + nInfoLen] = ETX;
// 發(fā)送數(shù)據(jù)
UART0_Send(SendBuf, SendBuf[FFP_FRAME_LEN]);
return TRUE;
}
// 從ZLG500模塊接收數(shù)據(jù)
BOOL ZLG500_COM_Receive(uint8 *pCommType, uint8 *pStatus, void *pInfoBuf, uint8 nBufSize, uint8 *pRecvInfoLen)
{
uint8 ReceiveBuf[40]; // 接收緩沖區(qū)
// 接收數(shù)據(jù)
uint32 nRecvLen = UART0_Receive(ReceiveBuf, sizeof(ReceiveBuf));
// 檢驗(yàn)各字段的合法性
// 檢驗(yàn)總數(shù)據(jù)長(zhǎng)度
if (nRecvLen < PROTOCOL_LEN)
{
return FALSE;
}
// 檢驗(yàn)幀數(shù)據(jù)長(zhǎng)度
if (ReceiveBuf[FFP_FRAME_LEN] != nRecvLen)
{
return FALSE;
}
// 檢驗(yàn)幀信息長(zhǎng)度
if (ReceiveBuf[FFP_INFO_LEN] != nRecvLen - PROTOCOL_LEN)
{
return FALSE;
}
// 檢驗(yàn)幀結(jié)束符
if (ReceiveBuf[nRecvLen - 1] != ETX)
{
return FALSE;
}
// 檢驗(yàn)幀號(hào)
if ((ReceiveBuf[FFP_SEQ] >> 4) != g_SEQ)
{
return FALSE;
}
// 檢驗(yàn)校驗(yàn)碼
if (ReceiveBuf[FFP_BCC + ReceiveBuf[FFP_INFO_LEN]] != CheckSum(ReceiveBuf, ReceiveBuf[FFP_FRAME_LEN] - 2))
{
return FALSE;
}
// 檢驗(yàn)信息緩沖區(qū)是否足夠大
if (nBufSize < ReceiveBuf[FFP_INFO_LEN])
{
return FALSE;
}
// 解裝數(shù)據(jù)
*pCommType = ReceiveBuf[FFP_CMD_TYPE] & 0x0F; // 命令類型
*pStatus = ReceiveBuf[FFP_CMD_CODE]; // 狀態(tài)碼
memcpy(pInfoBuf, &ReceiveBuf[FFP_INFO], ReceiveBuf[FFP_INFO_LEN]); // 信息
*pRecvInfoLen = ReceiveBuf[FFP_INFO_LEN]; // 信息長(zhǎng)度
return TRUE;
}
// 發(fā)送命令并接收回應(yīng),此函數(shù)是ZLG500_COM_Send()和ZLG500_COM_Receive()兩函數(shù)的結(jié)合。
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;
}
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -