发帖
0 0 0

【BW20-12F开发板评测】5、NTP时钟

sujingliang
论坛元老

26

主题

17

回帖

8428

积分

论坛元老

积分
8428
BW系列 12 0 1 小时前

从NTP服务器获取时钟校准MCU的RTC时间,是一种获取准确时间的方法。

本文通过WB20-12F来实现这一过程

1.png

一、NTP获取时间

1、变量定义

#define TIME_MODE    1	//0: for UTC with microseconds, 1: for timezone with seconds
#define SNTP_SERVER             "pool.ntp.org"

2、rtc初始化

static void rtc_init(void)
{
	RTC_InitTypeDef RTC_InitStruct;
	RCC_PeriphClockCmd(APBPeriph_RTC, APBPeriph_RTC_CLOCK, ENABLE);

	RTC_StructInit(&RTC_InitStruct);
	RTC_InitStruct.RTC_HourFormat = RTC_HourFormat_24;
	RTC_Init(&RTC_InitStruct);

	/* set UTC+8 localtime */
	setenv("TZ", "CST-8", 1);
}

3、设置rtc时间函数

static void set_rtc_time(struct tm *ti)
{
	struct tm *timeinfo;
	timeinfo=ti;

	RTC_TimeTypeDef RTC_TimeStruct;

	/*set time in RTC */
	RTC_TimeStructInit(&RTC_TimeStruct);
	RTC_TimeStruct.RTC_H12_PMAM = RTC_H12_AM;
	RTC_TimeStruct.RTC_Days = timeinfo->tm_yday;
	RTC_TimeStruct.RTC_Hours = timeinfo->tm_hour;
	RTC_TimeStruct.RTC_Minutes = timeinfo->tm_min;
	RTC_TimeStruct.RTC_Seconds = timeinfo->tm_sec;
	RTC_TimeStruct.RTC_Year = timeinfo->tm_year + 1900;
	RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);
}

4、获取NTP时间并更新RTC

tatic void show_time(void)
{
#if (TIME_MODE == 0)
	uint32_t sec;
	uint32_t us;
	SNTP_GET_SYSTEM_TIME(sec, us);
	time_t now = (time_t)sec;
	RTK_LOGS(NOTAG, RTK_LOG_INFO, "%s + %d usec\n", ctime(&now), us);
#elif (TIME_MODE == 1)
	time_t now;
	struct tm timeinfo;
	int timezone = 8;	// use UTC+8(offset in hrs) timezone for example, 8 * 60 * 60(offset in seconds)
	time(&now);
	setenv("TZ", "CST-8", 1);
	tzset();
	timeinfo = *(localtime(&now));
	RTK_LOGS(NOTAG, RTK_LOG_INFO, "%d-%d-%d %d:%d:%d UTC%s%d\n",
			 timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec,
			 (timezone > 0) ? "+" : "", timezone);

	set_rtc_time(&timeinfo);

#endif
}

5、线程函数

获取10次NTP时间后,退出线程。

在开始前,需要通过调试串口发送AT指令连接WIFI:

AT+WLCONN=ssid,你的ssid,pw,SSID的秘密

static void example_sntp_showtime_thread(void *param)
{
	/* To avoid gcc warnings */
	(void) param;

	int should_stop = 1;
	int get_time=10;


	// Delay to check successful WiFi connection and obtain of an IP address
	LwIP_Check_Connectivity();

	rtc_init();
	RTK_LOGS(NOTAG, RTK_LOG_INFO, "\r\n====================Example: SNTP show time====================\r\n");

	sntp_setservername(0, SNTP_SERVER);

	sntp_init();

	while (1) {
		show_time();
		rtos_time_delay_ms(1000);

		if (!get_time&&should_stop) {
			break;
		}
		get_time--;
	}

	rtos_task_delete(NULL);
}

二、LCD驱动显示RTC时间

1、获取rtc时间

static struct tm *get_rtc_time(void )
{
	RTC_TimeTypeDef RTC_TimeStruct;

