基于STM32实现的的短信实时传送位置----GPS+GSM

Posted Mnster_Lu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于STM32实现的的短信实时传送位置----GPS+GSM相关的知识,希望对你有一定的参考价值。

 

总的来说就是实现了一个GPS数据通过串口发送给STM32,

STM32进行解码,

在通过串口把解码提取出的经纬度发送给GSM,

GSM根据给定的手机号发短信过去。

 

main函数里的最后一个while循环是每隔5s发一个位置出去

延时函数写在sim900a.c里,可以自行调节时间间隔。

就是这么任性。

 

 

 

 

main.c

/*
  ******************************************************************************
  * @attention
  *
  * 实验平台:野火 ISO-STM32 开发板

  ******************************************************************************
    */
#include "stm32f10x.h"
#include "bsp_usart1.h"
#include "gps_config.h"
#include <string.h>
#include "gsm.h"
#include <stdio.h>

        

extern void nmea_decode_test(void);

/*
 * 测试GPS模块功能
 * 
 */
 
 
double  zaishichua;
double  zaishichub;
int main(void)
{
    char zaiship1[14];
    char zaiship2[14];
    /* 配置USART1 用于向电脑printf调试信息*/
   USART1_Config();                          
    /* 初始化GPS模块使用的接口 */
    GPS_Config();
    printf("\\r\\nGPS模块测试例程\\r\\n");

    printf("\\r\\nGPS模块测试例程\\r\\n");      /////////////////////////////////
         while(1)
         {/* GPS解码测试 */
    nmea_decode_test();
    printf("\\r\\n纬度:%f,经度%f\\r\\n",zaishichua,zaishichub);
     printf("\\r\\n纬度:%f,经度%f\\r\\n",zaishichua,zaishichub);
   

      sprintf(zaiship1,"%013.6f",zaishichua);
      sprintf(zaiship2,"%013.6f",zaishichub);
       gsm(zaiship1,zaiship2);
         }

  
  
}

 

 

bsp_usart1.c

/**
  ******************************************************************************
  * @file    bsp_usart1.c
  * @author  fire
  * @version V1.0
  * @date    2013-xx-xx
  * @brief   重现c库printf函数到usart端口
  ******************************************************************************
  * @attention
  *
  * 实验平台:野火 iSO STM32 开发板
  *
  ******************************************************************************
  */

#include "bsp_usart1.h"


/**
 * @brief  USART1 GPIO 配置,工作模式配置。115200 8-N-1
 * @param  无
 * @retval 无
 */
void USART1_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    /* config USART1 clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

    /* USART1 GPIO config */
    /* Configure USART1 Tx (PA.09) as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Configure USART1 Rx (PA.10) as input floating */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* USART1 mode config */
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No ;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);

    USART_Cmd(USART1, ENABLE);
}

///重定向c库函数printf到USART1
int fputc(int ch, FILE *f)
{
    /* 发送一个字节数据到USART1 */
    USART_SendData(USART1, (uint8_t) ch);

    /* 等待发送完毕 */
    while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);

    return (ch);
}

///重定向c库函数scanf到USART1
int fgetc(FILE *f)
{
    /* 等待串口1输入数据 */
    while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);

    return (int)USART_ReceiveData(USART1);
}



/*********************************************END OF FILE**********************/

 

bsp_usart2.c

 

/******************** (C) COPYRIGHT 2012 WildFire Team **************************
 * 文件名  :usart2.c
 * 描述    :将printf函数重定向到USART2。这样就可以用printf函数将单片机的数据
 *           打印到PC上的超级终端或串口调试助手。         
 * 实验平台:野火STM32开发板
 * 库版本  :ST3.5.0
 *
 * 作者    :wildfire team 
**********************************************************************************/
#include "bsp_usart2.h"
#include <stdarg.h>


/// 配置USART2接收中断
static void NVIC_Configuration(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    /* Configure the NVIC Preemption Priority Bits */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

    /* Enable the USARTy Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

/*
 * 函数名:USART2_Config
 * 描述  :USART2 GPIO 配置,工作模式配置
 * 输入  :无
 * 输出  : 无
 * 调用  :外部调用
 */
void USART2_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    /* config USART2 clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

    /* USART2 GPIO config */
   /* Configure USART2 Tx (PA.02) as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
        
  /* Configure USART2 Rx (PA.03) as input floating */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
      
    /* USART2 mode config */
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No ;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

    USART_Init(USART2, &USART_InitStructure); 
    
    /*    配置中断优先级 */
    NVIC_Configuration();
    /* 使能串口2接收中断 */
    USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

    
    USART_Cmd(USART2, ENABLE);
}

/*
 * 函数名:fputc
 * 描述  :重定向c库函数printf到USART2
 * 输入  :无
 * 输出  :无
 * 调用  :由printf调用
 */
//int fputc(int ch, FILE *f)
//{
///* 将Printf内容发往串口 */
//  USART_SendData(USART2, (unsigned char) ch);
//  while (!(USART2->SR & USART_FLAG_TXE));
// 
//  return (ch);
//}

/*
 * 函数名:itoa
 * 描述  :将整形数据转换成字符串
 * 输入  :-radix =10 表示10进制,其他结果为0
 *         -value 要转换的整形数
 *         -buf 转换后的字符串
 *         -radix = 10
 * 输出  :无
 * 返回  :无
 * 调用  :被USART2_printf()调用
 */
static char *itoa(int value, char *string, int radix)
{
    int     i, d;
    int     flag = 0;
    char    *ptr = string;

    /* This implementation only works for decimal numbers. */
    if (radix != 10)
    {
        *ptr = 0;
        return string;
    }

    if (!value)
    {
        *ptr++ = 0x30;
        *ptr = 0;
        return string;
    }

    /* if this is a negative value insert the minus sign. */
    if (value < 0)
    {
        *ptr++ = \'-\';

        /* Make the value positive. */
        value *= -1;
    }

    for (i = 10000; i > 0; i /= 10)
    {
        d = value / i;

        if (d || flag)
        {
            *ptr++ = (char)(d + 0x30);
            value -= (d * i);
            flag = 1;
        }
    }

    /* Null terminate the string. */
    *ptr = 0;

    return string;

} /* NCL_Itoa */


#if 1
//中断缓存串口数据
#define UART_BUFF_SIZE      255
volatile    uint8_t uart_p = 0;
uint8_t     uart_buff[UART_BUFF_SIZE];

void bsp_USART2_IRQHandler(void)
{
    if(uart_p<UART_BUFF_SIZE)
    {
        if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
        {
            uart_buff[uart_p] = USART_ReceiveData(USART2);
            uart_p++;
        }
    }
}



//获取接收到的数据和长度
char *get_rebuff(uint8_t *len)
{
    *len = uart_p;
    return (char *)&uart_buff;
}

void clean_rebuff(void)
{
    uint16_t i=UART_BUFF_SIZE+1;
    uart_p = 0;
    while(i)
        uart_buff[--i]=0;
}

#endif

/*
 * 函数名:USART2_printf
 * 描述  :格式化输出,类似于C库中的printf,但这里没有用到C库
 * 输入  :-USARTx 串口通道,这里只用到了串口2,即USART2
 *             -Data   要发送到串口的内容的指针
 *               -...    其他参数
 * 输出  :无
 * 返回  :无 
 * 调用  :外部调用
 *         典型应用USART2_printf( USART2, "\\r\\n this is a demo \\r\\n" );
 *                     USART2_printf( USART2, "\\r\\n %d \\r\\n", i );
 *                     USART2_printf( USART2, "\\r\\n %s \\r\\n", j );
 */
