CUBEMX配置STM32实现FTP文件传输以及使用SNTP获取网络时间并写入RTC

  • 引言
  • FTP代码库的移植
  • Cubemx配置SNTP以及RTC
    • RTC配置方法
    • SNTP配置方法
    • FATFS载入RTC时间
  • 总结

引言

在前三篇文章中自己介绍了如何配置freeRTOS以及如何配置LWIP。使用lwip实现一个httpd服务器,使浏览器可以访问,并且我们利用CGI功能,实现通过网页来控制单片机的一个LED灯的电平翻转。在第四篇文章中,我们在单片机16M的Flash上建立了文件系统。

自己写的另外四篇文章
从零开始Cubemx配置STM32搭载freeRTOS实现多路ADC(一)
从零开始Cubemx配置STM32搭载freeRTOS以及lwip实现tcp网络通信(二)
从零开始使用CubeMX配置STM32使用lwip实现httpd服务器以及使用vscode编辑阅读keil代码(三)
CubeMX配置STM32实现FatFS文件系统(五)

在本篇文章中我们使用CUBEMX配置STM32实现FTP文件传输以及使用SNTP获取网络时间并写入RTC

FTP代码库的移植

FTP的代码移植我主要参考的这位大佬的文章 【程序】在STM32单片机上用1700行代码实现基于LwIP 2.1.2协议栈raw API和FatFs文件系统的FTP服务器(20200703版) 移植了其项目中的ftpd.c以及ftpd.h这两个文件,这两个文件中对代码有注释可以好好看一下。

移植库前需要做好的准备:
1、lwip库已经移植好,能够正常建立TCP连接。
2、文件系统已经建立好,因为FTP要使用f_open()等函数对文件进行操作。

使用方法:把ftpd.c以及ftpd.h这两个文件添加到工程中,编译通过。在主函数中调用ftpd_init()就可以启用FTP功能。下面是使用的截图

注意事项
在使用FTP的时候一定把lwipopts.h中的MEM_SIZE改大点,不然申请内存的时候会不对,导致程序崩溃,默认只有1600字节,我改到了10240字节。

/*----- Default Value for MEM_SIZE: 1600 ---*/
#define MEM_SIZE 10240

Cubemx配置SNTP以及RTC

RTC配置方法

实时时钟的缩写是RTC(Real_Time Clock)。RTC 是集成电路,通常称为时钟芯片。
实时时钟芯片是日常生活中应用最为广泛的消费类电子产品之一。它为人们提供精确的实时时间,或者为电子系统提供精确的时间基准,目前实时时钟芯片大多采用精度较高的晶体振荡器作为时钟源。有些时钟芯片为了在主电源掉电时,还可以工作,需要外加电池供电。
cubemx配置RTC在这个界面进行配置

要注意的是在STM32中,RTC的时钟尽量采用LSE,因为RTC需要断电后继续工作。


这样就配置好了,生成代码就行,使用的代码如下:

RTC_DateTypeDef GetData;  //获取日期结构体
RTC_TimeTypeDef GetTime;   //获取时间结构体HAL_RTC_GetTime(&hrtc, &GetTime, RTC_FORMAT_BIN);
/* Get the RTC current Date */
HAL_RTC_GetDate(&hrtc, &GetData, RTC_FORMAT_BIN);/* Display date Format : yy/mm/dd */
printf("%02d/%02d/%02d\r\n",2000 + GetData.Year, GetData.Month, GetData.Date);
/* Display time Format : hh:mm:ss */
printf("%02d:%02d:%02d\r\n",GetTime.Hours, GetTime.Minutes, GetTime.Seconds);
printf("\r\n");

在使用的时候好像必须要先使用HAL_RTC_GetTime获取时间,再使用HAL_RTC_GetDate获取日期,顺序不能颠倒,具体原因我还没看,知道的可以留言一下。下面我们开始配置SNTP,我们要将SNTP中获取的时间赋值给RTC,这样就不用给RTC赋值初值了。

SNTP配置方法

网络时间协议,英文名称:Network Time Protocol(NTP)是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精准度的时间校正(LAN上与标准间差小于1毫秒,WAN上几十毫秒),且可介由加密确认的方式来防止恶毒的协议攻击。NTP的目的是在无序的Internet环境中提供精确和健壮的时间服务。

简单网络时间协议(Simple Network Time Protocol,SNTP),由 NTP 改编而来,主要用来同步因特网中的计算机时钟。

配置SNTP的方法很简单,在这个界面开启就行了,配置不用改。

