先简单说明串口协议的规范:
1 通讯协议
1.1 串口发送数据协议
1. 数据头:包含1个字节,设置为0xFD。
2. 设备地址:包含1个字节,以区别不同的设备。
3. 发送命令头:包含1个字节,以区别不同命令。
4. 数据长度:包含1个字节,发送数据的长度N。
5. 数据:实际发送数据N个字节
6. 校验码:除校验码之外,前面所有数据按字节相加,取低8位。
数据头 |
设备地址 |
发送命令头 |
数据长度 |
数据 |
校验码 |
1 |
1 |
1 |
1 |
N |
1 |
1.2 串口接收数据协议
1. 数据头:包含1个字节,设置为0xFD。
2. 设备地址:包含1个字节,以区别不同的设备。
3. 返回命令头:包含1个字节,命令执行结果。
4. 数据长度:包含1个字节,发送数据的长度N。
5. 数据:实际发送数据N个字节。
6. 校验码:除校验码之外,前面所有数据按字节相加,低8位。
数据头 |
设备地址 |
返回命令头 |
数据长度 |
数据 |
校验码 |
1 |
1 |
1 |
1 |
N |
1 |
代码的模板如下:
#ifndef __UART_232_H
#define __UART_232_H
//////////////////////////////////////////////////////////////////////////
#include "types.h"
#include "REG925.h"
//////////////////////////////////////////////////////////////////////////
//串口控制寄存器
#define UART_MODE1_ENA (SCON = 0x50) //选择模式1,并使能串口
#define BRGEN_CLOSE (BRGCON = 0x00) //波特率发生器关闭
#define BRGEN_OPEN (BRGCON = 0x03) //波特率发生器开启
#define UART_INTEN(x) (ES = (x)) //串口中断使能操作
//波特率
#define BAUTRATE_9600 {BRGR1 = 0x02; BRGR0 = 0xF0;} //
#define BAUTRATE_19200 {BRGR1 = 0x01; BRGR0 = 0x70;}
//////////////////////////////////////////////////////////////////////////
#define UART_STAT_IDLE 0 //空闲
#define UART_STAT_REC 1 //接收
#define UART_STAT_PARSE 2 //解析
#define UART_STAT_ACK 3 //响应
//////////////////////////////////////////////////////////////////////////
typedef struct UART_STAT_bit
{
U8 RecCnt: 5; //接收字节计数
U8 Stat: 2; //状态
U8 Res: 1; //保留
U8 SndCnt: 5; //发送字节计数
U8 Debug: 1; //调试标志 1:调试 0:正常
U8 ISP: 1; //进入ISP
U8 Reboot: 1; //重启
}UART_STAT_bit;
typedef union UART_STAT
{
UART_STAT_bit stat;
U16 all;
}UART_STAT;
//////////////////////////////////////////////////////////////////////////
extern void UART232_Init(void);
extern void UART232_Debug(U8 ucDebug);
extern void UART232_ISP();
extern void UART232_Reboot();
extern U8 UART232_ACK(U8 ucCmd);
extern void UART232_Run(void);
extern U8 UART232_GetState(UART_STAT* pUARTStat);
//////////////////////////////////////////////////////////////////////////
#endif//__UART_232_H
实现文件:
#include "UART232.h"
///////////////////////////////////////////////////////////////////////////
UART_STAT m_UARTStat;
U32 m_ulUARTTime;
U8 m_ucUARTBuf[UART_BUF_SIZE];
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void (*ExIsp)(void) = 0x1e46; //ISP指针函数
//////////////////////////////////////////////////////////////////////////
//初始化串口
void UART232_Init(void)
{
SSTAT = 0; //使能双缓冲区
UART_MODE1_ENA; //选择模式1,并使能串口
BRGEN_CLOSE; //波特率发生器关闭
BAUTRATE_9600; //设置波特率为9600
BRGEN_OPEN; //波特率发生器开启
UART_INTEN(1); //串口中断使能
m_ulUARTTime = g_ulCurTickCount;
m_UARTStat.all = 0;
}
//串口中断接收
void UART_INT (void) interrupt 4
{
ES = 0; //关闭串口中断
//发送中断
if(TI)
{
m_UARTStat.stat.SndCnt++;
if ( m_UARTStat.stat.SndCnt >= FRAME_TOTAL_SIZE(m_ucUARTBuf[FRAME_O_LEN]) )
{
// memset(m_ucUARTBuf, 0, sizeof(m_ucUARTBuf));
m_UARTStat.stat.Stat = UART_STAT_IDLE;
m_UARTStat.stat.SndCnt = 0;
m_UARTStat.stat.RecCnt = 0;
}
else
{
SBUF = m_ucUARTBuf[m_UARTStat.stat.SndCnt];
m_UARTStat.stat.Stat = UART_STAT_ACK;
}
TI = 0;
}
else if(RI) //接收中断
{
RI = 0;
if(m_UARTStat.stat.Stat == UART_STAT_IDLE)
{
if(SBUF == FRAME_HEAD)
{
m_ucUARTBuf[FRAME_O_HEAD] = SBUF;
m_UARTStat.stat.RecCnt = 1;
m_UARTStat.stat.Stat = UART_STAT_REC;
}
}
else if(m_UARTStat.stat.Stat == UART_STAT_REC)
{
m_ucUARTBuf[m_UARTStat.stat.RecCnt] = SBUF;
if(FRAME_O_LEN == m_UARTStat.stat.RecCnt)
{
if(m_ucUARTBuf[FRAME_O_LEN] >= UART_BUF_SIZE - FRAME_SIZE)
m_UARTStat.stat.Stat = 0;
}
m_UARTStat.stat.RecCnt++;
if ( m_UARTStat.stat.RecCnt > FRAME_O_LEN && m_UARTStat.stat.RecCnt >= m_ucUARTBuf[FRAME_O_LEN] + FRAME_SIZE )
{
m_UARTStat.stat.Stat = UART_STAT_PARSE;
}
}
m_ulUARTTime = g_ulCurTickCount;
}
ES = 1; //打开串口中断
}
void UART232_Run(void)
{
if(m_UARTStat.stat.Stat == UART_STAT_REC || m_UARTStat.stat.Stat == UART_STAT_ACK)
{
if ( (g_ulCurTickCount > (m_ulUARTTime + UART_OVERTIME)) || (g_ulCurTickCount + TICK_PASS_MS < m_ulUARTTime) )
{
m_UARTStat.stat.Stat = UART_STAT_IDLE;
m_UARTStat.stat.SndCnt = 0;
m_UARTStat.stat.RecCnt = 0;
}
}
switch(m_UARTStat.stat.Stat)
{
case UART_STAT_IDLE://空闲
{
if(m_UARTStat.stat.ISP)
{//进入ISP
ISP_Ready(); //作准备
ExIsp();
}
if(m_UARTStat.stat.Reboot)
{//软复位
AUXR1 |= 0x08; //软复位
}
}
break;
case UART_STAT_REC:
break;
case UART_STAT_ACK://响应
{
if ( m_UARTStat.stat.SndCnt >= FRAME_TOTAL_SIZE(m_ucUARTBuf[FRAME_O_LEN]) )
{
m_UARTStat.stat.Stat = UART_STAT_IDLE;
m_UARTStat.stat.SndCnt = 0;
m_UARTStat.stat.RecCnt = 0;
}
}
break;
case UART_STAT_PARSE://解析
default:
{
U8 ucErr;
ucErr = UnpackageFrame(m_ucUARTBuf, m_UARTStat.stat.RecCnt, g_byDevAddr);
if( ucErr == COM_OK)
{//执行相应的命令操作
ucErr = ParseCmd(m_ucUARTBuf);
if(ucErr == ERR_COM_DEBUG)
{//不在调试模式下,且命令不允许执行,则不返回命令
m_UARTStat.all = 0;
return;
}
}
else if(ucErr == ERR_COM_ADDR)
{ //地址不匹配,不响应
m_UARTStat.all = 0;
return;
}
else
{//返回相应错误原因
m_ucUARTBuf[FRAME_O_CMD] = ucErr;
m_ucUARTBuf[FRAME_O_LEN] = 0;
}
PackageFrame(m_ucUARTBuf, m_ucUARTBuf[FRAME_O_LEN], g_byDevAddr);
m_UARTStat.stat.SndCnt = 0;
m_UARTStat.stat.Stat = UART_STAT_ACK;
m_ulUARTTime = g_ulCurTickCount;
SBUF = m_ucUARTBuf[m_UARTStat.stat.SndCnt];
}
break;
}
}
void UART232_Debug(U8 ucDebug)
{
m_UARTStat.stat.Debug = ucDebug;
}
void UART232_ISP()
{
m_UARTStat.stat.ISP = 1;
}
void UART232_Reboot()
{
m_UARTStat.stat.Reboot = 1;
}
U8 UART232_ACK(U8 ucCmd)
{
U8 ucRet = OK;
if(m_UARTStat.stat.Debug)
return ucRet;
switch(ucCmd)
{
case CMD_ISP: //进入ISP
case CMD_UARTDEBUG: //设置串口调试模式
case CMD_SOFTWAREVER: //获取软件版本号
case CMD_HARDWAREVER: //获取硬件版本号
case CMD_GETDEVADDR: //获取设备地址
case CMD_GETDEVSN: //获取序列号
case CMD_MODULEINFO: //获取模块信息
ucRet = OK;
break;
case CMD_REBOOT: //重启操作
case CMD_SOFTTRIG: //软触发
case CMD_READPARAM: //读取参数
case CMD_SAVEPARAM: //保存参数
case CMD_RECOVERPARAM: //恢复出厂参数
case CMD_EXPOSEPLUS: //设置曝闪脉宽
case CMD_EXPOSEPLUSLIMIT: //设置曝闪脉宽阈值
case CMD_WORDMODE: //设置模式参数
case CMD_FLASHPLUS: //设置频闪脉宽
case CMD_FLASHPLUSLIMIT: //设置频闪脉宽阈值
case CMD_FLASHADDPLUS: //设置加频脉宽
case CMD_FLASHADDPLUSLIMIT: //设置加频脉宽阈值
case CMD_EXPOSEDELAY: //设置曝闪延时
case CMD_LIGHTENA: //设置光敏使能
case CMD_FLASHENA: //加频使能
case CMD_KEEPLIMIT: //保护参数
case CMD_SETDEVADDR: //设置设备地址
case CMD_SETDEVSN: //设置序列号
default:
ucRet = ERR_COM_DEBUG;
break;
}
return ucRet;
}
U8 UART232_GetState(UART_STAT* pUARTStat)
{
pUARTStat->all = m_UARTStat.all;
return sizeof(UART_STAT);
}
//////////////////////////////////////////////////////////////////////////