赞
踩
目录
利用STM32获取网络时间,然后再通过LCD将时间显示出来,这是之前很久做的工程,这段时间刚好比较悠闲,然后之前也做过一些笔记,现在刚好将其完善一下。我感觉这篇博客主要讲实现的方法,注意:代码不是重点,重点是我是如何一步一步实现的。而且后续的博客还会讲到如何利用同样的方式去获取天气,去连接阿里云等。
所以,学会一种方法很重要。
STM32选用核心板F103C8T6,然后再加一个ESP8266 WiFi模块(任何型号应该都可以),最后需要一个USB-TTL模块用来打印串口数据。群号:1020775171。
- AT //查询模块是否正常工作
- AT+RST //模块复位
- AT+RESTORE //恢复出厂设置
- AT+CWMODE=1 //设置WiFi模块的模式
- AT+CIPMUX=0 //设置模块为单路连接模式
- AT+CWJAP="WIFI名称","密码" //连接网络
- AT+CIPSTART="TCP","192.168.666",80//连接TCP服务器,192.168.0.102是服务器IP,8080是服务器端口。
- AT+CIPSTART="TCP","quan.suning.com",80 //或者 AT+CIPSTART="TCP","175.6.49.231",80
- AT+CIPMODE=1 //开启透传模式
- AT+CIPSEND //开始发送数据
- +++ //退出透传模式
首先是这一篇,这篇文章作者是通过Arduino IDE开发板实现的,但是给我提供了灵感,文章地址:esp8266获取网络时间_tongyue的博客-CSDN博客_esp8266获取网络时间
其次是关于苏宁后台时间数据的解析方式,这里我参考的是这一篇,文章解释的非常详细,而且我时间的解析代码也是来源于这篇文章,推荐大家去看一下。利用苏宁API接口获取北京时间授时_xgy516的博客-CSDN博客_获取北京时间api
下图就是获取时间的流程图,这里的时间其实是通过访问苏宁网页的后台得到的时间数据,例如你可以直接在浏览器中输入“quan.suning.com/getSysTime.do”,你就会看到返回的时间数据格式是怎样的。另外,后面也会解释每个步骤的原理。
上面介绍了获取时间的流程图,下面就依据这流程图的步骤,一步一步来实现。
第一步、让ESP8266连接上USB-TTL模块,然后连接电脑,接着打开电脑上的串口助手软件,最后点击打开串口。注意:默认串口的波特率为115200
第二步、在多条发送那一栏提前建立指令集,如下图所示
- 0:AT
- 1:AT+RST
- 2:AT+CWMODE=1
- 3:AT+CIPMUX=0
- 4:AT+CWJAP="你的WiFi名称","你的WiFi密码"
- 5:AT+CIPMODE=1
- 6:AT+CIPSTART="TCP","quan.suning.com",80
- 7:AT+CIPSEND
- 8:GET http://quan.suning.com/getSysTime.do
- 9:+++
第三步、开始发送指令,之间点击按钮0就可以了,注意:勾选发送新行
如果返回OK,表明连接成功。如果没有反应,那就要注意:看一下ESP8266的RXD和TXD与USB-TTL的RXD与TXD是不是交叉相接?
第三步、对ESP8266进行复位操作
第四步、设置ESP8266为STA(Station)模式,这个模式类似于无线终端,本身并不接受无线的接入,它可以连接到AP,一般无线网卡即工作在该模式。
第五步、设置ESP8266为单路连接模式,因为后面我要将模块设置为透传模式,而透传模式只能在单连接模式下进行
第六步、连接WiFi,这里我推荐通过手机开热点的方式建立一个WiFi,因为这样连接成功后,手机上也会有显示。
第七步、设置为透传模式,透传模式是指:与传输网络的介质、调制解调方式、传输方式、传输协议无关的一种数据传送方式,这就好比收快递,邮件中间有可能通过自行车、汽车、火车、飞机的多种组合运输方式到达你的手上,但你不用关心它们中间经历了哪些。
第八步、连接目标的服务器,TCP是传输协议,quan.suning.com是服务器的IP地址,80是服务器端口。
第九步、开始发送数据,只出现一个 >
第十步、发送获取数据的请求,得到时间数据
第十一步、未退出透传模式,发送指令返回乱码数据
退出透传模式,发送指令+++,取消发送新行,返回+++,表明退出成功
验证透传模式是都退出成功,勾选发送新行发送AT,若返回OK,证明退出透传模式成功,若返回乱码数据据,多发送几次+++(取消发送新行)。
熟悉了上面串口助手获取时间的步骤,那么下面就可以利用STM32来按照上述的步骤获取时间,如下图。
接着我们就要考虑一个问题,上面通过ESP8266获取的时间是静态的,因为你不可能一直让ESP8266连续去获取网络时间,这样我们单片机就干不了别的事情了,那么怎么获取动态时间呢?解决办法:获取一次时间之后,就通过STM32自带的定时器,利用定时器让时间动起来。
其次就是动态时间的表现方式:方式一、可以通过串口实时打印动态时间数据。方式二、借助显示屏将时间显示出来。我这里就利用方式一实现,其它花里胡哨的交给你自己。
(1)main.c文件代码
- #include "delay.h"
- #include "usart.h"
- #include "usart2.h"
- #include "esp8266.h"
- #include "timer.h"
-
- //时间数据
- extern int DAYS,MOONS,YEARS,TIMES;
- /*注意;这时间与准确时间大约存在6秒内的误差,因为STM32做计算肯定也是要时间的。 */
- /*其次:关于时间显示在其他器件上,例如:LCD,OLED等,就需要你自己动手移植显示 */
- /* 屏的驱动了。*/
-
- extern int hour_return;//小时
- extern int min_return; //分钟
- extern int sec_return; //秒数
-
-
- int main()
- {
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断控制器分组设置
- Usart1_Init(115200);
- Usart2_Init(115200);
- LED_Init();
- delay_init();//初始化很重要//用不了的函数一般都是没有初始化
- TIM3_Int_Init(10000,7199); //设置延时1s
- Get_current_time(); //获取时间
- cJSON_Time_Parse();
-
- while(1)
- {
- LED0 = 0;
- delay_ms(500);
- LED0 = 1;
- delay_ms(500);
- /*将动态的时间通过串口打印出来*/
- printf("\r\n时间数据: \r\n");
- printf("%d年%d月%d日 ",YEARS,MOONS,DAYS);
- printf("%02d:%02d:%02d \r\n",hour_return,min_return,sec_return);
-
- }
- }
(2)esp8266.c文件代码,主要是负责获取时间数据包,处理时间数据包。
- #include "stm32f10x.h"
- #include "sys.h"
- #include "string.h"
- #include "stdlib.h"
- #include "esp8266.h"
-
- #include "usart.h"
- #include "usart2.h"
-
- #include "delay.h"
- #include "led.h"
-
- /*用于保存小时,分钟,秒数的变量*/
- int hour_return;//小时
- int min_return; //分钟
- int sec_return; //秒数
-
- //WIFI和密码·
- #define ESP8266_WIFI_INFO "AT+CWJAP=\"iPhone111\",\"123456789\"\r\n"
-
- //苏宁后台获取时间的API
- #define Time_TCP "AT+CIPSTART=\"TCP\",\"quan.suning.com\",80\r\n"
- //苏宁后台获取时间GET报文
- #define Time_GET "GET http://quan.suning.com/getSysTime.do\r\n"
-
-
- //ESP8266数据存放
- unsigned char esp8266_buf[300] = {0};
- unsigned short esp8266_cnt = 0, esp8266_cntPre = 0;
- //存放时间数据
- unsigned char Time_buff[100]; //位数是随机确定的
-
-
-
- /**************************************************************************/
- //函数作用:ESP8266_Init初始化函数
- //函数名称:ESP8266_Init(void);
- //内部参数:
- //修改日期:2022年4月18日 下午16:18
- /**************************************************************************/
- void ESP8266_Init(void)
- {
- ESP8266_Clear();//清除缓冲
-
- /*让WIFI退出透传模式 要发两次*/
- while(ESP8266_SendCmd("+++", ""));//这是一个死循环,目的结束透传模式
-
- /*让WIFI清除Flah*/
- printf("0.恢复出厂设置成功\r\n");
-
- while(ESP8266_SendCmd("AT+RESTORE\r\n", "OK"));//恢复出厂设置
-
- //初始AT应答,看wifi接线是否成功
- printf("1.AT应答成功\r\n");
-
- while(ESP8266_SendCmd("AT\r\n", "OK"));
-
- //
- //加一步ESP8266复位操作
- printf("2.RST复位成功\r\n");
- ESP8266_SendCmd("AT+RST\r\n", "");
- delay_ms(500);
- ESP8266_SendCmd("AT+CIPCLOSE\r\n", "");//断开与服务器的连接
- delay_ms(500);
- /
-
- printf("3.CWMODE设置工作模式,保存到Flash\r\n");
-
- while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK"));//没有CUR就是保存到Flash,AT+CWMODE_CUR设置模块工作模式为station,不保存到Flash
-
- printf("4.AT+CIPMUX单连接模式设置成功\r\n");
-
- while(ESP8266_SendCmd("AT+CIPMUX=0\r\n", "OK"));//AT+CIPMUX=0 设置为单连接模式
-
- printf("5.寻找对应的WIFI名称和密码\r\n");
-
- while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "WIFI GOT IP"));
-
- printf("6.ESP8266_Init连接WIFI成功\r\n");
- }
-
-
-
- /**************************************************************************/
- //函数作用:获取苏宁后台时间
- //函数名称:Get_current_time();
- //内部参数:
- //修改日期:2022年4月18日 晚上20:32
- //作者: 大屁桃
- /**************************************************************************/
- void Get_current_time(void)
- {
- ESP8266_Init(); //连接Wifi的ESP8266初始化
- ESP8266_Clear();
-
- while(ESP8266_SendCmd(Time_TCP, "CONNECT"));
-
- printf("6.访问苏宁服务器成功 OK\r\n");
-
- while(ESP8266_SendCmd("AT+CIPMODE=1\r\n", "OK"));//开启透传模式
-
- printf("7.开启透传模式成功 OK\r\n");
-
- /*sizeof(Time_GET),必须用sizeof函数,用strlen没有用*/
- ESP8266_SendData((u8 *)Time_GET, sizeof(Time_GET)); //发送AT+CIPSEND 以及 Time_GET
-
- ESP8266_GetIPD_GET(200, Time_buff); //将串口数据取出来
- ESP8266_Clear();//清除缓存数据
-
- while(ESP8266_SendCmd("+++", "")); /*退出透传模式,发送两次*/
-
- printf("9.退出透传模式成功 OK\r\n");
-
- }
-
-
- /*******************************************解析时间*************************************/
- //代码来源于CSDN博客地址:https://blog.csdn.net/xgy516/article/details/119968124
- /****************************************************************************************
- 年的首地址移动11位;
- 月份首地址移动15位;
- 日期首地址移动17位;
- 小时首地址移动19位;
- 分钟首地址移动21位;
- 秒钟首地址移动23位;
- */
- #define YEAR_ADD_DRES 11
- #define MOON_ADD_DRES 15
- #define DAYS_ADD_DRES 17
-
- #define HOURS_ADD_DRES 19
- #define MINUTES_ADD_DRES 21
- #define SECONDS_ADD_DRES 23
-
- int DAYS, MOONS, YEARS, TIMES;
- ///**************************************************************************/
- 函数作用:解析苏宁时间函数
- 函数名称:cJSON_Time_Parse();
- 内部参数:
- 修改日期:2022年4月18日 下午22:11
- ///**************************************************************************/
- void cJSON_Time_Parse(void)
- {
- char *data_pt;
- char *day_string;
- char *moon_string;
- char *year_string;
- char *hour_string;
- char *minute_string;
- char *second_string;
-
-
- data_pt = strstr((const char *)Time_buff, (const char *)"sysTime1"); //寻找到时间结果的地址
-
- // printf("%s\r\n",Time_buff);
- if(data_pt != NULL)
- {
- day_string = data_pt + DAYS_ADD_DRES; //日期地址
- moon_string = data_pt + MOON_ADD_DRES; //月份地址
- year_string = data_pt + YEAR_ADD_DRES; //年份地址
- hour_string = data_pt + HOURS_ADD_DRES; //小时地址
- minute_string = data_pt + MINUTES_ADD_DRES; //分钟地址
- second_string = data_pt + SECONDS_ADD_DRES; //秒中地址
-
- //将时间信息传递给全局变量
- DAYS = Get_Day(day_string);
- MOONS = Get_Moonth(moon_string);
- YEARS = Get_Year(year_string);
- TIMES = Get_Times(hour_string, minute_string, second_string);
-
- hour_return = TIMES/3600;//小时
- min_return = (TIMES%3600)/60; //分钟
- sec_return = (TIMES%3600)%60; //秒数
- printf("时间获取并处理成功\r\n");
-
- }
- else
- {
- printf("时间获取失败\r\n");
- }
- }
-
- //得到年函数(以年开始的字符串长度过长,因此使用不一样的方法)
- //输入值是年位置的地址
- //返回值是 整型的10进制四位数
- int Get_Year(char *y)
- {
-
- int year_return;
- char *year_temp;
- char year[5] = {0};
- char i;
- //年的获取须要提取一次字符串,不然没法读取
- year_temp = y;
-
- for(i = 0; i < 4; i++)
- {
- year[i] = *year_temp;
- year_temp ++;
- }
-
- year_return = atoi(&year[0]);
- return year_return;
- }
-
- //得到月份函数
- //输入值是月份位置的地址
- //返回值是 整型的10进制两位数
- int Get_Moonth(char *m)
- {
- int moonth_return;
- moonth_return = atoi(m) / 100000000; //取月份
- return moonth_return;
- }
-
- //得到日期函数
- //输入值是日期位置的地址
- //返回值是 整型的10进制两位数
- int Get_Day(char *d)
- {
-
-
- int day_return;
- day_return = atoi(d) / 1000000; //取日期
-
- return day_return;
- }
-
- //得到时间
- //输入值是时间的位置的地址
- //返回值是 整型的10进制的时间总秒数
- int Get_Times(char *h, char *m, char *s)
- {
- int time_return;
- int hour_return;
- int min_return;
- int sec_return;
-
- hour_return = atoi(h) / 10000; //取小时
- min_return = atoi(m) / 100; //取分钟
- sec_return = atoi(s); //取秒数
-
- time_return = hour_return * 3600 + min_return * 60 + sec_return; //转换成总秒数
-
- return time_return;
- }
-
- /*****************************************************************解析苏宁时间END********************************************************************************/
- /*************************************************************************************************************************************************/
-
- /**************************************************************************/
- //函数作用:串口二中断函数
- //函数名称:USART2_IRQHandler();
- //内部参数:
- //修改日期:2022年4月18日 下午4:18
- /**************************************************************************/
- void USART2_IRQHandler(void)
- {
- if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断
- {
-
- if(esp8266_cnt >= sizeof(esp8266_buf)) esp8266_cnt = 0; //防止串口被刷爆
-
- esp8266_buf[esp8266_cnt++] = USART2->DR;
-
- // USART_SendData(USART1,USART2->DR); //让接收到的数据打印在串口一上
-
- USART_ClearFlag(USART2, USART_FLAG_RXNE);
- }
- }
- /**下面的代码来源于:
- ************************************************************
- ************************************************************
- ************************************************************
- * 文件名: esp8266.c
- *
- * 作者: 张继瑞
- *
- * 日期: 2017-05-08
- *
- * 版本: V1.0
- *
- * 说明: ESP8266的简单驱动
- *
- * 修改记录:
- ************************************************************
- ************************************************************
- ************************************************************
- **/
- //==========================================================
- // 函数名称: ESP8266_Clear
- //
- // 函数功能: 清空缓存
- //
- // 入口参数: 无
- //
- // 返回参数: 无
- //
- // 说明:
- //==========================================================
- void ESP8266_Clear(void)
- {
-
- memset(esp8266_buf, 0, sizeof(esp8266_buf));
- esp8266_cnt = 0;
-
- }
- //==========================================================
- // 函数名称: ESP8266_SendData
- //
- // 函数功能: 发送数据
- //
- // 入口参数: data:数据
- // len:长度
- //
- // 返回参数: 无
- //
- // 说明:
- //==========================================================
- void ESP8266_SendData(unsigned char *data, unsigned short len)
- {
- char cmdBuf[32];
-
- ESP8266_Clear(); //清空接收缓存
- sprintf(cmdBuf, "AT+CIPSEND\r\n"); //发送命令
-
- if(!ESP8266_SendCmd(cmdBuf, ">")) //收到‘>’时可以发送数据
- {
- printf("8.开始处于透传发送状态!\r\n");
- /*发送请求数据*/
- Usart_SendString(USART2, data, len); //发送设备连接请求数据
- }
- }
-
- //==========================================================
- // 函数名称: ESP8266_GetIPD
- //
- // 函数功能: copy天气数据到buff数组里面
- //
- // 返回参数: 平台返回的原始数据
- //
- // 说明: copy天气数据到buff
- //==========================================================
-
- unsigned char *ESP8266_GetIPD_GET(unsigned short timeOut, u8 *buff) //这里我用了一个全局变量将esp8266buf储存到这个全局变量里面
- {
- do
- {
- delay_ms(5);
- }
- while(timeOut--);
-
- strcpy((char*)buff, (char*)esp8266_buf);
- return buff;
- }
-
-
-
- //==========================================================
- // 函数名称: ESP8266_WaitRecive
- //
- // 函数功能: 等待接收完成
- //
- // 入口参数: 无
- //
- // 返回参数: REV_OK-接收完成 REV_WAIT-接收超时未完成
- //
- // 说明: 循环调用检测是否接收完成
- //==========================================================
- _Bool ESP8266_WaitRecive(void)
- {
-
- if(esp8266_cnt == 0) //如果接收计数为0 则说明没有处于接收数据中,所以直接跳出,结束函数
- return REV_WAIT;
-
- if(esp8266_cnt == esp8266_cntPre) //如果上一次的值和这次相同,则说明接收完毕
- {
- esp8266_cnt = 0; //清0接收计数
-
- return REV_OK; //返回接收完成标志
- }
-
- esp8266_cntPre = esp8266_cnt; //置为相同
-
- return REV_WAIT; //返回接收未完成标志
-
- }
-
-
- //==========================================================
- // 函数名称: ESP8266_SendCmd
- //
- // 函数功能: 发送命令
- //
- // 入口参数: cmd:命令
- // res:需要检查的返回指令
- //
- // 返回参数: 0-成功 1-失败
- //
- // 说明:
- //==========================================================
- _Bool ESP8266_SendCmd(char *cmd, char *res)
- {
-
- unsigned char timeOut = 250;
-
- Usart_SendString(USART2, (unsigned char *)cmd, strlen((const char *)cmd));
-
- while(timeOut--)
- {
- if(ESP8266_WaitRecive() == REV_OK) //如果收到数据
- {
- if(strstr((const char *)esp8266_buf, res) != NULL) //如果检索到关键词
- {
- ESP8266_Clear(); //清空缓存
-
- return 0;
- }
- }
-
- delay_ms(10);
- }
- return 1;
- }
(3)esp8266.h文件代码
- #ifndef __ESP8266_H
- #define __ESP8266_H
- #include "sys.h"
- #include "stdio.h"
-
- #define REV_OK 0 //接收完成标志
- #define REV_WAIT 1 //接收未完成标志
-
- //函数声明
- unsigned char *ESP8266_GetIPD_GET(unsigned short timeOut,u8 *buff);
-
- void ESP8266_Clear(void);
- _Bool ESP8266_WaitRecive(void);
-
- _Bool ESP8266_SendCmd(char *cmd, char *res);
- void ESP8266_SendData(unsigned char *data, unsigned short len);
-
- void ESP8266_Init(void);
- void Get_current_time(void);
-
- //解析苏宁返回数据
- void cJSON_Time_Parse(void);
- int Get_Year(char *y);
- int Get_Moonth(char *m);
- int Get_Day(char *d);
- int Get_Times(char *h, char *m, char *s);
-
- #endif
(4)usart2.c文件代码
- #include "sys.h"
- #include "usart.h"
- #include "usart2.h"
-
- #include "stdarg.h"
- #include "stdio.h"
- #include "string.h"
-
-
- /**********************************************************串口二***************************************************************/
- void Usart2_Init(unsigned int baud)
- {
-
- GPIO_InitTypeDef gpioInitStruct;
- USART_InitTypeDef usartInitStruct;
- NVIC_InitTypeDef nvicInitStruct;
-
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
-
- //PA2 TXD
- gpioInitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
- gpioInitStruct.GPIO_Pin = GPIO_Pin_2;
- gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &gpioInitStruct);
-
- //PA3 RXD
- gpioInitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
- gpioInitStruct.GPIO_Pin = GPIO_Pin_3;
- gpioInitStruct.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOA, &gpioInitStruct);
-
- usartInitStruct.USART_BaudRate = baud;
- usartInitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控
- usartInitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //接收和发送
- usartInitStruct.USART_Parity = USART_Parity_No; //无校验
- usartInitStruct.USART_StopBits = USART_StopBits_1; //1位停止位
- usartInitStruct.USART_WordLength = USART_WordLength_8b; //8位数据位
- USART_Init(USART2, &usartInitStruct);
-
- USART_Cmd(USART2, ENABLE); //使能串口
-
- USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //使能接收中断
-
- nvicInitStruct.NVIC_IRQChannel = USART2_IRQn;
- nvicInitStruct.NVIC_IRQChannelCmd = ENABLE;
- nvicInitStruct.NVIC_IRQChannelPreemptionPriority = 0;
- nvicInitStruct.NVIC_IRQChannelSubPriority = 0;
- NVIC_Init(&nvicInitStruct);
-
- }
-
-
- /******************************************************** 发送一个16位数 ************************************************/
- void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch)
- {
- uint8_t temp_h, temp_l;
-
- /* 取出高八位 */
- temp_h = (ch&0XFF00)>>8;
- /* 取出低八位 */
- temp_l = ch&0XFF;
-
- /* 发送高八位 */
- USART_SendData(pUSARTx,temp_h);
- while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
-
- /* 发送低八位 */
- USART_SendData(pUSARTx,temp_l);
- while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
- }
- /***************** 发送一个字符 **********************/
- void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
- {
- /* 发送一个字节数据到USART */
- USART_SendData(pUSARTx,ch);
-
- /* 等待发送数据寄存器为空 */
- while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
- }
-
- void Usart_SendString(USART_TypeDef *USARTx, unsigned char *str, unsigned short len)
- {
-
- unsigned short count = 0;
-
- for(; count < len; count++)
- {
- USART_SendData(USARTx, *str++); //发送数据
- while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET); //等待发送完成
- }
-
- }
- /***************** 发送字符串 **********************/
- void Usart_SendString2( USART_TypeDef * pUSARTx, char *str)
- {
- unsigned int k=0;
- do
- {
- Usart_SendByte( pUSARTx, *(str + k) );
- k++;
- } while(*(str + k)!='\0');
-
- /* 等待发送完成 */
- while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET)
- {}
- }
-
- void UsartPrintf(USART_TypeDef *USARTx, char *fmt,...)
- {
-
- unsigned char UsartPrintfBuf[296];
- va_list ap;
- unsigned char *pStr = UsartPrintfBuf;
-
- va_start(ap, fmt);
- vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap); //格式化
- va_end(ap);
-
- while(*pStr != 0)
- {
- USART_SendData(USARTx, *pStr++);
- while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);
- }
-
- }
(5)timer.c文件代码
- #include "timer.h"
- //通用定时器中断初始化
- //这里时钟选择为APB1的2倍,而APB1为36M
- //arr:自动重装值。
- //psc:时钟预分频数
- //这里使用的是定时器3!
- void TIM3_Int_Init(u32 arr,u16 psc)
- {
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
- NVIC_InitTypeDef NVIC_InitStructure;
-
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
-
- TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 计数到5000为500ms
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 10Khz的计数频率
- TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
- TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
-
- TIM_ITConfig( //使能或者失能指定的TIM中断
- TIM3, //TIM2
- TIM_IT_Update ,
- ENABLE //使能
- );
- NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
- NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
-
- TIM_Cmd(TIM3, ENABLE); //使能TIMx外设
-
- }
-
- extern int hour_return;
- extern int min_return;
- extern int sec_return;
-
- void TIM3_IRQHandler(void) //TIM3中断
- {
- if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
- {
- TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx的中断待处理位:TIM 中断源
- sec_return++;
-
- if(sec_return == 60)
- {
- sec_return = 0;
- min_return++;
- if(min_return == 60)
- {
- min_return = 0;
- hour_return ++;
- if(hour_return == 24) hour_return = 0;
- }
- }
- }
- }
下图是整个代码跑起来的功能视频。(视频不能居中)
这是这篇博客的完整的代码,工程源码。
最终得到的时间和网络时间大约相差5秒,这是因为STM32是串行执行的,因此得到数据肯定是有延迟的噻,要想很准确手动加上几秒就可以了
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。