justtest111 发表于 2015-8-28 08:37

同关注,学习一下。

datouyuan 发表于 2015-8-29 11:58

标记一下,关注中

kangbidz 发表于 2015-8-29 16:32

需要晶振请找康比电子

forthlab 发表于 2015-8-30 22:12

好文,如何收藏啊?

我是土匪 发表于 2015-8-31 11:09

本帖最后由 我是土匪 于 2015-9-18 17:17 编辑

更新GPRS开、关机代码:

enum
{
    GPRS_POWERON_STAR = 0,//拉低POWERKEY开始
    GPRS_POWERON_END ,               //拉低POWERKEY结束,认为开机动作结束
    GPRS_SYNC,                         //GPRS串口同步成功,成功开机
    GPRS_POWEROFF_STAR,   //开始关机,拉低POWERKEY
    GPRS_POWEROFF_END                //断电
};
#define GPRS_POWERKEY_OUTPUT_LOW()      GPIO_WriteBit(GPRS_POWERKEY_PORT, GPRS_POWERKEY_PIN, SET)
#define GPRS_POWERKEY_OUTPUT_HIGH()   GPIO_WriteBit(GPRS_POWERKEY_PORT, GPRS_POWERKEY_PIN, RESET)

#define GPRS_VBAT_ON()      GPIO_WriteBit(GPRS_POWER_PORT, GPRS_POWER_PIN, SET)
#define GPRS_VBAT_OFF()   GPIO_WriteBit(GPRS_POWER_PORT, GPRS_POWER_PIN, RESET)

#define STATUS_LED_ON()GPIO_WriteBit(LED_STATUS_PORT, LED_STATUS_PIN,LED_ON)
#define STATUS_LED_OFF()   GPIO_WriteBit(LED_STATUS_PORT, LED_STATUS_PIN,LED_OFF)
#define GPRS_POWER_CTR_EN //使能电源控制
/********************************************
执行开机动作(powerkey)后,发送AT去同步模块串口,最多重复3次,大于3依旧没同步上,证明本次开机失败,或者断电重启或者报警处理等。
发送:AT\r\n
返回:OK\r\n 则表示同步成功
*********************************************/
void Sent_AT(void)
{
    static char count = 0;
    const char AT_cmd[]="AT\r\n";

    if((GPRS_POWERON_STAR == Gprs_Status) || (GPRS_POWERON_END == Gprs_Status))
    {
      count ++;

      if(count > 3)
            {
            bsp_StopTimer(GPRS_SYNC_TIMER_ID);
            count = 0;
                /*
                本次开机失败,添加自己代码,断电重启,或其他处理
                */
            }
      else
            {
            Sent_String((char *)AT_cmd,strlen(AT_cmd));
            }      
    }
    else
    {
      bsp_StopTimer(GPRS_SYNC_TIMER_ID);
    }
}
/* ----------------------------------------------------------------------------
检测status引脚状态:PD4
1开机
0关机
----------------------------------------------------------------------------- */
char Check_GPRS_StatusPIN(void)
{
   char status = 0;

   status = GPIOD->IDR & GPIO_Pin_4;

   return (status?1:0);
}
/* ----------------------------------------------------------------------------
GPRS关机延时
POWER\断电和状态切换
----------------------------------------------------------------------------- */
void PowerOff_Gprs_Dely(void)
{

    GPRS_POWERKEY_OUTPUT_HIGH();      //POWERKEY PULL UP
    /*断电*/
    #ifdef GPRS_POWER_CTR_EN   
      GPRS_VBAT_OFF();
   #endif
    Gprs_Status = GPRS_POWEROFF_END;
}
/* ----------------------------------------------------------------------------
流程:
GPRS上电->延时200mS->拉低POWERKEY->3S后拉起POWERKEY->5S后AT去同步串口
----------------------------------------------------------------------------- */
volatile char PowerOn_GPRS_Count = 0;
#define POWERON_DELY30

void PowerOn_GPRS(void)
{
    if((GPRS_POWEROFF_STAR == Gprs_Status) || (GPRS_POWEROFF_END == Gprs_Status))
    {
      bsp_StopTimer(GPRS_POWEROFF_ID); //如果正在关机,停止该进程

        #ifdef GPRS_POWER_CTR_EN
      GPRS_VBAT_ON();//供电
            
      /* 供电需持续一段时间 ,相当于delyMs(200)*/
      PowerOn_GPRS_Count = 0;
      while(PowerOn_GPRS_Count < POWERON_DELY);//经验值,200ms左右
      #endif                

            
      GPRS_POWERKEY_OUTPUT_LOW();//开始拉低POWERKEY

      //定时3s( >1.2S),定时到拉起POWERKEY
      bsp_StopTimer(POWERKEY_LOW_TIMERID);
      bsp_StartTimer(POWERKEY_LOW_TIMERID, POWERKEY_LOW_TIMERPERIOD, (bspTimerHandler)PullUp_PowerKey);
             //单次执行的定时器

      //定时5S(>3.2S)判断单片机和GPRS模块是否同步成功:         AT
      bsp_StopTimer(GPRS_SYNC_TIMER_ID);
      bsp_StartAutoTimer(GPRS_SYNC_TIMER_ID, GPRS_SYNC_TIMEPERIOD,(bspTimerHandler)Sent_AT);//周期性的定时器   

      Gprs_Status = GPRS_POWERON_STAR;
            
      //避免串口串电,如果控制电源,有必要这样做。
      #ifdef GPRS_POWER_CTR_EN
             USART_Config();
      #endif
    }         

}
/* ----------------------------------------------------------------------------
关机流程:
拉低POWERKEY ->6S后拉高POWERKEY->断电
(关机拉低1S以上模块会关机,6S左右会彻底关机,此时断电对模块不会造成伤害)
----------------------------------------------------------------------------- */
void PowerOff_GPRS(char cmd)
{
       BitStatus res = 0;

    if((GPRS_POWEROFF_STAR != Gprs_Status) || (GPRS_POWEROFF_END != Gprs_Status))
    {
      //开始拉低POWERKEY
      GPRS_POWERKEY_OUTPUT_LOW();
      Gprs_Status = GPRS_POWEROFF_STAR;
      bsp_StopTimer(GPRS_POWEROFF_ID);
      bsp_StartTimer(GPRS_POWEROFF_ID, POWEROFF_GPRS_TIMERPERIOD, (bspTimerHandler)PowerOff_Gprs_Dely);
    }      
   Led_Cmd = LED_OFF;
}   
/* ----------------------------------------------------------------------------
开机时序中拉起POWERKEY功能
----------------------------------------------------------------------------- */
void PullUp_PowerKey(void)
{
    GPRS_POWERKEY_OUTPUT_HIGH();
    Gprs_Status = GPRS_POWERON_END;
}

   

我是土匪 发表于 2015-8-31 11:28

使用举例:
MCU每1分钟进入一次RTC中断,一次开机,一次关机,周而复始,整个开关机过程通过LED指示:
/* ----------------------------------------------------------------------------
外设做初始化
------------------------------------------------------------------------------*/
void Hardware_Init(void)
{
      LED_INIT();
      TIM4_Config();//作为时间基准
      RTC_Config();
      GPIO_Init(GPRS_POWERKEY_PORT, GPRS_POWERKEY_PIN, GPIO_Mode_Out_PP_Low_Slow);
      GPIO_Init(LED_STATUS_PORT, LED_STATUS_PIN, GPIO_Mode_Out_OD_HiZ_Slow);
      GPIO_Init(LED_STATUS_PORT, LED_STATUS_PIN, GPIO_Mode_Out_OD_HiZ_Slow);

       #ifdef GPRS_POWER_CTR_EN
       GPIO_Init(GPRS_POWER_PORT, GPRS_POWER_PIN, GPIO_Mode_Out_PP_Low_Slow);

      //串口引脚输出0,防止串电。       
       GPIO_Init(GPIOC,GPIO_Pin_2,GPIO_Mode_Out_OD_Low_Slow);
       GPIO_Init(GPIOC,GPIO_Pin_3,GPIO_Mode_Out_OD_Low_Slow);
    #elif
      USART_Config();
   #endif
}

