系列文章目录
项目一 基于 SIM800 的时间、天气语音播报服务机器人
等待后续添加……
文章目录
前言
移动蜂窝网络已经渗透到了我们生活的方方面面,无论是即时聊天、视频电视、亦或是移动支付都深度依赖移动蜂窝网络。
经过几十年的发展,移动蜂窝网从 1G 到 5G,让人们的生活方式得到了翻天覆地的改变。
该项目使用 2G 网络,实现一个能语言播报天气和时间的服务机器人。
一、总体设计方案
1. 硬件
- 主控:STM32F103C8T6;
- 通信模块:SIM800模块;
- 显示模块:0.96 寸 OLED12864 显示屏幕;
- 语音模块:SYN6288 串口文字转语音模块;
- 独立按键模块。
2. 软件
- SIM800 的 HTTP 服务从服务器获取天气和时间数据;
- 单片机串口将天气和时间数据通过文字的方式发送给 SYN6288 模块;
- 设计一个闹钟和定时器功能,可以通过按键设置;
- 显示屏显示时间和天气。
二、硬件设计
设计所使用的所有模块全部采用模块式组装,方便省事。
1. STM32F103C8T6 最小系统
现在的芯片贼贵,原来几块钱的单片机,现在要买到三四十块。
经费紧张的,STM32F103C8T6 可以考虑使用国产芯片代替。现在和 STM32 PIN to PIN 的国产芯片一大把,用来自己玩一下还是没问题的。
2. SIM800 模块
SIM800 是一款四频 GSM/GPRS 模块,为城堡孔封装。其性能稳定,外观小巧,性价比高,能满足客户的多种需求。SIM800 工作频率为GSM/GPRS850/900/1800/1900MHz,可以低功耗实现语音、SMS和数据信息的传输。SIM800 尺寸为17.615.72.3mm,能适用于各种紧凑型产品设计需求。
该模块需要配合 SIM 卡使用。不同厂家对 SIM800 模块的设计稍有区别,有的是自动复位,有的需要手动复位;SIM 的大小也有区别:有的使用小卡,有的是大卡。购买的时候要注意一下这些参数。
现在我们日常使用的卡大多数已经是 5G 网络了,最少也是 4G 的,但基本上都支持 2G,所以可以拿自己的手机卡来测试。不过网上也有很多纯 2G 卡卖,可以很方便买到。
3. SYN6288 语音模块
这个模块没什么好说的,直接拿串口发文字,就可以转换成语音了。中英文都是可以直接转换的。
唯一需要注意一下的是中文编码问题。这个模块支持 GB2312,GBK,Unicode 等不同中文编码,而你采用的编码跟编译器有关,这个使用的时候需要作为参数设置一下。
详细功能可以参考一下这篇文章:SYN6288语音合成模块介绍
数据手册:SYN6288 数据手册
4. OLED 显示模块
屏幕模块尺寸约为 0.96 英寸,主要由裸屏和底板PCB组成,裸屏由 SSD1306驱动,这也是一种较为广泛使用的 LED 驱动芯片。
驱动接口有 SPI 和 IIC 两种,本设计使用 IIC 驱动。
5. 按键模块
直接买了四合一的独立按键模块。不知道为什么这个模块没有上拉电阻,所以使用的使用要配置成 上拉输入。
三、软件设计
1 时间天气服务API
网上免费的天气和时间服务接口很多,可以自己去找一下。我这里使用 NowAPI。使用方式也很简单,去官网注册一个账号,然后申请免费使用。使用时间只有三个月,我只用做测试是够了。高德天气服务好像是有长期免费的接口。
申请一个天气预报接口和一个标准北京时间接口。
这里附上我申请的接口(过期无效):
天气预报
北京时间
要是失效了就自己注册一个账号,申请 API 后会自动生成 AppKey 和 Sign,替换一下上面连接里面的 AppKey 和 Sign 就行了。
2 SIM800 HTTP 服务
天气预报和北京时间服务都是使用 HTTP 协议的,所以我们要获取服务器数据,就需求启动 SIM800 的 HTTP 服务。
SIM800 使用 串口+AT 指令控制,实际我们只用发送几个 AT 指令,就可以获取到服务器返回给我们的数据了。
/*
获取服务器数据
url 是服务 API
获取到的数据存在串口接收 BUFF 里面
*/
u8 sim900a_get_http(u8 *url)
{
static u8 http_not_init = 1;
u8 cmd[200];
sprintf((char*)cmd, "AT+HTTPPARA=\"URL\",");
strcat((char*)cmd, (char*)url);
//if(sim900a_send_cmd((u8 *)"ATE0",(u8 *)"OK",100)) return SIM_CSQ_ERR;
if(http_not_init)
{
http_not_init = 0;
if(sim900a_send_cmd((u8 *)"AT+CSQ",(u8 *)"OK",100)) return SIM_CSQ_ERR;
if(sim900a_send_cmd((u8 *)"AT+CREG?",(u8 *)"OK",100)) return SIM_CREQ_ERR;
if(sim900a_send_cmd((u8 *)"AT+CSCA?",(u8 *)"OK",100)) return SIM_CSCA_ERR;
if(sim900a_send_cmd((u8 *)"AT+CGATT?",(u8 *)"OK",100)) return SIM_CGATT_ERR;
if(sim900a_send_cmd((u8 *)"AT+SAPBR=3,1,\"APN\",\"CMNET\"",(u8 *)"OK",100)) return SIM_SAPBR_ERR;
if(sim900a_send_cmd((u8 *)"AT+SAPBR=1,1",(u8 *)"OK",1000)) return SIM_SAPBR_ERR;
if(sim900a_send_cmd((u8 *)"AT+HTTPINIT",(u8 *)"OK",300)) return SIM_HTTPINIT_ERR;
}
if(sim900a_send_cmd(cmd,(u8 *)"OK",300));// return SIM_CMGS_ERR;
if(sim900a_send_cmd((u8 *)"AT+HTTPACTION=0",(u8 *)"+HTTPACTION: 0,200",2000)) return SIM_HTTPACTION_ERR;
sim900a_send_cmd((u8 *)"AT+HTTPREAD",(u8 *)"OK",100);
return SIM_OK;
}
//向sim900a发送命令
//cmd:发送的命令字符串(不需要添加回车了),当cmd<0XFF的时候,发送数字(比如发送0X1A),大于的时候发送字符串.
//ack:期待的应答结果,如果为空,则表示不需要等待应答
//waittime:等待时间(单位:10ms)
//返回值:0,发送成功(得到了期待的应答结果)
// 1,发送失败
u8 sim900a_send_cmd(u8 *cmd,u8 *ack,u16 waittime)
{
u8 res=0;
USART2_RX_STA=0;USART2_RX_REC_ATCOMMAD=1;
if((u32)cmd<=0XFF)
{
while(DMA1_Channel7->CNDTR!=0); //等待通道7传输完成
USART2->DR=(u32)cmd;
}else u2_printf("%s\r\n",cmd);//发送命令
if(ack&&waittime) //需要等待应答
{
while(--waittime) //等待倒计时
{
delay_ms(10);
if(USART2_RX_STA&0X8000)//接收到期待的应答结果
{
if(((USART2_RX_STA & 0x7FFF) > 200) && (strstr((const char*)USART2_RX_BUF,"{")))
{
memset(http_buff, 0, USART2_MAX_RECV_LEN);
strcpy((char*)http_buff, (char*)USART2_RX_BUF); //大于200字节认为是http数据
}
if(sim900a_check_cmd(ack))break;//得到有效数据
USART2_RX_STA=0;
}
}
if(waittime==0)res=1;
}
USART2_RX_STA=0;USART2_RX_REC_ATCOMMAD=0;
return res;
}
///
//usmart支持部分
//将收到的AT指令应答数据返回给电脑串口
//mode:0,不清零USART2_RX_STA;
// 1,清零USART2_RX_STA;
void sim_at_response(u8 mode)
{
if(USART2_RX_STA&0X8000) //接收到一次数据了
{
USART2_RX_BUF[USART2_RX_STA&0X7FFF]=0;//添加结束符
printf("%s"