P89LPC925单片机串口封装

来源:互联网 发布:在哪里看我的淘宝等级 编辑:程序博客网 时间:2024/05/17 01:51

先简单说明串口协议的规范:

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_bitstat;
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);
}
//////////////////////////////////////////////////////////////////////////








0 0