📄 uart.c
字号:
/*
项目: 人员定位:读卡器
文件: comport.c
日期: 2007.09.12
作者: 邵子扬
说明: 主程序,完成初始化,开始运行,低功耗等
*/
#include <avr/interrupt.h>
#include "common.h"
#define FRAMEHEAD1 0x7E //~
#define FRAMEHEAD2 0x3E //>
#define FRAMETAIL 0x3C //<
#define FRAMEADDR 2 //地址
#define FRAMELENGTH 3 //长度
#define FRAMECMD 4 //命令
#define FRAMEDATA 5 //数据
#define FRAMEBASELEN 7 //数据帧基本长度
uint8 RTflag = 0; //收发状态
// 0 - 接收帧头
// 1 - 接收数据
// 2 - 接收完成
// 3 - 发送数据
uint8 RTlen = 0; //缓冲区长度
uint8 RTptr = 0; //缓冲区指针
uint8 RTBuf[RTBUF_MAX_SIZE]; //收发缓存
uint8 RTptmr; //串口收发保护定时器
uint8 RTSn = 0; //通信流水号
void DataReceive(uint8 dat) //数据接收
{
switch(RTflag)
{
case 0://接收帧头
switch(RTptr)
{
case 0://第一个帧头
if(dat == FRAMEHEAD1)
{
RTBuf[0] = FRAMEHEAD1;
RTptr++;
}
return;
case 1://第二个帧头
if(dat == FRAMEHEAD2)
{
RTBuf[1] = FRAMEHEAD2;
RTptr++;
RTflag = 1;
RTlen = FRAMEBASELEN;//基本帧长度
}
else//重新开始接收
RTptr = 0;
return;
default://错误
RTptr = 0;
}
return;
case 1://接收数据
RTBuf[RTptr] = dat;
RTptr++;
if(RTptr >= RTlen)
{
RTflag = 2; //接收完所有数据
}
else
{
//if(RTptr == (FRAMEADDR + 1))//判断地址
//{
//
//}
if(RTptr == (FRAMELENGTH + 1))//判断长度
{
if(dat > (RTBUF_MAX_SIZE - 6))
{
RTflag = 0;//长度超过限制
RTptr = 0;
return;
}
RTlen = 5 + dat;//设置新长度
}
}
return;
case 2://接收完一帧数据,不在存入缓冲区
return;
case 3://发送中
return;
default:;//其它
RTflag = 0;
RTptr = 0;
return;
}
}
//返回0时,串口发送数据
//否则,不发送数据,直接设置为接收状态
uint8 FrameAnalyse(uint8 *buf) //数据分析
{
uint16 n;
uint8 i;
//检查CRC校验
n = crc_xmodem(buf + 2, buf[FRAMELENGTH] + 1);
//if((buf[buf[FRAMELENGTH] + 3] != (n / 256))||(buf[buf[FRAMELENGTH] + 4] != (n % 256)))
//return 1;
switch(buf[FRAMECMD])
{
case 0x00://查询卡片
//删除
if((buf[FRAMEDATA + 0] == cfg.addr) &&
(buf[FRAMEDATA + 1] == RTSn))
{
cdHead = (cdHead + cdRTNum) % MAX_CARD_NO;
RTSn++;
}
//地址不匹配
if(buf[FRAMEADDR] != cfg.addr)
return 1;
if(cdHead == cdTail) //没有卡片数据
{
buf[FRAMELENGTH] = 4; //返回长度
buf[FRAMEDATA + 0] = RTSn;//流水号
buf[FRAMEDATA + 1] = 0; //数量 = 0
cdRTNum = 0;
}
else
{
if(cdHead > cdTail)
{
n = cdHead + RTBUF_MAX_SIZE - cdTail;
}
else
{
n = cdTail - cdHead;
}
if(n > 15) //一次最多15个卡数据
{
n = 15;
buf[FRAMEDATA + 1] = 0x1F; //数量 = 15
}
else
{
buf[FRAMEDATA + 1] = n;
}
cdRTNum = n; //保存查询的个数
buf[FRAMELENGTH] = n * 5 + 4; //返回长度
buf[FRAMEDATA + 0] = RTSn; //流水号
for(i = 0; i < n; i++)
{
buf[FRAMEDATA + 2 + i*5 + 0] = card[(cdHead + i) % RTBUF_MAX_SIZE].ID / 256;
buf[FRAMEDATA + 2 + i*5 + 1] = card[(cdHead + i) % RTBUF_MAX_SIZE].ID % 256;
buf[FRAMEDATA + 2 + i*5 + 2] = card[(cdHead + i) % RTBUF_MAX_SIZE].time[0];
buf[FRAMEDATA + 2 + i*5 + 3] = card[(cdHead + i) % RTBUF_MAX_SIZE].time[1];
buf[FRAMEDATA + 2 + i*5 + 4] = card[(cdHead + i) % RTBUF_MAX_SIZE].time[2];
}
}
break;
case 0x02://获取配置
return 1;
case 0x10://校准时间
cli();
tmr.day = buf[FRAMEDATA + 0] % 31;
tmr.hour = buf[FRAMEDATA + 1] % 24;
tmr.min = buf[FRAMEDATA + 2] % 60;
tmr.sec = buf[FRAMEDATA + 3] % 60;
sei();
return 1;
default:
return 1;
}
FrameSend(buf);
return 0;
}
void preSend(uint8 *buf) //数据预处理
{
uint16 crc;
buf[0] = FRAMEHEAD1;
buf[1] = FRAMEHEAD2;
buf[2] = cfg.addr;
buf[FRAMECMD] = buf[FRAMECMD] ^ 0x80; //高位取反
crc = crc_xmodem(buf + 2, buf[FRAMELENGTH] + 1);
buf[buf[FRAMELENGTH] + 3] = crc / 256;//CRC校验:高位
buf[buf[FRAMELENGTH] + 4] = crc % 256;// 低位
buf[buf[FRAMELENGTH] + 5] = FRAMETAIL;//帧尾: 0x3C
}
void FrameSend(uint8 *buf) //数据发送
{
preSend(buf);
PORTREG(RS485PORT) |= (1 << RS485TXEn);
RTptr = 1;
RTlen = buf[FRAMELENGTH] + 6;
uart_write(buf[0]);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -