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.2 串口接收数据协议
1. 数据头:包含1个字节,设置为0xFD。
2. 设备地址:包含1个字节,以区别不同的设备。
3. 返回命令头:包含1个字节,命令执行结果。
4. 数据长度:包含1个字节,发送数据的长度N。
5. 数据:实际发送数据N个字节。
6. 校验码:除校验码之外,前面所有数据按字节相加,低8位。
代码的模板如下:
#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);
}
//////////////////////////////////////////////////////////////////////////
1 通讯协议
1.1 串口发送数据协议
1. 数据头:包含1个字节,设置为0xFD。
2. 设备地址:包含1个字节,以区别不同的设备。
3. 发送命令头:包含1个字节,以区别不同命令。
4. 数据长度:包含1个字节,发送数据的长度N。
5. 数据:实际发送数据N个字节
6. 校验码:除校验码之外,前面所有数据按字节相加,取低8位。
数据头 | 设备地址 | 发送命令头 | 数据长度 | 数据 | 校验码 |
1 | 1 | 1 | 1 | N | 1 |
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);
}
//////////////////////////////////////////////////////////////////////////
相关文章推荐
- 像写Windows程序那样写单片机程序之串口的封装
- 单片机C语言 串口传输 结构体
- C#封装的一个串口操作类(可用于Win CE)
- 52单片机串口控制AD转换显示到共阳极数码管
- 单片机中串口如何发送超过8位的数据
- stm32l01系列单片机通过串口编程(ISP)
- 基于opencv的图像分析,PID算法,串口发送,单片机接收,输出脉冲继而控制步进电机转动
- STM32单片机串口下载程序的简单原理和设置
- c8051f320学习,单片机不外乎时钟、IO、串口、USB等外设用法
- android手机通过串口蓝牙透传模块与AVR单片机通信实例。。。蓝牙服务程序案例
- TI MSP430系列单片机串口通信波特率计算方法
- API串口操作封装类(转)
- 单片机程序协助调试方法(一)串口调试(持续更新中)
- [15单片机] STC15F104W开发入门及模拟串口程序
- Rfid通信1-串口模式(附:对串口通讯进行了封装源码及学习资料)
- 单片机 MCU 51 115200 波特率 模拟串口程序
- 单片机C51串口中断接收和发送测试例程(含通信协议的实现)
- 单片机与PC机串口通讯接地问题
- 关于单片机通过串口发送浮点数信息
- 单片机中串口显示数字1至10