	RTC_GetTime(RTC_Format_BIN, &RTC_TimeStruct);
	time_t seconds = time(NULL);
	struct tm *timeinfo = localtime(&seconds);
	timeinfo->tm_sec = RTC_TimeStruct.RTC_Seconds;
	timeinfo->tm_min = RTC_TimeStruct.RTC_Minutes;
	timeinfo->tm_hour = RTC_TimeStruct.RTC_Hours;
	timeinfo->tm_year = RTC_TimeStruct.RTC_Year - 1900;

	// ti=timeinfo;
	return timeinfo;
}

2、初始化LCD gpio

void init_gpio(void)
{
	GPIO_InitTypeDef GPIO_InitStruct_LCD;
	GPIO_InitStruct_LCD.GPIO_Pin = LCD_RST;
	GPIO_InitStruct_LCD.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_Init(&GPIO_InitStruct_LCD);

	GPIO_InitStruct_LCD.GPIO_Pin = LCD_DC;
	GPIO_InitStruct_LCD.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_Init(&GPIO_InitStruct_LCD);

	#ifndef HARDWARE_SPI
	GPIO_InitStruct_LCD.GPIO_Pin = LCD_SDA;
	GPIO_InitStruct_LCD.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_Init(&GPIO_InitStruct_LCD);


	GPIO_InitStruct_LCD.GPIO_Pin = LCD_SCL;
	GPIO_InitStruct_LCD.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_Init(&GPIO_InitStruct_LCD);

	GPIO_InitStruct_LCD.GPIO_Pin = LCD_CS;
	GPIO_InitStruct_LCD.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_Init(&GPIO_InitStruct_LCD);
	#endif
}

3、硬件SPI初始化

void init_spi(void)
{
	u32 SclkPhase = SCPH_TOGGLES_IN_MIDDLE; // SCPH_TOGGLES_IN_MIDDLE or SCPH_TOGGLES_AT_START
	u32 SclkPolarity = SCPOL_INACTIVE_IS_LOW; // SCPOL_INACTIVE_IS_LOW or SCPOL_INACTIVE_IS_HIGH
	u32 ClockDivider = 20; // Fssi_clk is 100MHz

	rtos_time_delay_ms(500);
	Pinmux_Swdoff();

	/* SPI1 is as Master and SPI0 is as Slave */
	/* init SPI1 */
	SSI_SetRole(SPI1_DEV, SSI_MASTER);
	SSI_InitTypeDef SSI_InitStructM;
	SSI_StructInit(&SSI_InitStructM);

	RCC_PeriphClockCmd(APBPeriph_SPI1, APBPeriph_SPI1_CLOCK, ENABLE);
	Pinmux_Config(SPI1_MOSI, PINMUX_FUNCTION_SPIM);
	Pinmux_Config(SPI1_MISO, PINMUX_FUNCTION_SPIM);
	Pinmux_Config(SPI1_SCLK, PINMUX_FUNCTION_SPIM);
	Pinmux_Config(SPI1_CS, PINMUX_FUNCTION_SPIM);
	PAD_PullCtrl((u32)SPI1_CS, GPIO_PuPd_UP);

	SSI_InitStructM.SPI_Role = SSI_MASTER;
	SSI_Init(SPI1_DEV, &SSI_InitStructM);

	/* set format */
	SSI_SetSclkPhase(SPI1_DEV, SclkPhase);
	SSI_SetSclkPolarity(SPI1_DEV, SclkPolarity);
	SSI_SetDataFrameSize(SPI1_DEV, DFS_8_BITS);

	/* set frequency */
	SSI_SetBaudDiv(SPI1_DEV, ClockDivider); // Fssi_clk is 100MHz

}

引脚定义为:

// SPI1 FID=8 & Fully PG
#define SPI1_MOSI	_PB_19
#define SPI1_MISO	_PB_20
#define SPI1_SCLK	_PB_18
#define SPI1_CS		_PB_21

#define LCD_RST 	_PA_8 
#define LCD_DC 		_PA_12
#define LCD_SDA     _PB_19
#define LCD_SCL     _PB_18
#define LCD_CS      _PB_21

