单片机Ymodem协议C语言,ST官方代码——YModem协议部分代码分析

本文档提供了STM32单片机实现Ymodem协议的相关软件函数,包括接收包、准备初始包和数据包、CRC16校验等功能。通过对源代码的分析,读者可以理解如何在STM32上应用Ymodem协议进行文件传输。
摘要由CSDN通过智能技术生成

/**

******************************************************************************

* @file    IAP_Main/Src/ymodem.c

* @author  MCD Application Team

* @version V1.6.0

* @date    12-May-2017

* @brief   This file provides all the software functions related to the ymodem

*          protocol.

******************************************************************************

* @attention

*

*

© Copyright ?2016 STMicroelectronics International N.V.

* All rights reserved.

*

* Redistribution and use in source and binary forms, with or without

* modification, are permitted, provided that the following conditions are met:

*

* 1. Redistribution of source code must retain the above copyright notice,

*    this list of conditions and the following disclaimer.

* 2. Redistributions in binary form must reproduce the above copyright notice,

*    this list of conditions and the following disclaimer in the documentation

*    and/or other materials provided with the distribution.

* 3. Neither the name of STMicroelectronics nor the names of other

*    contributors to this software may be used to endorse or promote products

*    derived from this software without specific written permission.

* 4. This software, including modifications and/or derivative works of this

*    software, must execute solely and exclusively on microcontroller or

*    microprocessor devices manufactured by or for STMicroelectronics.

* 5. Redistribution and use of this software other than as permitted under

*    this license is void and will automatically terminate your rights under

*    this license.

*

* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"

* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT

* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A

* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY

* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT

* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,

* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,

* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF

* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING

* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,

* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*

******************************************************************************

*/

/** @addtogroup STM32F1xx_IAP

* @{

*/

/* Includes ------------------------------------------------------------------*/

#include "flash_if.h"

#include "common.h"

#include "ymodem.h"

#include "string.h"

#include "main.h"

#include "menu.h"

/* Private typedef -----------------------------------------------------------*/

/* Private define ------------------------------------------------------------*/

#define CRC16_F       /* activate the CRC16 integrity */

/* Private macro -------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/

/* @note ATTENTION - please keep this variable 32bit alligned */

uint8_t aPacketData[PACKET_1K_SIZE + PACKET_DATA_INDEX + PACKET_TRAILER_SIZE];

/* Private function prototypes -----------------------------------------------*/

static void PrepareIntialPacket(uint8_t *p_data, const uint8_t *p_file_name, uint32_t length);

static void PreparePacket(uint8_t *p_source, uint8_t *p_packet, uint8_t pkt_nr, uint32_t size_blk);

static HAL_StatusTypeDef ReceivePacket(uint8_t *p_data, uint32_t *p_length, uint32_t timeout);

uint16_t UpdateCRC16(uint16_t crc_in, uint8_t byte);

uint16_t Cal_CRC16(const uint8_t* p_data, uint32_t size);

uint8_t CalcChecksum(const uint8_t *p_data, uint32_t size);

/* Private functions ---------------------------------------------------------*/

/**

* @brief  Receive a packet from sender

* @param  data

* @param  length

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ymodem协议是一种常用于在串口通信中进行文件传输的协议,它支持数据的校验、重传等功能。下面是一个基于C语言的ymodem协议接收代码示例: ``` #include<stdio.h> #include<fcntl.h> #include<sys/stat.h> #include<sys/types.h> #include<unistd.h> #include<string.h> #include<stdlib.h> #include<termios.h> #include<errno.h> #define SOH 0x01 //起始字节 #define STX 0x02 //起始字节 #define EOT 0x04 //结束字节 #define ACK 0x06 //确认字节 #define NAK 0x15 //否定字节 #define CAN 0x18 //取消传输字节 #define CRC16 0x43 //CRC校验方式 #define BUFFER_SIZE 1024 //缓冲区大小 #define FILENAME_SIZE 128 //文件名长度 int serial_fd = -1; //串口文件描述符 char file_name[FILENAME_SIZE]; //接收的文件名 char buf[BUFFER_SIZE]; //数据缓冲区 //计算CRC16校验码 unsigned short cal_crc(char *ptr, int len) { unsigned short crc = 0; int i; while(len--) { crc = crc ^ (*ptr++ << 8); for(i=0;i<8;i++) { if(crc & 0x8000) crc = (crc << 1) ^ 0x1021; else crc = crc << 1; } } return crc; } //串口初始化 int serial_init(char *device) { struct termios options; //打开串口 serial_fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY); if(serial_fd == -1) { perror("open serial port"); return -1; } //设置串口参数 tcgetattr(serial_fd, &options); cfmakeraw(&options); cfsetispeed(&options, B115200); cfsetospeed(&options, B115200); options.c_cflag |= CLOCAL | CREAD; options.c_cflag &= ~PARENB; options.c_cflag &= ~CSTOPB; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; options.c_cc[VTIME] = 0; options.c_cc[VMIN] = 1; tcsetattr(serial_fd, TCSANOW, &options); return 0; } //接收文件 int receive_file() { int i = 0, j = 0, buf_len = 0, file_len = 0, count = 0, res = 0, max_count = 10; unsigned short crc = 0, crc_recv = 0; unsigned char packet_num = 0, packet_num_recv = 0; char file_buf[BUFFER_SIZE] = {0}; FILE *fp = NULL; //发送文件接收确认请求 write(serial_fd, &NAK, 1); while(1) { //读取一个数据包 res = read(serial_fd, buf, 1); if(res < 1) { count++; if(count > max_count) { printf("receive file timeout!\n"); return -1; } else { write(serial_fd, &NAK, 1); continue; } } //判断数据包类型 if(buf[0] == SOH) { buf_len = 128; } else if(buf[0] == STX) { buf_len = 1024; } else if(buf[0] == EOT) { write(serial_fd, &ACK, 1); break; } else if(buf[0] == CAN) { printf("transfer cancel by sender!\n"); return -1; } else { printf("unknown packet type!\n"); return -1; } //读取剩余的数据部分 res = read(serial_fd, buf+1, buf_len+3); if(res < buf_len+3) { printf("read packet error!\n"); return -1; } //计算校验和 crc = cal_crc(buf+3, buf_len); crc_recv = buf[buf_len+3] << 8 | buf[buf_len+2]; if(crc != crc_recv) { printf("crc check error!\n"); write(serial_fd, &NAK, 1); continue; } //确认数据包序号 packet_num_recv = buf[1]; if(packet_num_recv != packet_num + 1) { printf("packet num error!\n"); write(serial_fd, &NAK, 1); continue; } packet_num = packet_num_recv; //保存文件数据 memcpy(file_buf+j, buf+3, buf_len); j += buf_len; file_len += buf_len; //发送数据包接收确认 write(serial_fd, &ACK, 1); } //保存接收的文件 fp = fopen(file_name, "wb"); if(fp == NULL) { printf("open file error!\n"); return -1; } fwrite(file_buf, 1, file_len, fp); fclose(fp); printf("receive file success!\n"); return 0; } int main(int argc, char *argv[]) { if(argc != 2) { printf("usage: %s /dev/ttyS0\n", argv[0]); return -1; } //初始化串口 if(serial_init(argv[1]) == -1) { return -1; } //接收文件名 memset(buf, 0, BUFFER_SIZE); while(1) { read(serial_fd, buf+i, 1); if(buf[i] == 0) { break; } i++; } strcpy(file_name, buf); printf("receive file name: %s\n", file_name); //接收文件 receive_file(); close(serial_fd); return 0; } ``` 在这个代码示例中,我们通过调用`serial_init`函数初始化了串口并打开了文件描述符。然后,在`receive_file`函数中,我们通过读取串口数据来获取文件数据包,并进行数据校验和处理。最后,我们将接收到的文件保存到本地磁盘上。 需要注意的是,ymodem协议接收端在接收文件名时,需要读取一个以零字节结尾的字符串,因此我们需要在`read`函数读取数据时进行一些特殊处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值