使用SNTP的代码如下,主要看bsp_sntp_init(void)这个函数,在程序初始化的时候调用bsp_sntp_init(void)这个函数实现sntp的初始化。

/********************************************************************************* File Name          : RTC.c* Description        : This file provides code for the configuration*                      of the RTC instances.******************************************************************************* @attention** <h2><center>&copy; Copyright (c) 2022 STMicroelectronics.* All rights reserved.</center></h2>** This software component is licensed by ST under Ultimate Liberty license* SLA0044, the "License"; You may not use this file except in compliance with* the License. You may obtain a copy of the License at:*                             www.st.com/SLA0044********************************************************************************//* Includes ------------------------------------------------------------------*/
#include "rtc.h"/* USER CODE BEGIN 0 */
#include "sntp.h"
#include <stdio.h>
#include "time.h"
/* USER CODE END 0 */RTC_HandleTypeDef hrtc;/* RTC init function */
void MX_RTC_Init(void)
{RTC_TimeTypeDef sTime = {0};RTC_DateTypeDef sDate = {0};/** Initialize RTC Only */hrtc.Instance = RTC;hrtc.Init.HourFormat = RTC_HOURFORMAT_24;hrtc.Init.AsynchPrediv = 127;hrtc.Init.SynchPrediv = 255;hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;if (HAL_RTC_Init(&hrtc) != HAL_OK){Error_Handler();}/* USER CODE BEGIN Check_RTC_BKUP *//* USER CODE END Check_RTC_BKUP *//** Initialize RTC and set the Time and Date */sTime.Hours = 0x12;sTime.Minutes = 0x10;sTime.Seconds = 0x10;sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;sTime.StoreOperation = RTC_STOREOPERATION_RESET;if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK){Error_Handler();}sDate.WeekDay = RTC_WEEKDAY_TUESDAY;sDate.Month = RTC_MONTH_JANUARY;sDate.Date = 0x18;sDate.Year = 0x22;if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK){Error_Handler();}}void HAL_RTC_MspInit(RTC_HandleTypeDef* rtcHandle)
{if(rtcHandle->Instance==RTC){/* USER CODE BEGIN RTC_MspInit 0 *//* USER CODE END RTC_MspInit 0 *//* RTC clock enable */__HAL_RCC_RTC_ENABLE();/* USER CODE BEGIN RTC_MspInit 1 *//* USER CODE END RTC_MspInit 1 */}
}void HAL_RTC_MspDeInit(RTC_HandleTypeDef* rtcHandle)
{if(rtcHandle->Instance==RTC){/* USER CODE BEGIN RTC_MspDeInit 0 *//* USER CODE END RTC_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_RTC_DISABLE();/* USER CODE BEGIN RTC_MspDeInit 1 *//* USER CODE END RTC_MspDeInit 1 */}
} /* USER CODE BEGIN 1 */
/*!
* @brief 设置 SNTP 的服务器地址,
*        加入多个 IP 以免某个 IP 获取不了时间
*        执行条件:无
*
* @retval: 无
*/
void set_sntp_server_list(void)
{uint32_t server_list[SNTP_MAX_SERVERS] =  {  0x279148D2,  //国家授时中心0x42041876,0x5F066CCA,0x0B6C1978,0x0B0C5CB6,0x58066BCB,0x14731978,0xC51F70CA,0x521D70CA,0x820176CA,0x510176CA,};ip_addr_t sntp_server;for(int i = 0; i < SNTP_MAX_SERVERS; i++){sntp_server.addr = server_list[i];sntp_setserver(i, &sntp_server);  // 国家授时中心}
}void bsp_sntp_init(void)
{//设置 SNTP 的获取方式 -> 使用向服务器获取方式sntp_setoperatingmode(SNTP_OPMODE_POLL);//SNTP 初始化sntp_init();//加入授时中心的IP信息set_sntp_server_list();
}uint32_t get_timestamp(void)
{struct tm stm;static RTC_DateTypeDef g_Date = {0};static RTC_TimeTypeDef g_Time = {0};///获取时间必须在获取日期前HAL_RTC_GetTime(&hrtc, &g_Time, RTC_FORMAT_BIN);HAL_RTC_GetDate(&hrtc, &g_Date, RTC_FORMAT_BIN);stm.tm_year = g_Date.Year + 100;    //RTC_Year rang 0-99,but tm_year since 1900stm.tm_mon = g_Date.Month - 1;      //RTC_Month rang 1-12,but tm_mon rang 0-11stm.tm_mday = g_Date.Date;          //RTC_Date rang 1-31 and tm_mday rang 1-31stm.tm_hour = g_Time.Hours;         //RTC_Hours rang 0-23 and tm_hour rang 0-23stm.tm_min = g_Time.Minutes;        //RTC_Minutes rang 0-59 and tm_min rang 0-59stm.tm_sec = g_Time.Seconds;return (mktime(&stm) - (8 * 60 * 60));///配置时由于东八区增加8小时,现为时间戳,需减去
}void sntp_set_time(uint32_t sntp_time)
{if(sntp_time == 0){printf("sntp_set_time: wrong!@@\n");return;}printf("sntp_set_time: c00, enter!\n");printf("sntp_set_time: c01, get time = %u\n", sntp_time);#if 1struct tm *time;RTC_TimeTypeDef sTime = {0};RTC_DateTypeDef sDate = {0};sntp_time += (8 * 60 * 60); ///北京时间是东8区需偏移8小时time = localtime(&sntp_time);/** 设置 RTC 的 时间*/sTime.Hours = time->tm_hour;sTime.Minutes = time->tm_min;sTime.Seconds = time->tm_sec;sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;sTime.StoreOperation = RTC_STOREOPERATION_RESET;if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK){Error_Handler();}/** 设置 RTC 的 日期*/sDate.WeekDay = time->tm_wday;sDate.Month = (time->tm_mon) + 1;sDate.Date = time->tm_mday;sDate.Year = (time->tm_year) + 1900 - 2000;if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK){Error_Handler();}printf("sntp_set_time: c02, decode time: 20%d-%02d-%02d %02d:%02d:%02d\n", \sDate.Year, sDate.Month, sDate.Date, sTime.Hours, sTime.Minutes, sTime.Seconds);printf("sntp_set_time: c03, test get = %u\n", get_timestamp());printf("sntp_set_time: c04, set rtc time done\n");
#endif
}/* USER CODE END 1 *//************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

还有重要的一步是把自己写的设置时间的函数注册到sntp库中。方法是在lwipopts.h中加入下面的代码:

/*-----------------------------------------------------------------------------*/
/* Current version of LwIP supported by CubeMx: 2.1.2 -*/
/*-----------------------------------------------------------------------------*//* Within 'USER CODE' section, code will be kept by default at each generation */
/* USER CODE BEGIN 0 */
#include "rtc.h"
#define SNTP_SET_SYSTEM_TIME        sntp_set_time
/* USER CODE END 0 */

使用截图

FATFS载入RTC时间

之前配置的文件系统不能在创建文件的时候显示当前时间,很不方便,在这里我们把ntp以及RTC都配置好了,把RTC嵌入到FATFS文件系统中,这样创建文件的时间就是当前时间。在fatfs.c的文件中添加以下代码:

DWORD get_fattime(void)
{/* USER CODE BEGIN get_fattime */DWORD retValue = 0;uint8_t year, month, day, hour, minuite, second;RTC_DateTypeDef GetData;  //获取日期结构体RTC_TimeTypeDef GetTime;   //获取时间结构体year = 2000 + GetData.Year - 1980;month = GetData.Month;day = GetData.Date-1;hour = GetTime.Hours+16;//printf("Hours is %d\n",(uint8_t)hour);minuite = GetTime.Minutes;second = GetTime.Seconds/2;//printf("Second is %d\n",(uint8_t)second);retValue = (DWORD)year<<25 | (DWORD)month<<21 | (DWORD)day<<16 | (DWORD)hour<<11 | (DWORD)minuite<<5 | (DWORD)second>>1;return retValue;/* USER CODE END get_fattime */
}


这样创建文件的时候就有当前时间了,现在还遗留一个问题没解决,RTC读出的时间是对的,但是转换成DWORD的时候,年月入都对,但是秒会为0,自己还在看,知道怎么回事的可以评论告诉我一下。

总结

自己在这篇文章中写入了FTP如何移植,以及关于时间的一些操作,SNTP,RTC等,并把RTC时间写入了文件系统中,这样一套物联网框架应该就比较全了,自己下周开始搞一下MQTT。

CUBEMX配置STM32实现FTP文件传输以及使用SNTP获取网络时间并写入RTC相关推荐

  1. ESP32-C3 ESP-IDF 配置smartconfig 和 sntp 获取网络时间

    ESP32-C3 ESP-IDF 配置smartconfig 和 sntp 获取网络时间 /* Esptouch exampleThis example code is in the Public D ...

  2. Bandwagon的配置记录(二) —— ftp文件传输

    SSH登录服务器 登录的方法在Bandwagon的配置记录(一) -- kexue上网 配置前的准备 1.新建一个目录(  /home/ftp  ),以后可以把文件放在这里,这里相当于是个中转站 cd ...

  3. CubeMX配置STM32实现httpd服务器CGI功能并使用网页控制STM32单片机(四)

    CubeMX配置STM32实现httpd服务器CGI功能并使用网页控制STM32单片机 引言 CubeMX配置HTTPD的CGI功能 实验过程 发现的问题 总结 引言 在前三篇文章中自己介绍了如何配置 ...

  4. 详解“FTP文件传输服务”安装配置实例

    "FTP文件传输服务"安装配置实例 家住海边喜欢浪:zhang789.blog.51cto.com 目录 简介 ftp工作原理 常见的FTP服务 Vsftpd服务器的安装 Vsft ...

  5. 简述使用ftp进行文件传输时的两种登录方式?它们的区别是什么?常用的ftp文件传输命令是什么?

    简述使用ftp进行文件传输时的两种登录方式?它们的区别是什么?常用的ftp文件传输命令是什么? 参考答案: (1)ftp有两种登录方式:匿名登录和授权登录.使用匿名登录时,用户名为:anonymous ...

  6. Linux 网络服务之FTP 文件传输

    Linux FTP 文件传输 --王宇然qq:496488051 实验一:配置匿名上传FTP 1.软件包安装: [root@localhost ~]# cd /misc/cd/Server       ...

  7. asc码转换 linux_Linux网络服务04——FTP文件传输服务

    Linux网络服务04--FTP文件传输服务 一.FTP连接及传输模式 1.控制连接:TCP 21,用于发送FTP命令信息 2.数据连接:TCP 20,用于上传.下载数据 3.数据连接的建立类型: ( ...

  8. 【CubeMX配置STM32驱动超声波模块(HC-SR04)】

    CubeMX配置STM32以驱动超声波模块(HC-SR04) 一.CubeMX配置STM32 1.选择定时器 选择输入捕获模式 预分频设置为71,向上计数,自动重装值65535 然后将名字改为ECHO ...

  9. Linux运维系列总结-Linux系统启动过程、WEB工作原理、DHCP工作原理、DNS解析原理、NFS网络文件系统、FTP文件传输协议、PXE+KICKSTART自动安装系统

    Linux运维系列总结-Linux系统启动过程.WEB工作原理.DHCP工作原理.DNS解析原理.NFS网络文件系统.FTP文件传输协议.PXE+KICKSTART自动安装系统 1.Linux系统的启 ...

最新文章

  1. YII 测试环境搭建
  2. 隐马尔可夫(HMM)
  3. 我们需要StringBuffer么?
  4. Apache Derby-02通过IJ简单操作DERBY
  5. windows 系统nginx做反向代理实例
  6. 【Leetcode | 6】136. 只出现一次的数字
  7. shell 编程(难题分析)
  8. Spring-boot配置JedisShardInfo
  9. q learning简单理解_班级励志标语格言-生活其实很简单,过了今天就是明天
  10. android 如何解锁屏幕,2解锁屏幕破裂Android手机的方法(自由方式)
  11. js中的symbol详解
  12. 父亲节php源码,父亲节 | 愿时光再慢一点,祝天下所有的父亲,父亲节快乐
  13. linux无法解析域名
  14. nodejs实现VSCode中的open with five server功能
  15. 发布一个JINI服务
  16. Java POI导出word文件及生成表格
  17. python中init函数详解_Python 中__init__函数以及参数self
  18. 光电效应在计算机中应用,光电效应在现在的应用主要包括哪几个方面?
  19. 券商API/程序化交易接口
  20. 瑞云渲染 | 全面支持Anima®4渲染插件,实现高精度的群集角色!

热门文章

  1. Linux系统获取开发板的文件系统并打包成img文件
  2. oracle静默创建实例linux,linux CentOS7下快速静默安装Oracle11GR2数据库并创建实例
  3. colab常见问题解答
  4. 自定义圆环形进度条实现
  5. 魔兽争霸3的MapHack制作教程(一)显示敌对单位
  6. 标题类、文本类、列表类、代码类、图文样式、表格布局、
  7. 2019最新Java实战开发今日头条资讯网站
  8. 如何编制项目蓝图汇报材料
  9. 使用python的zipfile模块巧解word批量生成问题
  10. LTE学习:PHICH