#define HARDWARE_SPI

#define LCD_RST_SET   GPIO_WriteBit(LCD_RST, 1)
#define LCD_RST_CLR   GPIO_WriteBit(LCD_RST, 0)
#define LCD_DC_SET    GPIO_WriteBit(LCD_DC, 1)
#define LCD_DC_CLR    GPIO_WriteBit(LCD_DC, 0)

// #define LCD_CS_SET  PAD_PullCtrl((u32)SPI1_CS, GPIO_PuPd_UP);
// #define LCD_CS_CLR  PAD_PullCtrl((u32)SPI1_CS, GPIO_PuPd_DOWN);
#define LCD_CS_SET  GPIO_WriteBit(LCD_CS, 1)
#define LCD_CS_CLR  GPIO_WriteBit(LCD_CS, 0)
#define LCD_SDA_SET GPIO_WriteBit(LCD_SDA, 1)
#define LCD_SDA_CLR GPIO_WriteBit(LCD_SDA, 0)
#define LCD_SCL_SET GPIO_WriteBit(LCD_SCL, 1)
#define LCD_SCL_CLR GPIO_WriteBit(LCD_SCL, 0)

4、LCD线程任务

void lcd_task(void)
{
	struct tm *timeinfo;
	char str_lcd_time[20];
	RTK_LOGS(NOTAG, RTK_LOG_INFO, "[%s] into lcd_task \r\n", __FUNCTION__);
	init_gpio();

	#ifdef HARDWARE_SPI
	 init_spi();
	#endif

	Lcd_Init();

	Lcd_Clear(BLACK);
	while(1)
	{
		timeinfo=get_rtc_time();
		RTK_LOGS(NOTAG, RTK_LOG_INFO, "Time as a custom formatted string = %d-%d-%d %d:%d:%d\n\n",
			   timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday, timeinfo->tm_hour,
			   timeinfo->tm_min, timeinfo->tm_sec);
		sprintf(str_lcd_time,"%04d-%02d-%02d",timeinfo->tm_year + 1900, timeinfo->tm_mon + 1, timeinfo->tm_mday);
		Gui_DrawFont_GBK16(24,10,BLUE,GRAY0,str_lcd_time);
		sprintf(str_lcd_time,"%02d:%02d:%02d",timeinfo->tm_hour,timeinfo->tm_min, timeinfo->tm_sec);
		Gui_DrawFont_GBK16(24,36,BLUE,GRAY0,str_lcd_time);
		rtos_time_delay_ms(1000);

	}
	//never excute
	SSI_Cmd(SPI1_DEV, DISABLE);
	rtos_task_delete(NULL);
}

5、LCD写数据函数

#ifdef HARDWARE_SPI
void  SPI_WriteData(unsigned char Data)
{
	while (!SSI_Writeable(SPI1_DEV));
	//RTK_LOGS(NOTAG, RTK_LOG_INFO, "[%s] SPI_WriteData \r\n", __FUNCTION__);
	SSI_WriteData(SPI1_DEV, Data);
	/* master read */
	 while (!SSI_Readable(SPI1_DEV));
	 SSI_ReadData(SPI1_DEV);
}
#endif

写寄存器、写数据

void Lcd_WriteIndex(unsigned char Index)
{
   	LCD_DC_CLR;

	#ifndef HARDWARE_SPI
	LCD_CS_CLR;
	#endif

   	SPI_WriteData(Index);

	#ifndef HARDWARE_SPI
	LCD_CS_SET;
	#endif
}

void Lcd_WriteData(unsigned char Data)
{
   	LCD_DC_SET;
	#ifndef HARDWARE_SPI
	LCD_CS_CLR;
	#endif

   	SPI_WriteData(Data);

	#ifndef HARDWARE_SPI
	LCD_CS_SET;
	#endif
}
──── 0人觉得很赞 ────

使用道具 举报

您需要登录后才可以回帖 立即登录
高级模式
返回
统计信息
  • 会员数: 30188 个
  • 话题数: 44384 篇