基于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的主要内容,如果未能解决你的问题,请参考以下文章
基于实时时钟RTC实现STM32F103C8的日历读取设置和输出
基于STM32F103+AS608指纹模块+4X4矩阵按键+SIM900A发短信——智能门禁卡系统