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

发布者:温柔阳光最新更新时间:2022-09-22 来源: csdn关键字:STM32F103  SIM900A  发送短信  串口打印 手机看文章 扫描二维码
随时随地手机看文章

最近用STM32F103做一个智能门锁小玩意,密码输入错误次数多进行验证码解锁,这里我采用SIM900A来通过发送短信输入验证码进行解锁。就是简单的了解了一下在这里也单独的写写这个SIM900A的一写笔记。

基本介绍

在这里插入图片描述

。。。。。。还是直接进入主题吧


一:单独测试

SIM900A是可以AT指令操作的,所以一般我拿到这种模块就是先单独的测试一下这个模块是否正常。通过一个USB-TTL 和 SIM900A连接 进行调试。用我们的电脑串口助手测试即可。没必要上来就用单片机,现单独测试了先。没问题再转成代码也不迟。


1.准备工作

USB-TTL一个

在这里插入图片描述

还有杜邦线就不用说啦


2.接线

image.png

3.指令操作

打开你的串口助手

注意:建议使用卖家配套的串口助手

注意:建议使用卖家配套的串口助手

注意:建议使用卖家配套的串口助手


第一步:发送AT检测是否正常 (记得要回车换行再发送) 成功返回OK


AT


第二步:选择短消息格式(0:PDU模式 1:文本模式) (记得要回车换行再发送) 成功返回OK


AT+CMGF=1


第三步:选择TE字库集 (记得要回车换行再发送) 成功返回OK


AT+CSCS="UCS2"


第四步:保存SMS设置 (记得要回车换行再发送) 成功返回OK


AT+CSCA?


第五步:设置短消息文本模式参数 (记得要回车换行再发送) 成功返回OK


AT+CSMP=17,167,0,25


**第六步:设置接收短信方的电话号码(要转UNICON编码) (记得要回车换行再发送) 成功返回>**不知道咋转往下翻有一个代码是生成的。


AT+CMGS="你接收短信方的电话号码的UNICON编码"


第七步:发送要发送的内容(要转UNICON编码)(记得要回车换行再发送)成功返回>


"发送的内容的UNICON编码"


第八步:发送结束标志 16进制:0X1A 切换到16进制模式发送(不需要回车换行) 成功返回OK


1A


提示:

1.不出意外的话你设置接收短信的手机号码就能接收到你发送的短信内容


2.上面提到的为啥最好用卖家提供的串口助手呢 因为我一开始就没用卖家的,我用的其他,换了2个都是发送最后的1A 返回的error 而不是OK。后来用回他们提供的就成功了。


3.关于UNICON编码转换软件 一般卖家都会提供资料的 如下图

你没有也没关系 或者懒得找咱就自己写一个 我这里也有写 请忘下看 不过我这里是ASCII转Unicode 如果是中文你可以自己写一下 或者还是找软件转吧 哈哈哈哈

在这里插入图片描述

4.测试结果

在这里插入图片描述

二:关于Unicode编码

Unicode基本介绍

Unicode一般指统一码,也叫万国码、单一码,是计算机科学领域里的一项业界标准,包括字符集、编码方案等。Unicode是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。


1、编码方式

unicode是一种国际组织制定能容纳所有文字和符号的字符编码方案。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案。


我们看图 我这里只是ASCII转… 凑合看吧

我们把ASCII字符串用当成双字节汉字转unicode码你发现1这个字符变成了0031

这31是不是你想到了什么,1的16进制不就是0X31吗?前面补2个0后面是它的16进制不就完事了么?

在这里插入图片描述

/**********************************************************************

描述: ASCII 转 unicode      比如 '1'  转成 "0031"

***********************************************************************/

void ASCII_TO_Unicode(char *ASCII,char *Unicode)