void USART2_printf(USART_TypeDef* USARTx, char *Data,...)
{
    const char *s;
  int d;   
  char buf[16];

  va_list ap;
  va_start(ap, Data);

    while ( *Data != 0)     // 判断是否到达字符串结束符
    {                                          
        if ( *Data == 0x5c )  //\'\\\'
        {                                      
            switch ( *++Data )
            {
                case \'r\':                                      //回车符
                    USART_SendData(USARTx, 0x0d);
                    Data ++;
                    break;

                case \'n\':                                      //换行符
                    USART_SendData(USARTx, 0x0a);    
                    Data ++;
                    break;
                
                default:
                    Data ++;
                    break;
            }             
        }
        else if ( *Data == \'%\')
        {                                      //
            switch ( *++Data )
            {                
                case \'s\':                                          //字符串
                    s = va_arg(ap, const char *);
          for ( ; *s; s++) 
                    {
                        USART_SendData(USARTx,*s);
                        while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );
          }
                    Data++;
          break;

        case \'d\':                                        //十进制
          d = va_arg(ap, int);
          itoa(d, buf, 10);
          for (s = buf; *s; s++) 
                    {
                        USART_SendData(USARTx,*s);
                        while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );
          }
                    Data++;
          break;
                 default:
                        Data++;
                    break;
            }         
        } /* end of else if */
        else USART_SendData(USARTx, *Data++);
        while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );
    }
}
/******************* (C) COPYRIGHT 2012 WildFire Team *****END OF FILE************/

 

bsp_usart3.c

 

 

 

/******************** (C) COPYRIGHT 2012 WildFire Team **************************
 * 文件名  :usart3.c
 * 描述    :将printf函数重定向到USART2。这样就可以用printf函数将单片机的数据
 *           打印到PC上的超级终端或串口调试助手。         
 * 实验平台:野火STM32开发
 * 库版本  :ST3.5.0
 *
 * 作者    :wildfire team 
**********************************************************************************/
#include "bsp_usart3.h"//头文件要在外面改头文件名,现只将其中内容改为usart3
#include <stdarg.h>




/*
 * 函数名:USART2_Config
 * 描述  :USART2 GPIO 配置,工作模式配置
 * 输入  :无
 * 输出  : 无
 * 调用  :外部调用
 */
void USART3_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    /* config USART2 clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//此处也要修改,修改为GPIOB
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

    /* USART2 GPIO config */
  /* Configure USART2 Tx (PB.10) as alternate function push-pull *///此处改为b10
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
        
  /* Configure USART2 Rx (PB.11) as input floating */ //此处改为b11
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
      
    /* USART2 mode config */
    USART_InitStructure.USART_BaudRate = 9600;                //GPS模块默认使用波特率:9600
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No ;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

    USART_Init(USART3, &USART_InitStructure); 

    USART_Cmd(USART3, ENABLE);
}

 

gps_config.c

 

/**
  ******************************************************************************
  * @file    gps_config.c
  * @author  fire
  * @version V1.0
  * @date    2014-08-xx
  * @brief   gps模块接口配置驱动
  ******************************************************************************
  * @attention
  *
  * 实验平台:野火 ISO-STM32 开发板
  *
  ******************************************************************************
    */

#include "gps_config.h"
#include "bsp_usart3.h"
#include "nmea/nmea.h"


/* DMA接收缓冲  */
uint8_t gps_rbuff[GPS_RBUFF_SIZE];

/* DMA传输结束标志 */
__IO uint8_t GPS_TransferEnd = 0, GPS_HalfTransferEnd = 0;



/**
  * @brief  GPS_Interrupt_Config 配置GPS使用的DMA中断 
  * @param  None.
  * @retval None.
  */
static void GPS_Interrupt_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

    // DMA2 Channel Interrupt ENABLE
    NVIC_InitStructure.NVIC_IRQChannel = GPS_DMA_IRQn;//中断用的是RX不是TX啊啊啊啊fuxx!!
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

}


/**
  * @brief  GPS_ProcessDMAIRQ GPS DMA中断服务函数
  * @param  None.
  * @retval None.
  */
void GPS_ProcessDMAIRQ(void)
{
  
  if(DMA_GetITStatus(GPS_DMA_IT_HT) )         /* DMA 半传输完成 */
  {
    GPS_HalfTransferEnd = 1;                //设置半传输完成标志位
    DMA_ClearFlag(GPS_DMA_FLAG_HT);
        
  }
  else if(DMA_GetITStatus(GPS_DMA_IT_TC))     /* DMA 传输完成 */
  {
    GPS_TransferEnd = 1;                    //设置传输完成标志位
    DMA_ClearFlag(GPS_DMA_FLAG_TC);

   }
}


/**
  * @brief  GPS_DMA_Config gps dma接收配置
  * @param  无
  * @retval 无
  */
static void GPS_DMA_Config(void) //其为一个函数
{
        DMA_InitTypeDef DMA_InitStructure; //定义一个DMA_InitTypeDef类型的结构体,名为DMA_InitStructure
    
        /*开启DMA时钟*/
        RCC_AHBPeriphClockCmd(GPS_DMA_CLK, ENABLE);

        /*设置DMA源:串口数据寄存器地址*/
        DMA_InitStructure.DMA_PeripheralBaseAddr = GPS_DATA_ADDR;       //带点号为结构体内的成员,可直接赋值,相当于变量
//从该处进入gps.config.h可见,gps的串口通信定义为USart2,我们可从这里修改
        /*内存地址(要传输的变量的指针)*/
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)gps_rbuff;

        /*方向:从外设到内存 */        
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;    

        /*传输大小DMA_BufferSize=SENDBUFF_SIZE*/    
        DMA_InitStructure.DMA_BufferSize = GPS_RBUFF_SIZE;

        /*外设地址不增*/        
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //想修改可直接找到相对应的名字修改

        /*内存地址自增*/
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;    

        /*外设数据单位*/    
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

        /*内存数据单位 8bit*/
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;     

        /*DMA模式:不断循环*/
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;     

        /*优先级:中*/    
        DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;  

        /*禁止内存到内存的传输    */
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

        /*配置DMA的通道*/           
        DMA_Init(GPS_DMA_CHANNEL, &DMA_InitStructure);        
    
    GPS_Interrupt_Config();
        
    DMA_ITConfig(GPS_DMA_CHANNEL,DMA_IT_HT|DMA_IT_TC,ENABLE);  //配置DMA发送完成后产生中断

        /*使能DMA*/
        DMA_Cmd (GPS_DMA_CHANNEL,ENABLE);        
    
    /* 配置串口 向 DMA发出TX请求 */
        USART_DMACmd(GPS_USART, USART_DMAReq_Rx, ENABLE);


}

/**
  * @brief  GPS_Config gps 初始化
  * @param  无
  * @retval 无
  */
void GPS_Config(void)
{
  GPS_USART_INIT();   //初始化串口
  GPS_DMA_Config();  //初始化串口配套的DMA模式
  
}

 

/**
  * @brief  trace 在解码时输出捕获的GPS语句
  * @param  str: 要输出的字符串,str_size:数据长度
  * @retval 无
  */
void trace(const char *str, int str_size)
{
  #ifdef __GPS_DEBUG    //在gps_config.h文件配置这个宏,是否输出调试信息
    uint16_t i;
    printf("\\r\\nTrace: ");
    for(i=0;i<str_size;i++)
      printf("%c",*(str+i));
  
    printf("\\n");
  #endif
}

/**
  * @brief  error 在解码出错时输出提示消息
  * @param  str: 要输出的字符串,str_size:数据长度
  * @retval 无
  */
void error(const char *str, int str_size)
{
    #ifdef __GPS_DEBUG   //在gps_config.h文件配置这个宏,是否输出调试信息

    uint16_t i;
    printf("\\r\\nError: ");
    for(i=0;i<str_size;i++)
      printf("%c",*(str+i));
    printf("\\n");
    #endif
}



