概述
在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) ;
}
结果