{

    int length;

    int i = 0;

    int j = 0;

memset(Unicode,'',sizeof(Unicode));

    length = strlen(ASCII);


    for(i=0;i    {

        Unicode[j++] = '0';

        Unicode[j++] = '0';


        Unicode[j++] = (ASCII[i] / 16) + 0x30;

        Unicode[j++] = (ASCII[i] % 16) + 0x30;

    }


}


比如我想把接收短信方的电话号码转一下

在这里插入图片描述

三:代码编写

有了刚才的测试,我们就可以转成代码来 用STM32F103来控制SIM900A发送短信了。


我这里不加入显示屏来了。直接用串口打印信息查看了。


用到资源:两个串口

串口1用于打印信息(充当显示屏)

串口2用于和SIM900A通信。


sim900a.c

#include "sim900a.h"

#include

#include

#include

#include

#include "usart.h"

#include "delay.h"


uint8_t verification_code[7]; //存放验证码 


uint8_t sim900a_receive_data[128] = {0};

uint16_t sim900a_receive_count;


/**********************************************************************

描述:   SIM900A模块发送指令 函数

参数: *str:指令内容 ack:正常返回结果的数据 time:允许时间(1次代表 10ms)

返回: 0:指令得到正确回应 1: 指令没得到回应

***********************************************************************/

uint8_t sim900a_send_cmd(uint8_t *str,uint8_t *ack,uint16_t time)

{

memset(sim900a_receive_data,'',sizeof(sim900a_receive_data));

sim900a_receive_count = 0;

usart_sendString(USART2,(char *)str); //发送指令

if(ack == NULL) return 0;

//开启中断接收

OPEN_USART2_RECEIVE;

while(time--)

{

delay_ms(10);

//寻找要找的关键词 找到关中断接收 并且返回0

if(strstr((char *)sim900a_receive_data,(char *)ack) != NULL)

{

CLOSE_USART2_RECEIVE; //关闭中断接收

return 0;

}

}

CLOSE_USART2_RECEIVE; //关闭中断接收

return 1; //超时还没收到想要得到的关键词 关串口中断 并且返回1

}



/**********************************************************************

描述:   SIM900A模块发送指令 函数

参数: *str:指令内容 ack:正常返回结果的数据 time:允许时间(1次代表 10ms)

返回: 0:指令得到正确回应 1: 指令没得到回应

***********************************************************************/

uint8_t sim900a_send_end(uint8_t data,uint8_t *ack,uint16_t time)

{

sim900a_receive_count = 0;

memset(sim900a_receive_data,'',sizeof(sim900a_receive_data));


usart_sendByte(USART2,data); //发送结束指令

if(ack == NULL) return 0;

//开启中断接收

OPEN_USART2_RECEIVE;

while(time--)

{

delay_ms(10);

//寻找要找的关键词 找到关中断接收 并且返回0

if(strstr((char *)sim900a_receive_data,(char *)ack) != NULL)

{

CLOSE_USART2_RECEIVE; //关闭中断接收

return 0;

}

}

CLOSE_USART2_RECEIVE; //关闭中断接收

return 1; //超时还没收到想要得到的关键词 关串口中断 并且返回1

}




/**********************************************************************

描述:   随机生成验证码('0'~'9')

        产生字符 '0' ~ '9'  十进制也就是 48 ~ 57

***********************************************************************/

void generate_verification_code(char *data,uint8_t number)

{

    uint8_t i;

//    srand(time(NULL));


    for(i=0;i    {

        data[i] = 48 + (rand() % 10);

    }

}


/**********************************************************************

描述: ASCII 转 unicode      比如 '1'  转成 "0031"

***********************************************************************/

void ASCII_TO_Unicode(char *ASCII,char *Unicode)

{

    int length;

    int i = 0;

    int j = 0;

memset(Unicode,'',sizeof(Unicode));

    length = strlen(ASCII);


    for(i=0;i    {

        Unicode[j++] = '0';

        Unicode[j++] = '0';


        Unicode[j++] = (ASCII[i] / 16) + 0x30;

        Unicode[j++] = (ASCII[i] % 16) + 0x30;

    }


}


/**********************************************************************

描述: SIM900A 发送验证码 函数

返回: 0:成功 1:失败

***********************************************************************/

uint8_t sim900a_send_verification_code(void)

{

uint8_t ack; //存放状态

uint8_t err = 3; //设置可错误次数 

uint8_t send_count = 3; //发送次数 发送次数达到还是没成功则放弃发送

uint8_t sim900a_send_buffer[96] = {0};


SEND_AT:

strcpy((char *)sim900a_send_buffer,"AT+CMGS="");

//发送指令AT 检测是否返回OK 给300ms时间检测

ack = sim900a_send_cmd(SIM900A_SEND_AT,"OK",30);

if(ack)

{

if(err-- == 0)

{

printf("AT FAILrn");

return 1;

}

goto SEND_AT;

}

printf("AT OKrn");

err = 3;

//发送 短消息格式 指令 检测是否返回OK 给300ms时间检测

SELECT_SMS_FORMAT:

ack = sim900a_send_cmd(SIM900A_SELECT_SMS_FORMAT,"OK",30);

if(ack)

{

if(err-- == 0)

{

printf("SMS FORMAT FAILrn");

return 1;

}

goto SELECT_SMS_FORMAT;

}

printf("SMS FORMAT SUCCESSrn");

err = 3;




//发送 选择TE字库集 指令 检测是否返回OK 给300ms时间检测

SELECT_TE_FONT:

ack = sim900a_send_cmd(SIM900A_SELECT_TE_FONT,"OK",30);

if(ack)

{

if(err-- == 0)

{

printf("SELECT_TE_FONT FAILrn");

return 1;

}

goto SELECT_TE_FONT;

}

printf("SELECT_TE_FONT SUCCESSrn");

err = 3;




//发送 选择TE字库集 指令 不检测返回值

SAVE_SMS_SET:

ack = sim900a_send_cmd(SIM900A_SAVE_SMS_SET,NULL,0);

if(ack)

{

if(err-- == 0)

{

printf("SAVE_SMS_SET FAILrn");

return 1;

}

goto SAVE_SMS_SET;

}

printf("SAVE_SMS_SET SUCCESSrn");

err = 3;



//发送 设置短消息文本模式参数 指令 检测是否返回OK 给300ms时间检测

SET_SMS_TEST_MODE:

ack = sim900a_send_cmd(SIM900A_SET_SMS_TEST_MODE,"OK",30);

if(ack)

{

if(err-- == 0)

{

printf("SMS TEST MODE FAILrn");

return 1;

}

goto SET_SMS_TEST_MODE;

}

printf("SMS TEST MODE SUCCESSrn");

err = 3;



//让我们的设置接收短信方电话号码生成unicode编码

ASCII_TO_Unicode(PHONE_NUMBER,&sim900a_send_buffer[strlen(sim900a_send_buffer)]);

strcat((char *)sim900a_send_buffer,""rn");

printf("%srn",sim900a_send_buffer);

//发送 接收短信方电话号码 指令 检测是否返回OK 给1000ms时间检测

SELECT_PHONE_NUMBER:

ack = sim900a_send_cmd(sim900a_send_buffer,">",100);

if(ack)

{

if(err-- == 0)

{

printf("SET PHONE NUMBER FAILrn");

return 1;

}

goto SELECT_PHONE_NUMBER;

}

printf("SET PHONE NUMBER SUCCESSrn");

err = 3;

//清空缓冲区 准备为发送验证码做准备

memset(sim900a_send_buffer,'',sizeof(sim900a_send_buffer));


//在这里开始就是开始发送内容了

//1-生成验证码

strcpy((char *)sim900a_send_buffer,"9A8C8BC17801003A"); //添加unicode码 "验证码:"

generate_verification_code((char *)verification_code,6);//生成验证码

printf("验证码生成结果:%srn",verification_code);

//2-将随机产生的6位验证码转Unicode编码 并且拼接一起

ASCII_TO_Unicode((char *)verification_code,&sim900a_send_buffer[strlen(sim900a_send_buffer)]);

strcat((char *)sim900a_send_buffer,"rn"); //加上回车换行 

printf("%srn",sim900a_send_buffer);

//3-发送数据

SEND_DATA:

ack = sim900a_send_cmd(sim900a_send_buffer,">",300);

if(ack)

{

if(err-- == 0)

{

printf("SEND DATA FAILrn");

return 1;

}

goto SEND_DATA;

}

printf("SEND DATA SUCCESSrn");

//4-发送 0X1A 标志

ack = sim900a_send_end(0x1a,"OK",800);

if(ack)

{

if(send_count-- == 0) return 1;

memset(sim900a_send_buffer,'',sizeof(sim900a_send_buffer));

err = 3;

goto SEND_AT; //重发短信

}

printf("SEND MESSAGE SUCCESSrn");

return 0;

}


/**********************************************************************

描述: SIM900A 初始化 函数

返回: 0:成功 1:失败

***********************************************************************/

uint8_t sim900a_init(void)

{

uint8_t ack; //存放状态

uint8_t err; //设置可错误次数 


err = 3;

//发送指令AT 检测是否返回OK 给300ms时间检测

SEND_AT:

ack = sim900a_send_cmd(SIM900A_SEND_AT,"OK",30);

if(ack)

{

if(err-- == 0)

{

printf("AT FAILrn"); //ESP8266模块不存在

return 1;

}


goto SEND_AT;

}

printf("AT SUCCESSrn");

return 0;

}


sim900a.h

#ifndef __SIM900A_H

#define __SIM900A_H

#include "stm32f10x.h"


/*用户必改 xxxxxxxxxxx 改成接收短信的电话号码*/

#define PHONE_NUMBER "xxxxxxxxxxx"



#define SIM900A_SEND_AT "ATrn"

//1.选择短消息格式 (0:PDU模式 1:文本模式)

#define SIM900A_SELECT_SMS_FORMAT "AT+CMGF=1rn"

//2.选择TE字库集

#define SIM900A_SELECT_TE_FONT "AT+CSCS="UCS2"rn"

//3.保存SMS设置

#define SIM900A_SAVE_SMS_SET "AT+CSCA?rn"

//4.设置短消息文本模式参数

#define SIM900A_SET_SMS_TEST_MODE "AT+CSMP=17,167,0,25rn"


extern uint8_t  sim900a_receive_data[128];

extern uint16_t  sim900a_receive_count;

[1] [2]
关键字:STM32F103  SIM900A  发送短信  串口打印 引用地址:基于STM32F103——SIM900A发送短信+串口打印

上一篇:基于STM32F103+AS608指纹模块+4X4矩阵按键+SIM900A发短信——智能门禁卡系统
下一篇:基于STM32F103——AS608指纹模块+串口打印

推荐阅读最新更新时间:2024-11-12 16:11

STM32f103 USB移植之USB标准描述符
在对USB协议进行学习和移植的过程有个东西不可避免,肯定会遇到,那就是USB的设备描述符。这个东西始终在usb协议中发挥作用,从设备的枚举到设备的配置,都是由usb描述符进行修改的。今天在移植的时候这个整理了一下usb描述符有关的知识。 /********************************************不啰嗦的分割线***********************************************/ 参考资料:深入浅出USB系统开发——基于ARM Cortex-M3 王川北 刘强 圈圈教你玩usb http://www.openedv.com/thread-10971-1-1.html
[单片机]
<font color='red'>STM32f103</font> USB移植之USB标准描述符
基于STM32F103单片机的汽车远程防盗系统方案
  近几年,汽车偷盗案件越来越多,给人们带来巨大的经济损失。市场上随之出现了各种各样的汽车防盗器,本汽车防盗系统采用ST公司生产的STM32F103R6T6(以下简称STM32F103)单片机作为控制器,功能强大,实时性好。    1 系统结构与功能   汽车远程防盗系统是基于现代无线通信技术设计的,可以不受距离的约束,将汽车的状态信息直接发送到车主手机,进行一对一防盗报警,汽车远程防盗系统的结构如图1所示。      汽车防盗系统的信息采集模块包括人体感应传感器、振动传感器等,用来采集汽车警情信息。传感器将采集到警情信息,传送给微处理器处理,微处理器开始执行报警程序。首先,发送短信到车主手机;然后,报警器根据不同的警情进
[单片机]
基于<font color='red'>STM32F103</font>单片机的汽车远程防盗系统方案
基于LoRa的可燃气体监测系统设计方案
摘 要 :针对目前可燃气体监测系统存在的通信传输距离短和功耗高的问题,提出了一种基于 LoRa 技术的可燃气体监测系统设计方案,给出了系统的总体设计以及详细的系统硬件组成和原型,软件系统由 Keil 软件编译实现。基于 FM33LG048 设计的无线传感器采集现场气体浓度,通过 SX1278 无线射频模块与 LoRa 控制器通信 ;以高性能,低功耗 STM32F103 为主控制单元设计的 LoRa 控制器接收、处理、存储无线传感器数据,并提供操作界面,其中,控制器中的 LoRa 网关作为中继通过 GPRS 将接收的数据发送到云平台。系统可通过 LoRa 控制器在本地查看、操作无线传感器,通过手机或电脑远程增、删、改、查无线传感器相
[单片机]
基于LoRa的可燃气体监测系统设计方案
使用STM32F103实验和总结PWM相关知识
脉冲宽度调制PWM(Pulse Width Modulation)的原理示意图如下: 图中,假定定时器工作在向上计数PWM2模式,定时器从0开始计数到ARR,t时刻比较计数值CNT和CCRx,当CNT 显然:改变CCRx可以改变占空比,改变ARR可以改变输出频率。 STM32F103 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。其中高级定时器 TIM1 和 TIM8 可以同时产生多达 7 路的 PWM 输出,高级定时器尚未研究,以后再议。用定时器也能同时产生多达 4路的 PWM 输出。 首先大致了解PWM相关的三个寄存器:捕获/比较模式寄存器(TIMx_CCMR1/2)、捕获/比较使
[单片机]
使用<font color='red'>STM32F103</font>实验和总结PWM相关知识
错误解决:STM32F103串口1与串口3相同代码却结果不同
在前几天调试openmv时发现同样的代码串口1和串口3的结果却是不一样的,当时着实是把我坑了很久,怎么都找不到原因,用示波器看波形也是没有问题的,在Openedv网站上有位网友指出是我初始化代码的问题,在翻阅参考手册后终于发现了问题。 下列代码为我原本的初始化代码: #include sys.h #include usart.h #include led.h #include usart3.h int theta_err,rho_err; int main(void) { Stm32_Clock_Init(9); //=====系统时钟设置 delay_init(72); /
[单片机]
错误解决:<font color='red'>STM32F103</font><font color='red'>串口</font>1与<font color='red'>串口</font>3相同代码却结果不同
SystemInit()函数详解
1 基于STM32F103的SystemInit()函数详解 1 使用的固件库是,STM32F10x_StdPeriph_Lib_V3.5.0 2 学习板CPU的具体型号为STM32F103VET6 3 软件开发环境为RVMDK3.90 4 未定义STM32F10X_CL,在system_stm32f10x.c(第0115行)中定义了SYSCLK_FREQ_72MHz,具体如下: #if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL) /* #define SYSCLK_FREQ_HSE HSE
[单片机]
SystemInit()函数详解
基于STM32F103平台CANOPEN工业协议源码
单片机源程序如下: /* Includes ------------------------------------------------------------------*/ #include stm32f10x.h #include delay.h #include can.h #include mco.h #include lcd.h #include bsp.h #include i2c.h #include 24cxx.h #include stdio.h typedef struct { u8 BaudRate_Data; u8 ODNodeID_Data; }e2prom; e2prom
[单片机]
STM32F103单片机学习笔记(3):串口
关于串口,基础的应该都知道,波特率,校验位,停止位,双向通信接收端连接发送端,发送端连接接收端,两个不同设备通信的时候要共地。485、232、422都是由串口驱动的,只是他们的传输电平不一样。经过了前面IO口的设置以及中断的配置之后,感觉再驱动中断普通的接收和发送就没有那么的吃力了,关于复杂的用法设置我这里就不总结了。这里要注意的是USART1应用的是APB2时钟,USART2、USART3、UART4、UART5应用的是APB1时钟。 继续看给我们的库函数,这一个涉及到的库函数是与串口相关的库函数stm32f10x_usart.c 对于串口,它在接收和发送的时候也可以设置为中断,这样就应用到我们之前的设置方法。这里我以
[单片机]
<font color='red'>STM32F103</font>单片机学习笔记(3):<font color='red'>串口</font>
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved