很高兴收到瑞萨电子的RA4M2开发板,有幸成为了幸运观众,本期就来使用瑞萨的RA4M2开发板通过串口连接WIFI模块ESP8266,获取天气预报数据信息。并实时显示出来。它可以获取国内任何城市的天气预报。
ESP8266是一款WiFi模块,它具有强大的网络连接功能,可以轻松地连接到互联网。将使用ESP8266模块来获取天气数据,并将其发送给RA4M2 控制器。通过AT指令来控制ESP8266收发数据,并通过串口打印输出。


我会使用到两个串口,一个用来调试,一个用来连接ESP8266。具体架构框图如下所示:

由上图可知,串口9就是板载的USB串口,用来打印调试。
串口0和ESP8266连接,用来发AT指令。
话不多说了,先上干货!!!!
1。打开配置软件

取名ESP8266
2。选择芯片型号

3。
4。选择非RTOS

5。不选择任何外设,最小化

6。生成代码

7。添加串口

一共两个

8。生成代码

9。打开KEIL

10。串口9函数实现代码
#include "usart9.h"
/*作用:串口9初始化,P109--TXD,P110--RXD
*传入参数:无
*返回参数:无
*/
void UART9_Init(void)
{
fsp_err_t err = FSP_SUCCESS;
err = R_SCI_UART_Open(&g_uart9_ctrl,&g_uart9_cfg);
assert(err == FSP_SUCCESS);
}
static volatile bool uart_send_complete_flag = false; // 发送完成标志
uint8_t RxBuff[1]; //进入中断接收数据的数组
uint8_t DataBuff[5000]; //保存接收到的数据的数组
int RxLine=0; //接收到的数据长度
int Rx_flag=0; //接受到数据标志
int Rx_flag_finish=0; //接受完成或者时间溢出
void user_uart_callback (uart_callback_args_t * p_args)
{
if(p_args->event == UART_EVENT_TX_COMPLETE)
{
uart_send_complete_flag = true;
}
if(p_args->event == UART_EVENT_RX_CHAR)
{
RxBuff[0] = p_args->data;
RxLine++; //每接收到一个数据,进入回调数据长度加1
DataBuff[RxLine-1]=RxBuff[0]; //把每次接收到的数据保存到缓存数组
Rx_flag=1;
if(RxBuff[0]==0xff) //接收结束标志位,这个数据可以自定义,根据实际需求,这里只做示例使用,不一定是0xff
{
Rx_flag_finish=1;
}
RxBuff[0]=0;
// err = R_GPT_Reset(&g_timer0_ctrl);
// assert(FSP_SUCCESS == err);
}
}
void printf_usart(void)
{
printf("length=%d\\\\r\\\\n",RxLine);
for(int i=0;i<RxLine;i++)
printf("data:[%d] = 0x%x\\\\r\\\\n",i,DataBuff[i]);
memset(DataBuff,0,sizeof(DataBuff));
RxLine=0;
Rx_flag_finish=0;
Rx_flag = 0;
}
/* 重定向 printf 输出 */
#if defined GNUC && !defined clang
int _write(int fd, char *pBuffer, int size); //防止编译警告
int _write(int fd, char *pBuffer, int size)
{
(void)fd;
R_SCI_UART_Write(&g_uart9_ctrl, (uint8_t *)pBuffer, (uint32_t)size);
while(uart_send_complete_flag == false);
uart_send_complete_flag = false;
return size;
}
#else
int fputc(int ch, FILE *f)
{
(void)f;
R_SCI_UART_Write(&g_uart9_ctrl, (uint8_t *)&ch, 1);
while(uart_send_complete_flag == false);
uart_send_complete_flag = false;
return ch;
}
#endif


重定义

11。串口0 ESP8266代码定义






void ESP8266 (uart_callback_args_t * p_args)
{
if(p_args->event == UART_EVENT_TX_COMPLETE)
{
uart_send_complete_flag = true;
}
if(p_args->event == UART_EVENT_RX_CHAR)
{
if(esp8266_cnt >= sizeof(esp8266_buf))
{
esp8266_cnt = 0; //防止串口被刷爆
}
esp8266_buf[esp8266_cnt++] = (uint8_t)p_args->data;
}
}
_Bool ESP8266_SendCmd(char *cmd, char *res)
{
unsigned char timeOut = 200;
R_SCI_UART_Write(&g_uart0_ctrl, (uint8_t *)cmd, strlen(cmd));
#if DEBUG_MODEM
printf("%s",cmd);
#endif
while(timeOut--)
{
if(ESP8266_WaitRecive() == REV_OK)
{
if(strstr((const char *)esp8266_buf, res) != NULL)
{
#if DEBUG_MODEM
printf("%s\\\\r\\\\n\\\\r\\\\n",res);
#endif
ESP8266_Clear();
return 0;
}
}
R_BSP_SoftwareDelay(10, BSP_DELAY_UNITS_MILLISECONDS);
}
return 1;
}
设置好了核心代码后,就可以跑通RSP8266了,
下面我来讲解如何获取城市天气预报信息。
12。这里我使用的是心知天气的api,百度搜索即可,可以申请免费试用付费版也可以使用免费版,这里以免费版为例。
心知天气api: https://api.seniverse.com/v3/weather/now.json?key=smtq3n0ixdggurox&location=beijing&language=zh-Hans&unit=c
当你注册好心知天气的账号并开通免费版或者申请试用后或获得一个密钥,将连接中的加粗字体key替换为你的密钥即可。
链接中加粗字体beijing为地区名,想换成哪里就是哪里的拼音。
链接中加粗字体zh-Hans为语言,如果想代码简单化就改成en,英文方式显示,中文处理过于复杂,本文即为在英语环境下处理
首先我们来看下本文程序思想:
1.连接WIFI
2.DNS解析域名获得IP
3.创建TCP连接
4.GET获得源代码
5.数据处理
1.连接WIFI
本步骤过于简单,不再赘述。
2.DNS解析域名获得IP
8266官方库中给出了espconn_gethostbyname()这样的一个函数,可以解析域名获得IP,但本人觉得放在8266中运行无疑是增加了负担,这一步完全可以通过PC端完成,本文便以最简便方式说明。
2.DNS解析域名获得IP
8266官方库中给出了espconn_gethostbyname()这样的一个函数,可以解析域名获得IP,但本人觉得放在8266中运行无疑是增加了负担,这一步完全可以通过PC端完成,本文便以最简便方式说明。
步骤:win+r键→输入cmd→输入ping api.seniverse.com并回车

