Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1304607
  • 博文数量: 92
  • 博客积分: 10389
  • 博客等级: 上将
  • 技术积分: 1918
  • 用 户 组: 普通用户
  • 注册时间: 2006-08-10 16:13
文章存档

2014年(1)

2012年(15)

2009年(6)

2008年(37)

2007年(72)

2006年(54)

我的朋友

分类: LINUX

2008-04-17 11:04:18

/*
博主说明:此文章收录纯属是从完善本xmodem题目以其系统性考虑。由于下面代码只有发送部分,所以供
读者参考程序设计的框架更有意义。
*/
 
 
 
/**********************************************************
日期:2007-05-21
编写:李猛
功能:编程实现简化Xmodem协议,为实现标准的Xmodem协议做基础
备注:此程序中430为发送方
说明:1.程序开始时,会循环等待NAK的到来,只要收到的不是NAK,
           就会一直等待下去,直到收到了NAK,才开始数据的发送;
             2.上一轮如果发送的是一组数据,则收到CAN,程序就中止;
          收到ACK,就发送下一组数据;收到NAK,就发送上一组数据;
          如果收到的不是上面三种,程序就返回,直到出现三个中的某一个;
             3.上一轮如果发送的是EOT,收到CAN就中止;收到ACK,就结束程序;
          收到NAK,就再发送EOT;收到的是其他数据就返回,直到出现三个中的某一个。
**********************************************************/

 
 
 
 
 
#include

#define uchar unsigned char

#define NAK 0x15                //Xmodem协议中的术语
#define ACK 0x06
#define CAN 0x18
#define EOT 0x04
#define SOH 0x01

//要发送的数据,即430从此数组中取数据构成数据包,共22字节,分5次发送,最后一次补3个0x1A
uchar FileSend[22] = {0xAA,0xA9,0xA8,0xA7,0xA6,0xA5,0xA4,0xA3,0xA2,0xA1,0xA0,0x9F,0x9E,0x9D,0x9C,0x9B,0x9A,0x99,0x98,0x97,0x96,0x95};
//数据包,长9字节,分别为SOH、包序号、序号补码、5字节数据、校验码
uchar DataSend[9];

uchar Seq = 0x01;                //数据包序号,初值为1
uchar cmpl;                          //数据包序号的补码
uchar csum;                         //垂直累加和校验码,初值为0

uchar rec_PC;                    //收到的PC的确认命令
uchar k = 0;                        //指向FileSend的标号,从中取数据时使用,初值为0
uchar j = 0;                         //指向DataSend的标号,发送数据时使用,初值为0
uchar fin_flag = 0;              //数据取完的标志,为1时表示FileSend中的数据已经取完               
uchar eot_flag = 0;             //发送完成的标志,为1时表示430已经发送过了EOT标志

void Init_CLK();                 //函数声明
void Init_Port();
void Init_UART0();

void main(void)
{  
    WDTCTL = WDTPW + WDTHOLD;     //关闭看门狗
  
    _DINT();                      //关中断
  
    Init_CLK();
    Init_Port();
    Init_UART0();                 //一系列的初始化
  
    _EINT();                      //开中断
  
    while(1);                     //等待:接收中断,功能全在接收中断函数中完成
                                    //主程序只是循环等待
}

/******************时钟初始化函数******************/
void Init_CLK(void)
{
    BCSCTL1=0x00;
    BCSCTL1 += XT2OFF;    //关闭XT2,因为板子上没有
    BCSCTL1 += XTS;       //低速振荡器是高频模式
    BCSCTL2=0x00;
    BCSCTL2 += SELM0;
    BCSCTL2 += SELM1;     //MCLK的时钟源为低速晶体振荡器
                        //此外,ACLK的时钟源为LFTX1,SMCLK的时钟源为DC0CLK
                        //分频因子均为1
}

/******************端口初始化函数******************/
void Init_Port(void)
{
    P3DIR=0;
    P3SEL=0;              //P3所有管脚均初始化为输入方向和一般I/O口
    return;
}

/******************串口初始化函数******************/
void Init_UART0(void)
{
    U0CTL=SWRST;          //串行模块设置时的必须
    U0CTL += CHAR;        //8位数据位,1位停止位,无校验
  
    U0TCTL=0x00;
    U0TCTL += SSEL0;      //波特率时钟源选择为ACLK
  
    U0BR1=0x01;
    U0BR0=0xA0;
    U0MCTL=0xBA;          //设置波特率为9600
  
    U0CTL &= ~SWRST;
  
    ME1 |= UTXE0+URXE0; //使能USART0模块
    IE1 |= URXIE0;        //使能USART0的接收中断
  
    P3SEL |= BIT4+BIT5; //P3.4和P3.5为串口功能
    P3DIR |= BIT4;        //P3.4为输出
  
    return;
}

