概述
在w5500基础库中进行封装,获取服务端的时间,来校准本地时间。 本次使用的方案是通过ntp获取时间+定时器更新保证时间准确。
NTP封装
头文件
# ifndef F1XX_TEMPLATE_W5500_NTP_H
# define F1XX_TEMPLATE_W5500_NTP_H # include "socket.h" # define TIMEZONE0 22
# define TIMEZONE8 39
# define TIME_ZONE TIMEZONE8
# define SECS_PERDAY 86400UL
# define EPOCH 1900
struct ntp_conf { void ( * delay_ms_cb) ( uint32_t ms) ; uint8_t ntp_server[ 4 ] ; uint16_t ntp_port;
} ;
struct net_date_time { uint16_t year; uint8_t month; uint8_t day; uint8_t hour; uint8_t min; uint8_t sec;
} ; void ntp_config_set ( struct ntp_conf * cnf) ;
bool ntp_date_time_get ( SOCKET s, uint32_t wait_ms, struct net_date_time * dst) ;
void ntp_date_time_update ( ) ;
void net_date_time_loc_get ( struct net_date_time * dst) ; # endif
源文件
# include "w5500_ntp.h" # define DBG_ENABLE
# define DBG_SECTION_NAME "ntp_module"
# define DBG_LEVEL DBG_LOG # include "sys_dbg.h" uint32_t volatile total_sec;
static struct ntp_conf * ntp_conf_ptr = NULL ;
static uint8_t ntp_request_msg[ 48 ] = { 0x23 } ;
static uint8_t cache_buf[ SIZE_256B] ;
static struct net_date_time nt_tm; static void calc_date_time ( uint32_t seconds, struct net_date_time * datetime) ; void get_seconds_from_ntp_server ( uint8_t * buf, uint16_t idx, struct net_date_time * dst) ; void ntp_config_set ( struct ntp_conf * cnf) { ntp_conf_ptr = cnf;
} struct net_date_time * ntp_date_time_get ( SOCKET s, uint32_t wait_ms) { uint16_t len = 0 ; if ( ntp_conf_ptr == NULL ) { LOG_E ( "ntp_config_set not set" ) ; return NULL ; } if ( udp_client_init ( s, ntp_conf_ptr-> ntp_port) ) { udp_client_send_simple ( s, ntp_conf_ptr-> ntp_server, ntp_conf_ptr-> ntp_port, ntp_request_msg, sizeof ( ntp_request_msg) ) ; for ( int i = 0 ; i < wait_ms / 2 ; ++ i) { if ( ( len = w5500_socket_rx_size_read ( s) ) > 0 ) { recvfrom_simple ( s, cache_buf, len) ; get_seconds_from_ntp_server ( cache_buf, 40 , & nt_tm) ; close ( s) ; return & nt_tm; } ntp_conf_ptr-> delay_ms_cb ( 2 ) ; } } else { LOG_E ( "udp_client_init err:%d" , __LINE__ ) ; } return NULL ;
} void ntp_date_time_update ( ) { total_sec += 1 ;
} struct net_date_time * net_date_time_loc_get ( ) { calc_date_time ( total_sec, & nt_tm) ; return & nt_tm;
} void get_seconds_from_ntp_server ( uint8_t * buf, uint16_t idx, struct net_date_time * dst) { uint32_t seconds = 0 ; uint8_t i = 0 ; for ( i = 0 ; i < 4 ; i++ ) { seconds = ( seconds << 8 ) | buf[ idx + i] ; } switch ( TIME_ZONE) { case 0 : seconds -= 12 * 3600 ; break ; case 1 : seconds -= 11 * 3600 ; break ; case 2 : seconds -= 10 * 3600 ; break ; case 3 : seconds -= ( 9 * 3600 + 30 * 60 ) ; break ; case 4 : seconds -= 9 * 3600 ; break ; case 5 : case 6 : seconds -= 8 * 3600 ; break ; case 7 : case 8 : seconds -= 7 * 3600 ; break ; case 9 : case 10 : seconds -= 6 * 3600 ; break ; case 11 : case 12 : case 13 : seconds -= 5 * 3600 ; break ; case 14 : seconds -= ( 4 * 3600 + 30 * 60 ) ; break ; case 15 : case 16 : seconds -= 4 * 3600 ; break ; case 17 : seconds -= ( 3 * 3600 + 30 * 60 ) ; break ; case 18 : seconds -= 3 * 3600 ; break ; case 19 : seconds -= 2 * 3600 ; break ; case 20 : seconds -= 1 * 3600 ; break ; case 21 : case 22 : break ; case 23 : case 24 : case 25 : seconds += 1 * 3600 ; break ; case 26 : case 27 : seconds += 2 * 3600 ; break ; case 28 : case 29 : seconds += 3 * 3600 ; break ; case 30 : seconds += ( 3 * 3600 + 30 * 60 ) ; break ; case 31 : seconds += 4 * 3600 ; break ; case 32 : seconds += ( 4 * 3600 + 30 * 60 ) ; break ; case 33 : seconds += 5 * 3600 ; break ; case 34 : seconds += ( 5 * 3600 + 30 * 60 ) ; break ; case 35 : seconds += ( 5 * 3600 + 45 * 60 ) ; break ; case 36 : seconds += 6 * 3600 ; break ; case 37 : seconds += ( 6 * 3600 + 30 * 60 ) ; break ; case 38 : seconds += 7 * 3600 ; break ; case 39 : seconds += 8 * 3600 ; break ; case 40 : seconds += 9 * 3600 ; break ; case 41 : seconds += ( 9 * 3600 + 30 * 60 ) ; break ; case 42 : seconds += 10 * 3600 ; break ; case 43 : seconds += ( 10 * 3600 + 30 * 60 ) ; break ; case 44 : seconds += 11 * 3600 ; break ; case 45 : seconds += ( 11 * 3600 + 30 * 60 ) ; break ; case 46 : seconds += 12 * 3600 ; break ; case 47 : seconds += ( 12 * 3600 + 45 * 60 ) ; break ; case 48 : seconds += 13 * 3600 ; break ; case 49 : seconds += 14 * 3600 ; break ; } total_sec = seconds; calc_date_time ( seconds, dst) ;
} static void calc_date_time ( uint32_t seconds, struct net_date_time * datetime) { uint8_t yf = 0 ; uint32_t p_year_total_sec; uint32_t r_year_total_sec; uint32_t n = 0 , d = 0 , total_d = 0 , rz = 0 ; uint16_t y = 0 , r = 0 , yr = 0 ; signed long long yd = 0 ; n = seconds; total_d = seconds / ( SECS_PERDAY) ; d = 0 ; p_year_total_sec = SECS_PERDAY * 365 ; r_year_total_sec = SECS_PERDAY * 366 ; while ( n >= p_year_total_sec) { if ( ( EPOCH + r) % 400 == 0 || ( ( EPOCH + r) % 100 != 0 && ( EPOCH + r) % 4 == 0 ) ) { n = n - ( r_year_total_sec) ; d = d + 366 ; } else { n = n - ( p_year_total_sec) ; d = d + 365 ; } r += 1 ; y += 1 ; } y += EPOCH; datetime-> year = y; yd = 0 ; yd = total_d - d; yf = 1 ; while ( yd >= 28 ) { if ( yf == 1 || yf == 3 || yf == 5 || yf == 7 || yf == 8 || yf == 10 || yf == 12 ) { yd -= 31 ; if ( yd < 0 ) break ; rz += 31 ; } if ( yf == 2 ) { if ( y % 400 == 0 || ( y % 100 != 0 && y % 4 == 0 ) ) { yd -= 29 ; if ( yd < 0 ) break ; rz += 29 ; } else { yd -= 28 ; if ( yd < 0 ) break ; rz += 28 ; } } if ( yf == 4 || yf == 6 || yf == 9 || yf == 11 ) { yd -= 30 ; if ( yd < 0 ) break ; rz += 30 ; } yf += 1 ; } datetime-> month = yf; yr = total_d - d - rz; yr += 1 ; datetime-> day = yr; seconds = seconds % SECS_PERDAY; datetime-> hour = seconds / 3600 ; datetime-> min = ( seconds % 3600 ) / 60 ; datetime-> sec = ( seconds % 3600 ) % 60 ; }
测试
配置文件(基础)
# include "app_conf.h"
# include "w5500_config.h" # if APP_CONFIG_W5500
# define DBG_ENABLE
# define DBG_SECTION_NAME "w5500"
# define DBG_LEVEL W5500_DBG_LEVEL # include "sys_dbg.h"
# include "w5500_dns.h" # define W5500_CS stm_port_define ( B, 12 )
# define W5500_RST stm_port_define ( C, 7 )
static SPI_HandleTypeDef * w5500_spi = NULL ; static void send_and_rec_bytes ( uint8_t * in_dat, uint8_t * out_data, uint16_t len) { while ( HAL_SPI_GetState ( w5500_spi) != HAL_SPI_STATE_READY) ; HAL_SPI_TransmitReceive ( w5500_spi, in_dat, out_data, len, 1000 ) ; while ( HAL_SPI_GetState ( w5500_spi) != HAL_SPI_STATE_READY) ;
} static void send_only ( uint8_t * in_data, uint16_t len) { HAL_SPI_Transmit ( w5500_spi, in_data, len, 1000 ) ;
} static void W5500_RST_HIGH ( void ) { stm_pin_high ( W5500_RST) ; } static void W5500_RST_LOW ( void ) { stm_pin_low ( W5500_RST) ; } static void W5500_CS_LOW ( void ) { stm_pin_low ( W5500_CS) ; } static void W5500_CS_HIGH ( void ) { stm_pin_high ( W5500_CS) ; } static void W5500_Driver_MspInit ( void ) { stm32_pin_mode ( W5500_CS, pin_mode_output) ; stm32_pin_mode ( W5500_RST, pin_mode_output) ; stm_pin_low ( W5500_RST) ; stm_pin_low ( W5500_CS) ; bsp_SpiHandleInit ( w5500_spi, SPI_BAUDRATEPRESCALER_2, spi_mode_3) ;
} module_w5500_t w5500_conf = { . base_conf= { . socket_num = 4 , . rx_size= { 4 , 4 , 4 , 4 } , . tx_size= { 4 , 4 , 4 , 4 } , } , . net_conf= { . ip= { 192 , 168 , 199 , 12 } , . gw= { 192 , 168 , 199 , 1 } , . sub= { 255 , 255 , 255 , 0 } , . dns= { 114 , 114 , 114 , 114 } ,
. dns_port = 53 , } , . driver= { . cs_high = W5500_CS_HIGH, . cs_low = W5500_CS_LOW, . rst_high= W5500_RST_HIGH, . rst_low= W5500_RST_LOW, . delay = HAL_Delay, . send_and_rec_bytes = send_and_rec_bytes, . send_only = send_only} , . api = { . msp_init= W5500_Driver_MspInit, }
} ; static void w5500_pre_init ( void ) { w5500_spi = conv_spi_handle_ptr ( handle_get_by_id ( spi2_id) ) ; module_w5500_init ( & w5500_conf) ; uint32_t uid0 = HAL_GetUIDw0 ( ) ; uint32_t uid1 = HAL_GetUIDw1 ( ) ; uint32_t uid2 = HAL_GetUIDw2 ( ) ; uint8_t mac[ 6 ] = { 0 , uid0 >> 8 , uid1, uid1 >> 8 , uid2, uid2 >> 8 } ; memcpy ( w5500_conf. net_conf. mac, mac, sizeof ( mac) ) ;
} static void w5500_init ( void ) { w5500_conf. api. msp_init ( ) ; w5500_conf. net_conf_init ( ) ; uint8_t ip[ 4 ] ; w5500_reg_ip_read ( ip) ; LOG_D ( "w5500_reg_ip_read:%d.%d.%d.%d" , ip[ 0 ] , ip[ 1 ] , ip[ 2 ] , ip[ 3 ] ) ; w5500_reg_gw_read ( ip) ; LOG_D ( "w5500_reg_gw_read:%d.%d.%d.%d" , ip[ 0 ] , ip[ 1 ] , ip[ 2 ] , ip[ 3 ] ) ;
} static void w5500_after_init ( void ) { } app_init_export ( w5500_net_conf, w5500_pre_init, w5500_init, w5500_after_init) ;
# endif
ntp配置文件(ntp+定时器6)
# include "app_conf.h" # define DBG_ENABLE
# define DBG_SECTION_NAME "net_ntp"
# define DBG_LEVEL DBG_LOG # include "sys_dbg.h"
# include "socket.h"
# include "w5500_ntp.h" static TIM_HandleTypeDef * ntp_base_timer = NULL ;
static struct ntp_conf conf = { . ntp_server= { 114 , 118 , 7 , 163 } , . ntp_port = 123 , . delay_ms_cb = HAL_Delay
} ;
struct net_date_time gb_app_time; static void net_ntp_init ( ) { ntp_base_timer = conv_tim_handle_ptr ( handle_get_by_id ( tim6_id) ) ; bsp_TimHandleInit ( ntp_base_timer, 7199 , 9999 ) ; HAL_TIM_Base_Start_IT ( ntp_base_timer) ; } sys_init_export ( net_ntp, net_ntp_init) ; static void net_ntp_after_init ( ) { ntp_config_set ( & conf) ; uint8_t try_cnt = 3 ; for ( int i = 0 ; i < try_cnt; ++ i) { if ( ntp_date_time_get ( 1 , 500 , & gb_app_time) ) { HAL_TIM_Base_Start ( ntp_base_timer) ; goto exit_ok; } } LOG_W ( "ntp_date_time_get time out" ) ; return ; exit_ok: LOG_D ( "NTP TIME:%d-%02d-%02d %02d:%02d:%02d" , gb_app_time. year, gb_app_time. month, gb_app_time. day, gb_app_time. hour, gb_app_time. min, gb_app_time. sec) ;
} sys_after_init_export ( net_ntp, net_ntp_after_init) ; void tim6_PeriodElapsedCallback ( ) { ntp_date_time_update ( ) ; net_date_time_loc_get ( & gb_app_time) ; LOG_D ( "NTP TIME:%d-%02d-%02d %02d:%02d:%02d" , gb_app_time. year, gb_app_time. month, gb_app_time. day, gb_app_time. hour, gb_app_time. min, gb_app_time. sec) ; } void tim6_it_msp_init ( void ) { HAL_NVIC_SetPriority ( TIM6_IRQn, 5 , 0 ) ; HAL_NVIC_EnableIRQ ( TIM6_IRQn) ;
} void tim6_it_msp_de_init ( void ) { HAL_NVIC_DisableIRQ ( TIM6_IRQn) ;
} void TIM6_IRQHandler ( void ) { HAL_TIM_IRQHandler ( ntp_base_timer) ;
}
结果