红色框中的就是心知app的IP地址,后面要用到这个,非常关键!!
3.创建TCP连接
本步骤过于简单,不再赘述。
但要提一下的是创建TCP连接时,IP为上面取到的IP,端口则为80。
4.GET获得源代码
如想获取源代码,便需要以下知识。
客户端发送一个HTTP请求到服务器的请求消息包括以下格式:
请求行(request line)、请求头部(header)、空行和请求数据四个部分组成,下图给出了请求报文的一般格式。
而我们这次用的方法是GET,URL是:/v3/weather/now.json?key=Key&location=beijing&language=zh-Hans&unit=c,Key注意替换,协议版本是HTTP/1.1,HOST是 api.seniverse.com,剩下的我们并不需要,再加上请求报文一般格式上的符号,代码如下:
#define HEAD "GET /v3/weather/now.json?key=Key&location=shenzhen&language=en&unit=c HTTP/1.1\r\nHost: %s\r\n\r\n"
好了,主要原理就是这样的,现在我们开始实现代码逻辑。。
void ESP8266_Init(void)
{
ESP8266_Clear();
while(ESP8266_SendCmd("AT+RST\\r\\n", "OK"))
R_BSP_SoftwareDelay(1000, BSP_DELAY_UNITS_MILLISECONDS);
while(ESP8266_SendCmd("AT\\r\\n", "OK"))
R_BSP_SoftwareDelay(1000, BSP_DELAY_UNITS_MILLISECONDS);
while(ESP8266_SendCmd("AT+CWMODE=1\\r\\n", "OK"))
R_BSP_SoftwareDelay(1000, BSP_DELAY_UNITS_MILLISECONDS);
while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "GOT IP"))
R_BSP_SoftwareDelay(1000, BSP_DELAY_UNITS_MILLISECONDS);
while(ESP8266_SendCmd(ESP8266_ONENET_INFO, "CONNECT"))
R_BSP_SoftwareDelay(1000, BSP_DELAY_UNITS_MILLISECONDS);
while(ESP8266_SendCmd("AT+CIPMODE=1\\r\\n", "OK"))
R_BSP_SoftwareDelay(1000, BSP_DELAY_UNITS_MILLISECONDS);
command(Data);
command(TX_Data);
R_BSP_SoftwareDelay(10000, BSP_DELAY_UNITS_MILLISECONDS);
cJSON *json;
cJSON *Array_obj1;
cJSON *Array_obj2;
cJSON *Array_obj3;
cJSON *Array_obj4;
cJSON *Array;
json = cJSON_Parse((const char *) esp8266_buf );
Array_obj1=cJSON_GetObjectItem(json,"results");
int size=cJSON_GetArraySize(Array_obj1);
printf("\\n%d",size);
if(json == NULL)
printf("\\njson fmt error:%s\\n.", cJSON_GetErrorPtr());
else
{
Array=cJSON_GetArrayItem(Array_obj1,0);
Array_obj2=cJSON_GetObjectItem(Array,"now");
Array_obj3=cJSON_GetObjectItem(Array_obj2,"code");
R_BSP_SoftwareDelay(1000, BSP_DELAY_UNITS_MILLISECONDS);
Array_obj4=cJSON_GetObjectItem(Array_obj2,"temperature");
printf("n\\r%s\\n\\r",Array_obj3->valuestring);
printf("n\\r%s\\n\\r",Array_obj4->valuestring);
strcpy(Recive,Array_obj3->valuestring);
strcpy(Recive2,Array_obj4->valuestring);
printf("\\n\\r%s\\n\\r",esp8266_buf);
printf("\\n\\r%s\\n\\r",Recive2);
memset(Recive2,0x00,sizeof(Recive2));
if(Recive[0]==1&&(Recive[1]=='3'||Recive[1]=='4'||Recive[1]=='5'))
{
printf("\\n天气:雨\\n");
}
else if(Recive[0]=='0'||Recive[0]=='1')
{
printf("\\n天气:晴\\n");
}
else if(Recive[0]=='4'||Recive[0]=='5'||Recive[0]=='6')
{
printf("\\n天气:多云\\n");
}
else if(Recive[0]=='9')
{
printf("\\n天气:阴\\n");
}
memset(Recive,0x00,sizeof(Recive));
}
ESP8266_Clear();
cJSON_free(esp8266_buf);
cJSON_Delete(json);
}



我使用了cJSON来解析返回的天气信息,可以参看深圳市天气预报如下
打开串口助手,查看打印的天气信息

打开手机查看深圳天气,发现在31度,是比较准确的!!!
