[经验] 简化Xmodem协议在MSP430F149上的实现

qinkaiabc   2014-2-21 15:27 楼主
  1. /**********************************************************
  2. 日期:2007-05-21
  3. 编写:李猛
  4. 功能:编程实现简化Xmodem协议,为实现标准的Xmodem协议做基础
  5. 备注:此程序中430为发送方
  6. 说明:1.程序开始时,会循环等待NAK的到来,只要收到的不是NAK,
  7.            就会一直等待下去,直到收到了NAK,才开始数据的发送;
  8.              2.上一轮如果发送的是一组数据,则收到CAN,程序就中止;
  9.           收到ACK,就发送下一组数据;收到NAK,就发送上一组数据;
  10.           如果收到的不是上面三种,程序就返回,直到出现三个中的某一个;
  11.              3.上一轮如果发送的是EOT,收到CAN就中止;收到ACK,就结束程序;
  12.           收到NAK,就再发送EOT;收到的是其他数据就返回,直到出现三个中的某一个。
  13. **********************************************************/
  14. #include <msp430x14x.h>

  15. #define uchar unsigned char

  16. #define NAK 0x15                //Xmodem协议中的术语
  17. #define ACK 0x06
  18. #define CAN 0x18
  19. #define EOT 0x04
  20. #define SOH 0x01

  21. //要发送的数据,即430从此数组中取数据构成数据包,共22字节,分5次发送,最后一次补3个0x1A
  22. 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};
  23. //数据包,长9字节,分别为SOH、包序号、序号补码、5字节数据、校验码
  24. uchar DataSend[9];

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

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

  33. void Init_CLK();                 //函数声明
  34. void Init_Port();
  35. void Init_UART0();

  36. void main(void)
  37. {  
  38.     WDTCTL = WDTPW + WDTHOLD;     //关闭看门狗
  39.   
  40.     _DINT();                      //关中断
  41.   
  42.     Init_CLK();
  43.     Init_Port();
  44.     Init_UART0();                 //一系列的初始化
  45.   
  46.     _EINT();                      //开中断
  47.   
  48.     while(1);                     //等待:接收中断,功能全在接收中断函数中完成
  49.                                     //主程序只是循环等待
  50. }

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

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

  70. /******************串口初始化函数******************/
  71. void Init_UART0(void)
  72. {
  73.     U0CTL=SWRST;          //串行模块设置时的必须
  74.     U0CTL += CHAR;        //8位数据位,1位停止位,无校验
  75.   
  76.     U0TCTL=0x00;
  77.     U0TCTL += SSEL0;      //波特率时钟源选择为ACLK
  78.   
  79.     U0BR1=0x01;
  80.     U0BR0=0xA0;
  81.     U0MCTL=0xBA;          //设置波特率为9600
  82.   
  83.     U0CTL &= ~SWRST;
  84.   
  85.     ME1 |= UTXE0+URXE0; //使能USART0模块
  86.     IE1 |= URXIE0;        //使能USART0的接收中断
  87.   
  88.     P3SEL |= BIT4+BIT5; //P3.4和P3.5为串口功能
  89.     P3DIR |= BIT4;        //P3.4为输出
  90.   
  91.     return;
  92. }

  93. /******************接收中断函数******************/
  94. #pragma vector=USART0RX_VECTOR
  95. __interrupt void Usart0Rx()
  96. {
  97.     rec_PC = RXBUF0;     //接收到的PC的命令
  98.   
  99.     if (rec_PC == CAN)
  100.     {
  101.       while (1);        //如果接收到CAN命令,则取消传输,程序中止
  102.                       //程序在此处循环,不再跳出中断
  103.     }
  104.   
  105.     if (k == 0)         //k=0表示这是第一次接收PC命令,判断是否是开始传输的标志NAK
  106.     {
  107.       if (rec_PC == NAK) //收到NAK则开始发送第一组数据,收到的不是NAK则返回继续等待NAK
  108.       {
  109.         cmpl = 0xFF - Seq;    //计算包序号补码
  110.         csum = FileSend[k]+FileSend[k+1]+FileSend[k+2]+FileSend[k+3]+FileSend[k+4];
  111.         //计算垂直累加和校验码
  112.       
  113.         DataSend[0] = SOH;
  114.         DataSend[1] = Seq;
  115.         DataSend[2] = cmpl;
  116.         DataSend[3] = FileSend[k];DataSend[4] = FileSend[k+1];DataSend[5] = FileSend[k+2];DataSend[6] = FileSend[k+3];DataSend[7] = FileSend[k+4];
  117.         DataSend[8] = csum;
  118.         //取得数据包
  119.       
  120.         while (j<9)           //发送数据包
  121.         {
  122.           while ((IFG1 & UTXIFG0)==0);
  123.           TXBUF0 = DataSend[j];
  124.           j++;
  125.         }
  126.         k = k+5;             //指向下一组数据
  127.         Seq++;               //数据包序号增1
  128.         j = 0;
  129.         return;              //返回,不在执行下面的语句
  130.       }
  131.     }
  132.   
  133.     if (k != 0)              //k!=0,表示已经发送过了数据包,接收到的是PC对数据包的确认命令
  134.     {
  135.       if (rec_PC == NAK)     //PC发回NAK,则把刚才发送的数据包重新发送一遍
  136.       {
  137.         if (eot_flag == 1) //如果刚才发送的不是数据,而是EOT,则再将EOT重新发送
  138.         {
  139.           while ((IFG1 & UTXIFG0)==0);
  140.           TXBUF0 = EOT;
  141.           eot_flag = 1;
  142.           return;
  143.         }
  144.             
  145.         while (j<9)
  146.         {
  147.           while ((IFG1 & UTXIFG0)==0);
  148.           TXBUF0 = DataSend[j];
  149.           j++;
  150.         }
  151.         j = 0;
  152.       }
  153.       if (rec_PC == ACK)
  154.       {
  155.         if (eot_flag == 1)    //表明刚才发送的是EOT,此时PC发回的ACK是对刚才发送的EOT的确认,程序完成
  156.         {
  157.           while (1);
  158.         }
  159.         else if (fin_flag == 1) //表明刚才发送的是最后一个数据包
  160.                                 //此时PC发回的ACK是对刚才发送的最后一个数据包的确认
  161.                                 //数据发送完成,发送EOT,返回等待确认
  162.         {
  163.           while ((IFG1 & UTXIFG0)==0);
  164.           TXBUF0 = EOT;
  165.           eot_flag = 1;
  166.         }
  167.         else                //刚才发送的是一组普通的数据,取下一个数据包并发送
  168.         {
  169.           cmpl = 0xFF - Seq;
  170.         
  171.           //判断是否已经发送到了最后一组数据
  172.           if (k==20)
  173.           {
  174.             csum = FileSend[k]+FileSend[k+1]+0x1A+0X1A+0X1A;
  175.         
  176.             DataSend[0] = SOH;
  177.             DataSend[1] = Seq;
  178.             DataSend[2] = cmpl;
  179.             DataSend[3] = FileSend[k];DataSend[4] = FileSend[k+1];DataSend[5] = 0X1A;DataSend[6] = 0X1A;DataSend[7] = 0X1A;
  180.             DataSend[8] = csum;
  181.          
  182.             fin_flag = 1;
  183.           }
  184.           else
  185.           {
  186.             csum = FileSend[k]+FileSend[k+1]+FileSend[k+2]+FileSend[k+3]+FileSend[k+4];
  187.         
  188.             DataSend[0] = SOH;
  189.             DataSend[1] = Seq;
  190.             DataSend[2] = cmpl;
  191.             DataSend[3] = FileSend[k];DataSend[4] = FileSend[k+1];DataSend[5] = FileSend[k+2];DataSend[6] = FileSend[k+3];DataSend[7] = FileSend[k+4];
  192.             DataSend[8] = csum;
  193.           }
  194.         
  195.           while (j<9)
  196.           {
  197.             while ((IFG1 & UTXIFG0)==0);
  198.             TXBUF0 = DataSend[j];
  199.             j++;
  200.           }
  201.           k = k+5;
  202.           Seq++;
  203.           j = 0;
  204.         }
  205.       }
  206.     }

  207.     return;
  208. }


回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复