@安小芯
这里使用N32G430设计了基于wifi通信的远程天气获取的设计。
使用的是ESP8266-01s的wifi模块,烧录at固件,通过AT指令建立连接,并通过get方式获取天气数据。
这里使用的是心知天气的api,免费的,这就不再赘述如何去注册了。
只要是通过串口发送get指令,然后获取返回值,自己解析相关的数据即可。
请求地址如下示例:
● https://api.seniverse.com/v4?fields=air_daily&locations=39:118&key=YOUR_PRIVATE_KEY
注册以后,需要填写自己的key,就可以免费使用了。
最先就是要测试串口的。这里使用的是官网自带的串口代码修改的,即可需要开启串口中断。
/* USARTy and USARTz configuration ------------------------------------------------------*/
USART_InitStructure.BaudRate = 115200;
USART_InitStructure.WordLength = USART_WL_8B;
USART_InitStructure.StopBits = USART_STPB_1;
USART_InitStructure.Parity = USART_PE_NO;
USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
/* Configure USARTy and USARTz */
USART_Initializes(USARTy, &USART_InitStructure);
USART_Initializes(USARTz, &USART_InitStructure);
/* Enable USARTy Receive and Transmit interrupts */
USART_Interrput_Enable(USARTy, USART_INT_RXDNE);
//USART_Interrput_Enable(USARTy, USART_INT_TXDE);
/* Enable USARTz Receive and Transmit interrupts */
USART_Interrput_Enable(USARTz, USART_INT_RXDNE);
//USART_Interrput_Enable(USARTz, USART_INT_TXDE);
/* Enable the USARTy and USARTz */
USART_Enable(USARTy);
USART_Enable(USARTz);
开启中断以后,就是需要通过串口与ESP8266建立连接了,这里是做了一个函数。
void ESP8266_ATSendBuf(uint8_t* buf,uint16_t len)
{
memset(usart2_rxbuf,0, USART2_MAX);
USART2_RX_STA = 0;
for(uint16_t i = 0; i<len; i++)
{
USART_Data_Send(USART2, (uint8_t)*(buf+i));
while (USART_Flag_Status_Get(USART2, USART_FLAG_TXDE) == RESET);
}
}
只要通过串口向ESP8266发送AT指令就,就可以实现自己的功能。
通过ESP8266实现的功能就是下面几个,
1,初始化ESP8266 2 建立ESP8266与wifi的连接 3 建立与网址的TCP连接 4 获取天气数据
void cfg_Esp8266(void)
{
if(ESP8266_Init())
{
printf("ESP8266 init succ \r\n");
}
else printf("ESP8266 init fail!\r\n");
//连接热点
if(ESP8266_ConnectAP(WIFI_NAME,WIFI_PASSWD))
{
printf("Connected to WIFI!\r\n");
}
else printf("to WIFI fail\r\n");
SysTick_Delay_Ms(5000);
if(ESP8266_ConnectServer("TCP","api.seniverse.com",80)!=0)
{
printf("to Server succ!\r\n");
}
else printf("to Server Fail!\r\n");
}
这里只是发送数据,如何接收数据?使用的还是串口中断
void USARTz_IRQHandler(void)
{
if (USART_Interrupt_Status_Get(USARTz, USART_INT_RXDNE) != RESET)
{
/* Read one byte from the receive data register */
char rr= USART_Data_Receive(USARTz);
flag_rev=1;
cnt_rev=0;
USART_Data_Send(USARTy, rr);
if(USART2_RX_STA<USART2_MAX) //还可以接收数据
{
usart2_rxbuf[USART2_RX_STA++]=rr; //记录接收到的值
} else
{
USART2_RX_STA=0; //强制标记接收完成
}
}
}
在这里,讲述一下技巧,如何使用定时器判断是否发送完成。如果间隔10ms没有收到数据,就判断数据结束。
使用的是定时器6实现的这个功能。每次在串口中断开启接收数据,并清空计数。如果持续20ms没有数据,则计数器会大于20,判定串口接收一帧数据完成。
void TIM6_IRQHandler(void)
{
if (TIM_Interrupt_Status_Get(TIM6, TIM_INT_UPDATE) != RESET)
{
TIM_Interrupt_Status_Clear(TIM6, TIM_INT_UPDATE);
time_cnt++;
if(flag_rev==1)
cnt_rev++;
if(cnt_rev>20)
Rx_Ok=1;
}
}
这里是使用的按一下获取当前的最新天气。
if(GPIO_Input_Pin_Data_Get(KEY2_PORT, KEY2_PIN) == PIN_RESET) {
SysTick_Delay_Ms(100);
while(GPIO_Input_Pin_Data_Get(KEY2_PORT, KEY2_PIN) == PIN_RESET);
Reset_ESP8266_RxBuffer();
ESP8266_ATSendString((char*)"GET /v3/weather/now.json?key=ddd&location=jinan&language=en&unit=c HTTP/1.1\r\nContent-Type:application/json;charset=utf-8\r\nHost:api.seniverse.com\r\nConnection: Keep Alive\r\n\r\n");
}
获取的天气数据如何解析呢?就是根据字符串的位置进行判断。
char *pos=strstr(usart2_rxbuf,"code");
if(*pos)
{ //printf("%s\r\n",pos);
if(*(pos+8)>='0' && *(pos+8)<='9')
weather_code= (*(pos+7)-'0')*10+*(pos+8)-'0';
else weather_code= (*(pos+7)-'0');
}
if(weather_code>40)weather_code=39;
pos=strstr(usart2_rxbuf,"temperature");
if(*pos)
{
// printf("%s\r\n",pos);
if(*(pos+15)>='0' && *(pos+15)<='9')
temper= (*(pos+14)-'0')*10+*(pos+15)-'0';
else temper= (*(pos+14)-'0');
}
printf("weather code:%d %s temp:%d\r\n",weather_code,weather_ENdis[weather_code],temper);
//printf("%s\r\n",usart2_rxbuf);
sprintf(s_temp,"Weat:%s ",weather_ENdis[weather_code]);
OLED_ShowStringCN(0,32,s_temp,1);
sprintf(s_temp,"Temp:%d 'C ",temper);
OLED_ShowStringCN(0,48,s_temp,1);
memset(usart2_rxbuf,0,1024);
OLED_Refresh();
附上效果图。为获取天气之前
获取天气以后。
工程文件
|