您的位置:首页 > 其它

P89LPC925单片机串口封装

2014-05-15 11:29 176 查看
先简单说明串口协议的规范:

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);

}

//////////////////////////////////////////////////////////////////////////
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: