[经验]
简化Xmodem协议在MSP430F149上的实现
- /**********************************************************
- 日期:2007-05-21
- 编写:李猛
- 功能:编程实现简化Xmodem协议,为实现标准的Xmodem协议做基础
- 备注:此程序中430为发送方
- 说明:1.程序开始时,会循环等待NAK的到来,只要收到的不是NAK,
- 就会一直等待下去,直到收到了NAK,才开始数据的发送;
- 2.上一轮如果发送的是一组数据,则收到CAN,程序就中止;
- 收到ACK,就发送下一组数据;收到NAK,就发送上一组数据;
- 如果收到的不是上面三种,程序就返回,直到出现三个中的某一个;
- 3.上一轮如果发送的是EOT,收到CAN就中止;收到ACK,就结束程序;
- 收到NAK,就再发送EOT;收到的是其他数据就返回,直到出现三个中的某一个。
- **********************************************************/
- #include <msp430x14x.h>
- #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;
- }
暂无评论,赶紧抢沙发吧