⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uart.c

📁 RS232+485+USB+nRF2401,该程序主要是nRF2401在各种通讯接口的应用
💻 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 + -