⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zlg500commu.c

📁 SmartARM2400系列开发板全套资料
💻 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 + -