#define WAKEUP_PEROID 60 //60s
void main(void)
{
       static char count = 0;

      PowerOn_Sys();
      Hardware_Init();
      enableInterrupts();

      Param_Init();
      bsp_InitTimer();
         Init_AlarmTime(WAKEUP_PEROID);//60s后触发中断

      while(1)
      {        
            bsp_TimerOutHandler();

            if(Rtc_flag)//60S一次中断,第一次开机,
             {
               Rtc_flag = 0;
               Init_AlarmTime(WAKEUP_PEROID);
                      
               if(count % 2 == 0)
                    {
                     PowerOff_GPRS();
                    }
              else
                    {
                PowerOn_GPRS();
                       }
                  count ++;
               }
      //RX,判断开机成功与否
          if(Rx_Flag)
          {
                  Rx_Flag = 0;
                  Deal_Rx_FromGprs();
          }
    }

}



我是土匪 发表于 2015-8-31 11:33

void Deal_Rx_FromGprs(void)
{
    //下拉POWERKEY过程GPRS可能开机成功
    if((GPRS_POWEROFF_END != Gprs_Status)|| (GPRS_POWEROFF_STAR == Gprs_Status))
    {
            if(strstr((char*)Rx_Data.buf,"OK\r\n"))
              {
                Gprs_Status = GPRS_SYNC;
            Led_Cmd = LED_ON;
              }       
   
    //固定波特率的情况下,开机或模块发生重启时会主动上报RDY
      if(strstr((char*)Rx_Data.buf,"RDY\r\n"))
              {
                Gprs_Status = GPRS_SYNC;
             Led_Cmd = LED_ON;
              }
    }   
      CLear_RxBuf();
}

我是土匪 发表于 2015-8-31 11:52

土匪建议:
1、如果模块不需要开关机控制,会简单很多,开机后就不需要再做多余处理。
2、如果模块涉及频繁开关及控制,比如低功耗模式一小时工作一次,最佳方案控制模块电源,关机最后一定要断电,不仅仅是省电,而且稳定。
模块的POWERKEY引脚开机时序和关机时序是相同的,如果判断错误或逻辑错误,开机和关机会颠倒、系统会混乱。而加了电源管理,关机后断电,彻底,放心。
3、如何控制模块电源,如果采用LM2596或者MIC29302这类电源芯片均有电源输出使能引脚,如果LI电池供电,可以考虑直接用MOS管控制。

我是土匪 发表于 2015-8-31 12:03

本帖最后由 我是土匪 于 2015-8-31 13:55 编辑

周末之前再更新:如何使用AT命令。

huarana 发表于 2015-9-1 11:36

好**,必须支持,

期待大作不断更新。

叶秋 发表于 2015-9-2 17:41

学习一下!

sfofyyy 发表于 2015-9-2 21:56

学习了,期待更新

guigui 发表于 2015-9-2 22:14

土匪大作,赞!

349264710 发表于 2015-9-2 23:01

mark,关注GPRS如何保持实时在线,如何检测各种网络异常并作出反应(如信号不佳,SIM卡未插,服务器端异常)。另外建议楼主提供简单的代码即可,无需用状态机的方式(用状态机逻辑跳跃比较大),毕竟是交流贴,不在代码在于方法。

zuoxuqi 发表于 2015-9-3 15:11

很专业,留个记号继续关注

我是土匪 发表于 2015-9-3 21:51

349264710 发表于 2015-9-2 23:01
mark,关注GPRS如何保持实时在线,如何检测各种网络异常并作出反应(如信号不佳,SIM卡未插,服务器端异常) ...

很好的建议。
确实目前数据业务的比重最大。

崔克七系 发表于 2015-9-4 21:57

好帖子搬个小板凳来学习一下

乐天天 发表于 2015-9-5 13:54

我有个朋友在联通上班。他们的流量卡2块多钱一张,哈哈

我学MCU 发表于 2015-9-6 09:17

支持,好**,好内容

wellhao2004 发表于 2015-9-6 16:27

关注一下
页: 1 [2] 3 4 5 6 7 8 9
查看完整版本: 【原创连载】+和土匪一起玩GPRS模块