/******************接收中断函数******************/
#pragma vector=USART0RX_VECTOR
__interrupt void Usart0Rx()
{
    rec_PC = RXBUF0;     //接收到的PC的命令
  
    if (rec_PC == CAN)
    {
      while (1);        //如果接收到CAN命令,则取消传输,程序中止
                      //程序在此处循环,不再跳出中断
    }
  
    if (k == 0)         //k=0表示这是第一次接收PC命令,判断是否是开始传输的标志NAK
    {
      if (rec_PC == NAK) //收到NAK则开始发送第一组数据,收到的不是NAK则返回继续等待NAK
      {
        cmpl = 0xFF - Seq;    //计算包序号补码
        csum = FileSend[k]+FileSend[k+1]+FileSend[k+2]+FileSend[k+3]+FileSend[k+4];
        //计算垂直累加和校验码
      
        DataSend[0] = SOH;
        DataSend[1] = Seq;
        DataSend[2] = cmpl;
        DataSend[3] = FileSend[k];DataSend[4] = FileSend[k+1];DataSend[5] = FileSend[k+2];DataSend[6] = FileSend[k+3];DataSend[7] = FileSend[k+4];
        DataSend[8] = csum;
        //取得数据包
      
        while (j<9)           //发送数据包
        {
          while ((IFG1 & UTXIFG0)==0);
          TXBUF0 = DataSend[j];
          j++;
        }
        k = k+5;             //指向下一组数据
        Seq++;               //数据包序号增1
        j = 0;
        return;              //返回,不在执行下面的语句
      }
    }
  
    if (k != 0)              //k!=0,表示已经发送过了数据包,接收到的是PC对数据包的确认命令
    {
      if (rec_PC == NAK)     //PC发回NAK,则把刚才发送的数据包重新发送一遍
      {
        if (eot_flag == 1) //如果刚才发送的不是数据,而是EOT,则再将EOT重新发送
        {
          while ((IFG1 & UTXIFG0)==0);
          TXBUF0 = EOT;
          eot_flag = 1;
          return;
        }
            
        while (j<9)
        {
          while ((IFG1 & UTXIFG0)==0);
          TXBUF0 = DataSend[j];
          j++;
        }
        j = 0;
      }
      if (rec_PC == ACK)
      {
        if (eot_flag == 1)    //表明刚才发送的是EOT,此时PC发回的ACK是对刚才发送的EOT的确认,程序完成
        {
          while (1);
        }
        else if (fin_flag == 1) //表明刚才发送的是最后一个数据包
                                //此时PC发回的ACK是对刚才发送的最后一个数据包的确认
                                //数据发送完成,发送EOT,返回等待确认
        {
          while ((IFG1 & UTXIFG0)==0);
          TXBUF0 = EOT;
          eot_flag = 1;
        }
        else                //刚才发送的是一组普通的数据,取下一个数据包并发送
        {
          cmpl = 0xFF - Seq;
        
          //判断是否已经发送到了最后一组数据
          if (k==20)
          {
            csum = FileSend[k]+FileSend[k+1]+0x1A+0X1A+0X1A;
        
            DataSend[0] = SOH;
            DataSend[1] = Seq;
            DataSend[2] = cmpl;
            DataSend[3] = FileSend[k];DataSend[4] = FileSend[k+1];DataSend[5] = 0X1A;DataSend[6] = 0X1A;DataSend[7] = 0X1A;
            DataSend[8] = csum;
          
            fin_flag = 1;
          }
          else
          {
            csum = FileSend[k]+FileSend[k+1]+FileSend[k+2]+FileSend[k+3]+FileSend[k+4];
        
            DataSend[0] = SOH;
            DataSend[1] = Seq;
            DataSend[2] = cmpl;
            DataSend[3] = FileSend[k];DataSend[4] = FileSend[k+1];DataSend[5] = FileSend[k+2];DataSend[6] = FileSend[k+3];DataSend[7] = FileSend[k+4];
            DataSend[8] = csum;
          }
        
          while (j<9)
          {
            while ((IFG1 & UTXIFG0)==0);
            TXBUF0 = DataSend[j];
            j++;
          }
          k = k+5;
          Seq++;
          j = 0;
        }
      }
    }

    return;
}

阅读(4184) | 评论(0) | 转发(0) |
0

上一篇:XMODEM transfer protocol

下一篇:avrboot

给主人留下些什么吧!~~