/******************************************************************************************************** 
**     函数名称:            bit        IsLeapYear(uint8_t    iYear) 
**    功能描述:            判断闰年(仅针对于2000以后的年份) 
**    入口参数:            iYear    两位年数 
**    出口参数:            uint8_t        1:为闰年    0:为平年 
********************************************************************************************************/ 
static uint8_t IsLeapYear(uint8_t iYear) 
{ 
    uint16_t    Year; 
    Year    =    2000+iYear; 
    if((Year&3)==0) 
    { 
        return ((Year%400==0) || (Year%100!=0)); 
    } 
     return 0; 
} 

/******************************************************************************************************** 
**     函数名称:            void    GMTconvert(uint8_t *DT,uint8_t GMT,uint8_t AREA) 
**    功能描述:            格林尼治时间换算世界各时区时间 
**    入口参数:            *DT:    表示日期时间的数组 格式 YY,MM,DD,HH,MM,SS 
**                        GMT:    时区数 
**                        AREA:    1(+)东区 W0(-)西区 
********************************************************************************************************/ 
void    GMTconvert(nmeaTIME *SourceTime, nmeaTIME *ConvertTime, uint8_t GMT,uint8_t AREA) 
{ 
    uint32_t    YY,MM,DD,hh,mm,ss;        //年月日时分秒暂存变量 
     
    if(GMT==0)    return;                //如果处于0时区直接返回 
    if(GMT>12)    return;                //时区最大为12 超过则返回         

    YY    =    SourceTime->year;                //获取年 
    MM    =    SourceTime->mon;                 //获取月 
    DD    =    SourceTime->day;                 //获取日 
    hh    =    SourceTime->hour;                //获取时 
    mm    =    SourceTime->min;                 //获取分 
    ss    =    SourceTime->sec;                 //获取秒 

    if(AREA)                        //东(+)时区处理 
    { 
        if(hh+GMT<24)    hh    +=    GMT;//如果与格林尼治时间处于同一天则仅加小时即可 
        else                        //如果已经晚于格林尼治时间1天则进行日期处理 
        { 
            hh    =    hh+GMT-24;        //先得出时间 
            if(MM==1 || MM==3 || MM==5 || MM==7 || MM==8 || MM==10)    //大月份(12月单独处理) 
            { 
                if(DD<31)    DD++; 
                else 
                { 
                    DD    =    1; 
                    MM    ++; 
                } 
            } 
            else if(MM==4 || MM==6 || MM==9 || MM==11)                //小月份2月单独处理) 
            { 
                if(DD<30)    DD++; 
                else 
                { 
                    DD    =    1; 
                    MM    ++; 
                } 
            } 
            else if(MM==2)    //处理2月份 
            { 
                if((DD==29) || (DD==28 && IsLeapYear(YY)==0))        //本来是闰年且是2月29日 或者不是闰年且是2月28日 
                { 
                    DD    =    1; 
                    MM    ++; 
                } 
                else    DD++; 
            } 
            else if(MM==12)    //处理12月份 
            { 
                if(DD<31)    DD++; 
                else        //跨年最后一天 
                {               
                    DD    =    1; 
                    MM    =    1; 
                    YY    ++; 
                } 
            } 
        } 
    } 
    else 
    {     
        if(hh>=GMT)    hh    -=    GMT;    //如果与格林尼治时间处于同一天则仅减小时即可 
        else                        //如果已经早于格林尼治时间1天则进行日期

以上是关于基于STM32实现的的短信实时传送位置----GPS+GSM的主要内容,如果未能解决你的问题,请参考以下文章

基于STM32F103——SIM900A发送短信+串口打印

基于实时时钟RTC实现STM32F103C8的日历读取设置和输出

基于STM32F103+AS608指纹模块+4X4矩阵按键+SIM900A发短信——智能门禁卡系统

基于STM32F103+AS608指纹模块+4X4矩阵按键+SIM900A发短信——智能门禁卡系统

基于STM32单片机的的智能水杯系统设计-毕业设计资料

14基于STM32的平衡小车设计