久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 11944|回復: 7
收起左側

STM32通過GSM模塊獲取網絡時間并設置到單片機內部RTC中實現上電自動校準時間

  [復制鏈接]
ID:435174 發表于 2019-6-20 23:52 | 顯示全部樓層 |閱讀模式
        先簡單說一下實驗目的吧。平時做項目或做一些小作品的時候需要用到時間,時間用的是STM32內部的RTC,在精度要求不是特別高時這樣省去接外設時鐘模塊,省時省力。但我們都知道,RTC在斷電后數據是不保存的,也就是說如果沒有電源如電池之類一直給后備寄存器供電的話數據是會丟失的,下次開機時時間就會恢復初始化時設置的那個時間,想要時間正確就要重新設置時間,這就很不實用。所以就想通過網絡獲取時間的方式來自動校正時間。又恰好用到SIM900A這個模塊,所以查了下資料,發現已經有前輩做過了。看了https://blog.csdn.net/ludaoyi88/article/details/51757664這位博主的文章,獲取時間部分用了這位前輩提供的代碼,在他提供的代碼上進行測試和改進(直接用不修改的話是不行的。如果大家仔細對比的話會發現其實我改進后的代碼跟原版的還是有蠻多小細節不同的),最終得以達到目的,即可以通過服務器獲取到網絡的時間并自動校正到STM32內部RTC中,這里再次感謝 ludaoyi123這位前輩。大家可以先去看看這位前輩的博客,也就是上面那個鏈接,獲取時間和處理時間數據都是源于他的那篇文章。好了,接下來就說一下怎么獲取時間的吧。        此次實驗用的單片機是STM32F103C8T6核心板,串口2控制SIM900A模塊數據的收發,串口1用于在串口調試助手打印相關信息。下面是我的硬件平臺:STM32F103C8T6核心板和SIM900A模塊。

硬件平臺

硬件平臺

獲取網絡時間的第一種方法是連接到國際授時服務器,IP為:timenistgov,端口為:13,我用的連接方式是TCP連接。當客戶端連接到此服務器后,服務器會立刻發送一串格式為“58646 19-06-12 16:05:36 50 0 0 668.3 UTC(NIST) * ”這樣的字符串返回給客戶端并主動斷開連接。這一串字符串中就包含有日期和時間,我們所要做的,就是把相關的日期和時間提取出來轉換成數字就好了,這也是最最重要的部分。這里貼出我修改后的代碼:`
  1. _nowtime_obj NowTime;        //現在時間日期結構體
  2. ///*******************************************************************************
  3. //* 函數名 : Get_Sever_Time
  4. //* 描述   : 獲取Time信息(連接服務器成功情況下)
  5. //* 輸入   :
  6. //* 輸出   :
  7. //* 返回   :
  8. //* 注意   :服務器返回的數據形式如下:58646 19-06-12 16:05:36 50 0 0 668.3 UTC(NIST) *
  9. //*******************************************************************************/
  10. void Get_Sever_Time(void)
  11. {
  12.     u8 i =0;
  13.     char timestr1[200]={0};
  14.     char *timestr = timestr1;//指向timestr1地址
  15.     printf("\r\n獲取時間日期中...\r\n");
  16.     while(1)
  17.     {            
  18.         if(strstr((const char*)USART2_RX_BUF , "-") != NULL || strstr((const char*)USART2_RX_BUF , "5") != NULL )
  19.         {
  20.             timestr = strstr((const char*)USART2_RX_BUF,"5");//58646//USART2_RX_BUF 為接收緩存數組
  21.             break;
  22.         }
  23.          
  24.     }

  25.     printf("\r\n時間數組timestr的數據為");
  26.     printf((char *)timestr);   
  27.     printf("\r\n");
  28.     delay_ms(5);
  29.     //提取UTC世界時間
  30.     for(i = 0 ; i <50 ; i++)
  31.     {
  32.         if(timestr[i] == '-')
  33.         {
  34.             NowTime.year = (timestr[i-2]-'0')*10 + (timestr[i-1]-'0') + 2000;
  35.             NowTime.moon = (timestr[i+1]-'0')*10 + (timestr[i+2]-'0');
  36.             NowTime.day  = (timestr[i+4]-'0')*10 + (timestr[i+5]-'0');
  37.             NowTime.hour = (timestr[i+7]-'0')*10 + (timestr[i+8]-'0');//時差相差8
  38.             if(NowTime.hour >= 16)//北京時間新的一天
  39.             {
  40.                 NowTime.hour = (timestr[i+7]-'0')*10 + (timestr[i+8]-'0') + 8 - 24;
  41.                 NowTime.day = NowTime.day + 1;
  42.                 if(NowTime.hour == 24)
  43.                     NowTime.hour = 0;
  44.             }
  45.             
  46.             else
  47.                 NowTime.hour = (timestr[i+7]-'0')*10 + (timestr[i+8]-'0') + 8 ;//時差相差8
  48.             
  49.             NowTime.minu = (timestr[i+10]-'0')*10 + (timestr[i+11]-'0');
  50.             NowTime.sec  = (timestr[i+13]-'0')*10 + (timestr[i+14]-'0') + 2;//2是返回數據到處理處結果的誤差

  51.             sprintf((char*)TimeRTC,"AT+CCLK=\"%d/%02d/%02d,%02d:%02d:%02d+08\"\r\n",NowTime.year,NowTime.moon,NowTime.day,NowTime.hour,NowTime.minu,NowTime.sec);            
  52.             //轉換成RTC時間格式           
  53.             break;
  54.         }
  55.     }

  56.    
  57.     printf("\r\n當前時間:%d年%02d月%02d日%02d時%02d分%02d秒\r\n",NowTime.year,NowTime.moon,NowTime.day,NowTime.hour,NowTime.minu,NowTime.sec);
  58.    
  59.     printf("\r\n寫入SIM900A設置時間的字符串為:");
  60.     printf((char *)TimeRTC);
  61.     printf("\r\n");
  62.     if(NowTime.year!=0&&NowTime.moon!=0&&NowTime.day!=0&&NowTime.hour!=0&&NowTime.minu!=0)//獲取到正確數據
  63.     {
  64.         RTC_Set(NowTime.year,NowTime.moon,NowTime.day,NowTime.hour,NowTime.minu,NowTime.sec);  //設置STM32單片機內部RTC時間
  65.         Set_SIM900A_RTCtime();//給GSM模塊設置從網絡獲取來的時間
  66.     }
  67.     else
  68.         printf("\r\n沒能在服務器獲取到正確時間,復位重試一下\r\n");
  69.    
  70.     delay_ms(500);
  71.     Get_GSM_RTCtime();//用串口查看一下GSM模塊時間正常了沒有
  72.     sim900a_send_cmd("AT+CIPSHUT\r\n","SHUT OK",2); //關閉連接
  73.     delay_ms(300);
  74.     AT_DataInit();//清除接收數組
  75.     CLR_Buf2();
  76.     delay_ms(200);

  77. }
復制代碼
代碼內容很簡單,就是連接上服務器后用strstr函數和字符“-”或者“5”比較串口2接收數組中的“58646 19-06-12 16:05:36 50 0 0 668.3 UTC(NIST) * ”這串字符串,如果串口二接收數組中接收到了這一串字符串,那個就將這串字符串保存到數組timestr中并跳出死循環。實驗過程中發現最容易出現問題的就是這一塊,也就是有時候串口2沒能收到完整的字符串導致程序死在死循環里面,應該是串口2中斷服務函數沒寫好。接到完整的字符串后,接下來接著把年月日時分秒提取出來,把字符變成數字并做判斷轉換成北京時間,當服務器中的小時大于或等于16時當地小時+8-24,且天數+1,否則小時只是單純地+8,這個8就是時差。數據處理好后就給STM32內部的RTC設置時間和給GSM模塊的RTC設置時間,后續如果要重新校正時間的話只需要在SIM900A內部獲取RTC的時間就可以了。實驗過程中相關信息在串口調試助手顯示,結果如下圖所示:

測試結果一

測試結果一


一次成功不代表什么,所以又在不同時間段多次測試:

測試結果二

測試結果二

測試三

測試三

測試四

測試四


測試結果表明,實驗是成功的,也就是在SIM900A連接到服務器后可以獲取到正確時間并校正到RTC中。

但測試的過程中發現上面連接服務器的方法并不是最佳的,原因是連接服務器不是很好用,有時候需要六七秒就能連上,有時候要半分多鐘才能連上,感覺不可靠,就像刷臉一樣,而且,有時候辛辛苦苦連上了,串口2還不能完完整整接收到那串字符串。。。所以,提供了第二個獲取時間的方法,也就是直接從SIM900A內部獲取時間日期,下面貼上代碼:

  1. _rtctime_obj RTCTime;        //SIM900A時間日期結構體
  2. /*******************************************************************************
  3. * 函數名 : Get_GSM_RTCtime(void)
  4. * 描述   : 獲取SIM900A模塊中RTC的時間
  5. * 輸入   :
  6. * 輸出   :
  7. * 返回   :RTCTime的時間結構體--年月日時分秒
  8. * 注意: 如:"19/06/18,13:11:52+08";
  9. *******************************************************************************/
  10. void Get_GSM_RTCtime(void)//直接從GSM模塊內部獲取時間,初次上電時需要手動復位
  11. {
  12.     u8 i = 0;
  13.     char timestr1[50]={0};
  14.     char *timestr = timestr1;//指向timestr1地址

  15.     AT_DataInit();//清除接收數組
  16.     sim900a_send_cmd("AT+CCLK?\r\n","OK",5);
  17.     delay_ms(1000);
  18.     printf("\r\n獲取SIM900A內部時間日期中...\r\n");
  19.     while(1)
  20.     {
  21.    if(strstr((const char*)USART2_RX_BUF , "+CCLK") != NULL )
  22.    {
  23.       timestr = strstr((const char*)USART2_RX_BUF , "+CCLK");
  24.       break;
  25.   }
  26.     }
  27.     delay_ms(500);

  28.     for(i = 0 ; i <50 ; i++)
  29.     {
  30.         if(timestr[i] == '/')
  31.         {
  32.     RTCTime.year = (timestr[i-2]-'0')*10 + (timestr[i-1]-'0') + 2000;
  33.     RTCTime.moon = (timestr[i+1]-'0')*10 + (timestr[i+2]-'0');
  34.     RTCTime.day= (timestr[i+4]-'0')*10 + (timestr[i+5]-'0');
  35.     RTCTime.hour = (timestr[i+7]-'0')*10 + (timestr[i+8]-'0');
  36.     RTCTime.minu = (timestr[i+10]-'0')*10 + (timestr[i+11]-'0');
  37.     RTCTime.sec = (timestr[i+13]-'0')*10 + (timestr[i+14]-'0');
  38.     break;
  39.         }
  40.     }
  41.     printf("\r\nGSM內部時間:%d年%02d月%02d日%02d時%02d分%02d秒\r\n",RTCTime.year,RTCTime.moon,RTCTime.day,RTCTime.hour,RTCTime.minu,RTCTime.sec);
  42.     RTC_Set(RTCTime.year,RTCTime.moon,RTCTime.day,RTCTime.hour,RTCTime.minu,RTCTime.sec);  //設置STM32單片機內部RTC時間
  43.     AT_DataInit();//清除接收數組
  44.     memset(USART2_RX_BUF,0,USART2_MAX_RECV_LEN);
  45. }
復制代碼
這代碼跟上面的差不多,這里就不重復解釋了,也很容易看懂。用法是直接在主函數調用就行了。需要注意的是,板子初次上電時需要手動復位一下單片機,不然串口發送AT+CCLK?命令給SIM900A模塊時它不會返回字符串。這里的代碼也是上面提到的那位博主提供我再進行小小修改的,我只是代碼搬運工。然后發現用AT+CCLK?指令查詢時間并沒有網上說的那樣不能用,反而覺得更好用,個人比較推薦這種方法。其效果圖如下所示:

直接獲取GSM內部時間.png
下面給出main.c和串口2配置及中斷服務函數代碼,請各路大神批評指正,提出寶貴意見。

  1. /**
  2.   ******************************************************************************
  3.   * @file    main.c
  4.   * @author  GXNU_LPK
  5.   * @version V1.0
  6.   * @date    2019-06-17
  7.   * @brief   用3.5.0版本庫建的工程模板
  8.   ******************************************************************************
  9.   * @attention
  10.   *
  11.   * 實驗平臺: STM32F103CT6核心板
  12.   * 實驗內容:GSM(SIM900A)模塊通過服務器實現網絡授時
  13.   * 實驗作者:廣西師范大學電子工程學院2015LPK
  14.   * 備    注:Get_net_time.c這部分的代碼來源于https://blog.csdn.net/ludaoyi88/article/details/51757664 ,
  15.   *           根據此ludaoyi123博主提供的思路和代碼進行測試和修改而來,經實驗測試和改善后目前已初步達到實驗目的,但
  16.   *           通過服務器獲取時間那種方法 穩定性方面略微存在一些欠缺,請學習者自行改善,僅供學習,不得用于其他用途
  17.   ******************************************************************************
  18.   */
  19.   
  20. #include "stm32f10x.h"
  21. #include "GSM.h"
  22. #include "AT_Cmd.h"
  23. #include "usart2.h"
  24. #include "usart1.h"
  25. #include "delay.h"
  26. #include "string.h"
  27. #include "rtc.h"
  28. #include "Get_net_time.h"
  29. /**
  30.   * @brief  主函數
  31.   * @param  無
  32.   * @retval 無
  33.   */
  34. int main(void)
  35. {
  36.     u8 res;
  37.    
  38.     delay_init();
  39.     Usart2_Init(115200);        //初始化串口2
  40.     delay_ms(3);
  41.     Usart1_Init(115200);        //初始化串口1
  42.    
  43.     if(RTC_Init()==0)
  44.         printf("RTC初始化成功\r\n");
  45.     else
  46.         printf("RTC初始化失敗\r\n");
  47.    
  48.     printf("初始化SIM900A中...\r\n");
  49.    
  50.     res=1;
  51.         while(res)
  52.         {
  53.                 res=GSM_Dect();
  54.                 delay_ms(2000);
  55.         }
  56.     res=1;
  57.         while(res)
  58.         {
  59.         res=SIM900A_CONNECT_SERVER_SEND_INFOR((u8*)"time.nist.gov",(u8*)"13");//連接授時服務器(國外)
  60.         }
  61.     Get_Sever_Time();//提取獲取到的時間并存入STM32和GSM模塊內部RTC中
  62. //    Get_GSM_RTCtime();//直接從GSM模塊內部獲取時間,初次上電時需要手動復位
  63.    
  64.     printf("\r\n系統初始化完成\r\n");
  65.             while(1)
  66.       {
  67.           display_time();//顯示STM32內部RTC的時間
  68.           delay_ms(1000);
  69.       }

  70.    
  71. }

  72. /*********************************************END OF FILE**********************/
復制代碼
下面是串口2配置及中斷服務函數代碼:
  1. #include "usart2.h"
  2. #include "stdio.h"         
  3. #include "string.h"        
  4. #include "stdarg.h"        

  5. //串口接收緩存區         
  6. u8 USART2_RX_BUF[USART2_MAX_RECV_LEN];                                 //接收緩沖,最大USART2_MAX_RECV_LEN個字節.
  7. u8 USART2_TX_BUF[USART2_MAX_SEND_LEN];                           //發送緩沖,最大USART2_MAX_SEND_LEN字節
  8. u16 USART2_RX_STA=0;  

  9. /*
  10.   功能描述: 發送一個字節
  11.   函數參數: byte —— 要發送的字節
  12.   返回說明: 無
  13. */
  14. void UART2_SendByte(unsigned char byte)        
  15. {
  16.         USART_SendData(USART2,byte);//向串口2發送數據
  17.         while(USART_GetFlagStatus(USART2,USART_FLAG_TC)!=SET);//等待發送結束
  18. }

  19. /*
  20.   功能描述: 串口發送字符串
  21.   函數參數: s —— 指向字符串的指針(字符串以'\0'結尾)
  22.   返回說明: 無
  23.   注:如果在字符串結尾有'\n',則會發送一個回車換行      
  24. */
  25. void UART2_SendStr(char *s)
  26. {
  27.         while( *s != '\0')
  28.         {
  29.                 UART2_SendByte( *s );        
  30.                 s ++;
  31.         }
  32. }

  33. void Usart2_Init(unsigned int bps)
  34. {
  35.         USART_InitTypeDef USART_InitStructure;
  36.         GPIO_InitTypeDef GPIO_InitStructure;
  37.         NVIC_InitTypeDef NVIC_InitStructure;
  38.         
  39.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  40.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
  41.         USART_DeInit(USART2);
  42.         
  43.         GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
  44.         GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;         //TX  PA2
  45.         GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
  46.         GPIO_Init(GPIOA,&GPIO_InitStructure );      
  47.         
  48.         GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
  49.         GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3;         //RX  PA3
  50.         GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz;
  51.         GPIO_Init(GPIOA,&GPIO_InitStructure );
  52.         
  53.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  54.         
  55. //        NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;
  56.     NVIC_InitStructure.NVIC_IRQChannel=USART2_IRQn;
  57.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0x01 ;
  58.         NVIC_InitStructure.NVIC_IRQChannelSubPriority= 1 ;
  59.         NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
  60.         NVIC_Init(&NVIC_InitStructure);
  61.         
  62.         USART_InitStructure.USART_BaudRate=bps;
  63.         USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
  64.         USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
  65.         USART_InitStructure.USART_Parity=USART_Parity_No;
  66. //        USART_InitStructure.USART_StopBits=USART_StopBits_1;
  67.     USART_InitStructure.USART_StopBits=USART_StopBits_2;
  68.         USART_InitStructure.USART_WordLength=USART_WordLength_8b;
  69.         USART_Init(USART2,&USART_InitStructure );
  70.         
  71. //        USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
  72.     USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);
  73.         
  74.         USART_Cmd(USART2,ENABLE);
  75. }

  76. //串口2,printf 函數
  77. //確保一次發送數據不超過USART2_MAX_SEND_LEN字節
  78. void u2_printf(char* fmt,...)  
  79. {  
  80.         u16 i,j;
  81.         va_list ap;
  82.         va_start(ap,fmt);
  83.         vsprintf((char*)USART2_TX_BUF,fmt,ap);
  84.         va_end(ap);
  85.         i=strlen((const char*)USART2_TX_BUF);                //此次發送數據的長度
  86.         for(j=0;j<i;j++)                                                        //循環發送數據
  87.         {
  88.           while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET); //循環發送,直到發送完畢   
  89.                 USART_SendData(USART2,USART2_TX_BUF[j]);
  90.         }
  91. }



  92. extern void AT_RecvProcess(unsigned char byte);

  93. //void USART2_IRQHandler(void)                        //串口2中斷服務程序
  94. //{
  95. //        u8 Res;
  96. //        if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)  //接收中斷(接收到的數據必須是0x0d 0x0a結尾)
  97. //        {
  98. //        USART_ClearITPendingBit(USART2,USART_IT_RXNE); //清除中斷標志位
  99. //                Res =USART_ReceiveData(USART2);//(USART2->DR);        //讀取接收到的數據
  100. //                AT_RecvProcess(Res);

  101. //        if(USART2_RX_STA < USART2_MAX_RECV_LEN)                //還可以接收數據
  102. //                {                                   
  103. //                        USART2_RX_BUF[USART2_RX_STA]=Res;                //記錄接收到的值
  104. //            USART2_RX_STA++;
  105. //                }
  106. //                else
  107. //                {                                
  108. //            USART2_RX_STA=USART2_MAX_RECV_LEN;//強制標記接收完成
  109. //                }
  110. //    }
  111. //}         


  112. void USART2_IRQHandler(void)        
  113. {
  114.          u8 clear=clear;
  115.          USART_ClearFlag(USART2,USART_FLAG_TC);

  116.          if(USART_GetITStatus(USART2,USART_IT_RXNE)!=Bit_RESET)        
  117.            {
  118.            AT_RecvProcess(USART2->DR);
  119.            USART2_RX_BUF[USART2_RX_STA++]=USART2->DR;
  120.            USART_ClearFlag(USART2,USART_FLAG_ORE);//讀SR
  121.            }
  122.                  
  123.          else if(USART_GetFlagStatus(USART2,USART_FLAG_IDLE)!=Bit_RESET)
  124.                 {                                       
  125.                 clear=USART2->SR;
  126.                 clear=USART2->DR;                                                
  127.                 USART2_RX_STA=0;
  128.             }                                                
  129. }
復制代碼
以上就是SIM900A獲取網絡時間的兩種小方法,不足之處請批評指正,不喜勿噴,謝謝~

沒有黑幣或黑幣不足的的完整工程下載鏈接:https://download.csdn.net/download/qq_36112455/11247378

有黑幣的可以從附件直接下載。
工程資源簡介:用STM32F103單片機控制SIM900A模塊通過連接國外的授時服務器或者訪問SIM900A內部獲取網絡時間,把獲得的時間設置到STM32內部的RTC中,實現單片機上電自動校正時間。時間在串口上顯示出來。資源是完整的工程,里面包含了SIM900A的驅動和常用的撥打電話發短信連接到服務器等等功能;另工程里面也有STM32 RTC的驅動,可通過編譯等獲取電腦上的時間,也可下載下來學習一下。程序測試多次可用,歡迎大家留言評論,一起探討,共同進步。
版權所有,轉載請注明出處,謝謝!代碼僅供學習,不得用于其他用途。

GSM通過服務器或內部網絡授時.7z

767.08 KB, 下載次數: 77, 下載積分: 黑幣 -5

評分

參與人數 1黑幣 +6 收起 理由
6789364 + 6 很給力!

查看全部評分

回復

使用道具 舉報

ID:355468 發表于 2019-10-27 17:54 | 顯示全部樓層
"TCP","time.nist.gov","13"  發完后回來數據是   IIII  這樣的,怎么回事?,之前成功過
回復

使用道具 舉報

ID:435174 發表于 2019-10-31 21:09 來自手機 | 顯示全部樓層
lis。ss 發表于 2019-10-27 17:54
"TCP","time.nist.gov","13"  發完后回來數據是   IIII  這樣的,怎么回事?,之前成功過

別用服務器的方式獲取了,不穩定不可靠,老是莫名其妙出現奇奇怪怪的問題。用我說的第二種方法直接從SIM卡獲取時間吧
回復

使用道具 舉報

ID:613800 發表于 2019-12-30 13:34 | 顯示全部樓層
獲取時間不穩定嗎??SIM卡或者時間是怎么做的?
回復

使用道具 舉報

ID:435174 發表于 2020-1-3 00:18 | 顯示全部樓層
qq1182560902 發表于 2019-12-30 13:34
獲取時間不穩定嗎??SIM卡或者時間是怎么做的?

從SIM卡獲取妥妥的,服務器不穩。 AT指令集你去查一下  AT+CCLK?
回復

使用道具 舉報

ID:435174 發表于 2020-1-23 23:30 | 顯示全部樓層
lis。ss 發表于 2019-10-27 17:54
"TCP","time.nist.gov","13"  發完后回來數據是   IIII  這樣的,怎么回事?,之前成功過

現在回頭看了下,你這個問題是串口2中斷接收沒處理好造成的。如果不想改中斷服務函數的話就在void Get_Sever_Time(void)函數下把所有USART2_RX_BUF改成AT_RecvBuffer可以解決此問題,而且再也不會出現上文提到的那些確定,我今晚用SIM800C測過好幾遍了,沒問題,很好用。你可以試下。
回復

使用道具 舉報

ID:435174 發表于 2020-1-23 23:40 | 顯示全部樓層
Linux— 發表于 2020-1-3 00:18
從SIM卡獲取妥妥的,服務器不穩。 AT指令集你去查一下  AT+CCLK?

現在回頭看了下,其實用服務器那種方式還是很穩的,只需要小小改動一下,在void Get_Sever_Time(void)函數下把所有USART2_RX_BUF改成AT_RecvBuffer就好了,克服了上文說的那些缺點,今晚測試過好多次了,沒有失敗過,每次都成功。而且連接服務器的速度其實是跟信號有關的,之前那個地方信號太弱了,導致連接速度比較慢,在信號好的地方一下子就連上了。還有,AT+CCLK?只是獲取模塊的內部時間,斷電重新上電后還是要從網絡獲取時間同步進去的,不然也是不準的。此外,獲取網絡時間和日期也可以用GPRS基站定位,從返回的字符串中把時間數據解析出來就行了。這個方法我也測過了,是能用的,但對信號強度要求更高,不然網絡沒配置好的話也是定位不到進而獲取不了數據的。

評分

參與人數 1黑幣 +30 收起 理由
admin + 30 回帖助人的獎勵!

查看全部評分

回復

使用道具 舉報

ID:435174 發表于 2020-2-5 20:59 | 顯示全部樓層
本帖最后由 Linux— 于 2020-2-5 21:41 編輯

各位,我又找到了一種方法,數據手冊上提到的。封裝成函數就是這樣的,親測可用:
函數如下:
  1. u8 Synchro_NTP_Time(void)//同步時間
  2. {   
  3.     printf("\r\n正在同步網絡\r\n");
  4.         if(sim900a_send_cmd("AT+SAPBR=3,1,\"CONTYPE\",\"GPRS\"\r\n","OK",100))   //設置網絡參數
  5.         {
  6.             printf("設置網絡參數失敗\r\n");
  7.             return 1;
  8.         }

  9.       if(sim900a_send_cmd("AT+SAPBR=3,1,\"APN\",\"UNIWAP\"\r\n","OK",500))  //設置APN
  10.       {
  11.           printf("設置APN失敗\r\n");
  12.           return 2;
  13.       }
  14.        if( sim900a_send_cmd("AT+SAPBR=1,1\r\n","OK",200))//激活網絡場景
  15.        {
  16.             printf("激活網絡場景失敗\r\n");
  17. //           sim900a_send_cmd("AT+CGATT=1\r\n","OK",200);
  18.            return 3;
  19.        }

  20.         if(sim900a_send_cmd("AT+SAPBR=2,1\r\n","OK",600))   //獲取分配的ip地址
  21.         {
  22.             printf("獲取分配的IP地址失敗\r\n");
  23.             return 4;
  24.         }

  25.         if(sim900a_send_cmd("AT+CNTP=\"ntp1.aliyun.com\",32\r\n","OK",200)) //設置NTP服務地址和時區(阿里云的NTP)
  26.         {
  27.             printf("設置NTP服務地址和時區失敗\r\n");
  28.             return 5;      
  29.         }

  30.         if(sim900a_send_cmd("AT+CNTP\r\n","CNTP: 1",500))  //開啟網絡同步
  31.         {
  32.             printf("開啟網絡同步失敗\r\n");
  33.             return 6;     
  34.         }  
  35.         printf("\r\n網絡同步成功!\r\n");
  36.         Get_GSM_RTCtime();
  37.         
  38.         return 0;
  39. }


復制代碼

只要模塊注冊到了網絡,一下子就同步到網絡了,GSM模塊內部時間也自動對齊網絡時間了。模塊有信號能注冊到網絡的話一秒鐘就搞定了,還是很快的。調用的時候可以讓它循環執行,若是不成功,設置失敗次數達到10次就跳出就好了。若是失敗的話估計就是在關閉網絡場景那一步,其他的沒啥問題。下面是我在串口調試助手顯示的內容:
  1. AT
  2. OK
  3. AT+CPIN?
  4. READY
  5. GSM模塊自檢成功
  6. AT+CCLK?
  7. CCLK: "04/01/01,00:00:05+0
  8. 獲取SIM900A內部時間日期中...
  9. AT+CCLK?
  10. CCLK?

  11. +CCLK: "04/01/01,00:00:05+0
  12. 模塊返回時間數據:CCLK?

  13. +CCLK: "04/01/01,00:00:05+08"

  14. OK

  15. SMS Ready
  16. AT+CCLK?

  17. +CCLK: "04/01/01,00:00:05+08"

  18. OK

  19. 數據轉換成功

  20. GSM內部時間:2004年01月01日00時00分05秒
  21. 系統初始化完畢!

  22. 進入同步網絡模式

  23. 正在同步網絡
  24. AT+SAPBR=3,1,"CONTYPE","GPRS"
  25. OK
  26. AT+SAPBR=3,1,"APN","UNIWAP"
  27. OK
  28. AT+SAPBR=1,1
  29. OK
  30. AT+SAPBR=2,1
  31. OK
  32. AT+CNTP="ntp1.aliyun.com",32
  33. OK
  34. AT+CNTP
  35. CNTP: 1

  36. 網絡同步成功!
  37. AT+CCLK?
  38. CCLK: "20/02/05,20
  39. 獲取SIM900A內部時間日期中...
  40. AT+CCLK?
  41. CCLK?

  42. +CCLK: "20/02/05,20
  43. 模塊返回時間數據:CCLK?

  44. +CCLK: "20/02/05,20:33:05+08"

  45. OK
  46. AT+CCLK?

  47. +CCLK: "20/02/05,20:33:05+08"

  48. OK

  49. 數據轉換成功

  50. GSM內部時間:2020年02月05日20時33分05秒
復制代碼


可以看到模塊剛開機初始化完成時內部時間是2004年01月01日00時00分05秒,同步網絡后時間自動更新到當前時間:2020年02月05日20時33分05秒 了。有興趣的各位不妨試試。相關的截圖和NTP同步的手冊截圖請看博客https://blog.csdn.net/qq_36112455/article/details/92798026。因為這里的我不懂怎么在評論添加圖片。
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 在线观看国产视频 | 国产精品久久欧美久久一区 | 免费成人av| 羞羞视频网站免费观看 | 91成人在线 | 99精品一区| 国产亚洲一区二区三区 | 日韩一区精品 | 午夜视频网 | 欧美大片黄 | 日韩超碰在线 | 黄色网址在线免费播放 | 亚洲 欧美 在线 一区 | 欧美一区二区在线观看视频 | 亚洲一区 | 伊人爽| 无码日韩精品一区二区免费 | 一色一黄视频 | 黄色在线免费观看视频网站 | 伊人久久伊人 | 欧美一级片中文字幕 | 91在线免费视频 | 国产精品夜间视频香蕉 | 二区三区在线观看 | 干一干操一操 | 欧美在线免费 | 日韩av高清在线 | 国产精品久久久久久福利一牛影视 | 国产精品一区免费 | 久久久国产精品入口麻豆 | 欧美在线一区二区三区 | 99亚洲精品 | 欧美自拍日韩 | 久久久精品一区 | aa级毛片毛片免费观看久 | 欧美 日韩 国产 成人 | 亚洲免费精品一区 | 亚洲福利网 | 黄a免费网络 | 国产精品久久av | 欧美激情国产精品 |