接线为 串口2 接入ESP8266
esp8266.c
#include "stm32f10x.h"
//8266预处理文件
#include "esp8266.h"
//硬件驱动
#include "delay.h"
#include "usart.h"
//用得到的库
#include <string.h>
#include <stdio.h>
#include <cJSON.h>
#include <stdlib.h>
#include <ctype.h> // for isspace
#include <string.h> // for strlen
#include <stddef.h>
#include <stdarg.h>
char city_name[32]="beijing"; //用于存储你要获取的城市名字(拼音或地址码)
char wifi_ssid[32]="0000"; //用于存储你要连接的热点名字
char wifi_pass[32]="0000"; //用于存储你要连接的热点密码
int is_wifi_connected;//联网标志位
const char *blacklist[] = {
//过滤显示设置
"Host:",
"Date:",
"Connection:",
"Content-Type:",
"access-control-allow-origin:",
"Content-Length:",
"etag:",
"x-powered-by:",
"x-ratelimit-limit:",
"x-ratelimit-remaining:",
"x-ratelimit-reset:",
"x-request-id:",
"x-tenant-id:",
NULL // 结束标志
};
//用于在杂乱的数据中找到关键词
const char *ExtractField(const char *buf, const char *key, char *out, size_t out_size);
//用于屏蔽关键词输出
void Filtered_Usart_Printf(const char *line);
//======================
// 初始化ESP8266
//======================
void ESP8266_Init(void)
{
is_wifi_connected=0;//初始化联网标志位
Usart_Printf(USART1, "Send AT\r\n"); //输出到串口一
// 查询AT指令有效度
ESP8266_SendCmd("AT\r\n","OK");
Usart_Printf(USART1, "Send AT+CWJAP?\r\n");
// 查询是否已经连上网络
if(ESP8266_SendCmd("AT+CWJAP?\r\n",wifi_ssid)) {
is_wifi_connected=1;
} else {
if(ConnectToWiFi()) {
is_wifi_connected=1;//表示已经连上网络
} else {
Usart_Printf(USART_DEBUG, "No Connect WiFi\r\n");
}
}
}
//判断联网是否成功
_Bool ConnectToWiFi(void)
{
char cmd[64];
Usart_Printf(USART1, "Send AT\r\n");
// 启动8266 客户端模式 尝试联网
ESP8266_SendCmd("AT\r\n","OK");
Usart_Printf(USART1, "Send AT+CWMODE=1\r\n");
//尝试连接到网络
ESP8266_SendCmd("AT+CWMODE=1\r\n","OK");
if(sizeof(wifi_ssid)!=0 &&sizeof(wifi_pass)!=0) {
//网络信息没设置不执行联网程序
sprintf(cmd, "AT+CWJAP=\"%s\",\"%s\"\r\n", wifi_ssid, wifi_pass);
Usart_Printf(USART_DEBUG, "Try to connect WiFi: %s pass:%s\r\n", wifi_ssid,wifi_pass);
ESP8266_SendCmd(cmd,"CONNECTED");
Usart_Printf(USART_DEBUG, "connected %s\r\n", wifi_ssid);
return 1;//不设置逻辑运行成功即返回1表联网成功
}
}
//=================================
// cmd:命令 res:需要检查的返回指令
// 传递字符串从串口2打印
//=================================
int ESP8266_SendCmd( char *cmd,char *res)
{
Usart_Printf(USART2, cmd);
char uart_buf[128];//数据缓存机制
while(1) {
if (USART2_GetLine(uart_buf, sizeof(uart_buf)) > 0) {
// 缓冲数据中查找对应的关键词
if (strstr(uart_buf, res) != NULL) {
// 判断成功才打印(节约资源),收到的内容到串口1
Usart_Printf(USART_DEBUG, "Recv: ");
Usart_Printf(USART_DEBUG, uart_buf);
Usart_Printf(USART_DEBUG, "\r\n");
break;
}
if (strstr(uart_buf, "ERROR") != NULL) {
// 判断成功才打印(节约资源),收到的内容到串口1
Usart_Printf(USART_DEBUG, "ERROR Recv: ");
Usart_Printf(USART_DEBUG, uart_buf);
Usart_Printf(USART_DEBUG, "\r\n");
}
}
delay(500);
}
return 1;//返回1表执行成功
}
//=================================
//发送给服务端以获取数据的 GET/POST
//=================================
void GetWeatherAPI(void)
{
Usart_Printf(USART_DEBUG, "AT+CIPMUX=0\r\n");
ESP8266_SendCmd("AT+CIPMUX=0\r\n", "OK"); // 单连接模式
Usart_Printf(USART_DEBUG, "AT+CIPSTART=\"TCP\",\"api.seniverse.com\",80\r\n");
ESP8266_SendCmd("AT+CIPSTART=\"TCP\",\"api.seniverse.com\",80\r\n", "CONNECT");
Usart_Printf(USART_DEBUG, "AT+CIPMODE=0\r\n"); // 确保是非透传模式
ESP8266_SendCmd("AT+CIPMODE=0\r\n", "OK");
httpget();
}
void httpget(void)
{
// 计算 GET 请求长度(根据你构造的 redata)
char redata[256];
char key[] = "心知天气密匙";
sprintf(redata,
"GET /v3/weather/now.json?key=%s&location=%s&language=zh-Hans&unit=c HTTP/1.1\r\n"
"Host: api.seniverse.com\r\n"
"Connection: close\r\n"
"\r\n",
key, city_name);
char cmd[64];
sprintf(cmd, "AT+CIPSEND=%d\r\n", strlen(redata)); // 指定长度
Usart_Printf(USART_DEBUG, "%d", strlen(redata));
ESP8266_SendCmd(cmd, ">"); // 等待 > 提示符
// 发送实际内容
Usart_Printf(USART_DEBUG, "%s", redata);
Usart_Printf(USART2,redata); // 直接发送原始数据,不带 \r\n 请求体内部已经定义好了
char uart_buf[256];//数据缓存机制
char temperature_str[16];
char text_str[16];
while(1) {
if (USART2_GetLine(uart_buf, sizeof(uart_buf)) > 0) {
Filtered_Usart_Printf(uart_buf);
if (ExtractField(uart_buf, "text", text_str, sizeof(text_str)))
{
Usart_Printf(USART_DEBUG,"\r\n城市:%s\r\n",city_name);
Usart_Printf(USART_DEBUG,"\r\n当前天气:%s\r\n",text_str);
}
if (ExtractField(uart_buf, "temperature", temperature_str, sizeof(temperature_str))) {
int temperature = atoi(temperature_str);
Usart_Printf(USART_DEBUG,"temperature:%d\r\n",temperature);
}
}
Usart_Printf(USART2,"AT+CIPCLOSE\r\n");//关闭服务器
}
const char *ExtractField(const char *buf, const char *key, char *out, size_t out_size)
{
char search_key[64];
snprintf(search_key, sizeof(search_key), "\"%s\":\"", key);
const char *start = strstr(buf, search_key);
if (!start) return NULL;
start += strlen(search_key);
const char *end = strchr(start, '"');
if (!end) return NULL;
size_t len = end - start;
if (len >= out_size) len = out_size - 1;
strncpy(out, start, len);
out[len] = '\0';
return out;
}
//屏蔽输出函数
void Filtered_Usart_Printf(const char *line) {
for (int i = 0; blacklist[i] != NULL; i++) {
if (strstr(line, blacklist[i])) {
return;
}
}
Usart_Printf(USART_DEBUG, "%s", line);
}
esp8266.h
#ifndef __ESP8266_H
#define __ESP8266_H
#define USART_DEBUG USART1
// 全局变量声明(外部可见)
extern int is_wifi_connected;
void ESP8266_Init(void); //初始化操作
void httpget(void);
int ESP8266_SendCmd( char *cmd,char *res);
void GetWeatherAPI(void);
_Bool ConnectToWiFi(void);
#endif
usart.c
#include "usart.h"
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include "stm32f10x_usart.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "misc.h"
#include "esp8266.h"
uint16_t usart2_index = 0;
uint8_t usart2_rx_buffer[USART2_RX_BUFFER_SIZE];
volatile uint16_t usart2_rx_head = 0; // 写指针
volatile uint16_t usart2_rx_tail = 0; // 读指针
uint8_t usart1_buf[USART1_BUF_SIZE];
uint8_t usart2_buf[USART2_BUF_SIZE];
// 串口1接收缓冲及状态
u8 USART1_RX_BUF[USART1_REC_LEN];
u16 USART1_RX_STA = 0;
// 串口2接收缓冲及状态
u8 USART2_RX_BUF[USART2_REC_LEN];
u16 USART2_RX_STA = 0;
void USART1_Init(u32 bound) {
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
// PA9 - TXD
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// PA10 - RXD
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置串口1
USART_InitStruct.USART_BaudRate = bound;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART1, &USART_InitStruct);
// 中断配置
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_Cmd(USART1, ENABLE);
// NVIC配置
NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
void USART2_Init(u32 bound) {
GPIO_InitTypeDef GPIO_InitStruct;
USART_InitTypeDef USART_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
// 使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // PA2/PA3
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
// PA2 - TXD
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// PA3 - RXD
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置串口2
USART_InitStruct.USART_BaudRate = bound;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART2, &USART_InitStruct);
// 中断配置
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
USART_Cmd(USART2, ENABLE);
// NVIC中断配置
NVIC_InitStruct.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 3;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
}
void Usart_SendString(USART_TypeDef *USARTx, const char *str) {
while (*str) {
USART_SendData(USARTx, (uint8_t)*str++);
while (USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);
}
}
void Usart_Printf(USART_TypeDef *USARTx, const char *fmt, ...) {
while (USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);//等待空闲
char buffer[256];
va_list ap;
va_start(ap, fmt);
vsnprintf(buffer, sizeof(buffer), fmt, ap);
va_end(ap);
Usart_SendString(USARTx, buffer);
}
void USART1_IRQHandler(void) {
if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
uint8_t ch = USART_ReceiveData(USART1);
if ((USART1_RX_STA & 0x8000) == 0) {
if ((USART1_RX_STA & 0x4000) != 0) {
if (ch == '\n') {
USART1_RX_STA |= 0x8000; // 完整帧接收完成
} else {
USART1_RX_STA = 0; // 出错重置
}
} else {
if (ch == '\r') {
USART1_RX_STA |= 0x4000;
} else {
USART1_RX_BUF[USART1_RX_STA++ & 0x7FFF] = ch;
if (USART1_RX_STA >= USART1_REC_LEN)
USART1_RX_STA = 0;
}
}
}
}
}
void USART2_IRQHandler(void) {
if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) {
uint8_t data = USART_ReceiveData(USART2);
uint16_t next_head = (usart2_rx_head + 1) % USART2_RX_BUFFER_SIZE;
if (next_head != usart2_rx_tail) { // 如果没有发生缓冲区满的情况
usart2_rx_buffer[usart2_rx_head] = data; // 存入数据
usart2_rx_head = next_head; // 更新写指针
return;
}
if (next_head == usart2_rx_tail) {
// 缓冲区满,允许覆盖
usart2_rx_tail = (usart2_rx_tail + 1) % USART2_RX_BUFFER_SIZE;
}
usart2_rx_buffer[usart2_rx_head] = data;
usart2_rx_head = next_head;
}
}
/**
* @brief 从 USART2 的 Ring Buffer 中读取一个字节
* @param data: 用于保存读取到的数据
* @retval 1: 成功读取, 0: 缓冲区为空
*/
int USART2_GetLine(char *buf, int max_len) {
int i = 0;
while (i < max_len - 1) {
if (usart2_rx_tail == usart2_rx_head) {
break; // 缓冲区为空
}
char ch = usart2_rx_buffer[usart2_rx_tail];
usart2_rx_tail = (usart2_rx_tail + 1) % USART2_RX_BUFFER_SIZE;
buf[i++] = ch;
if (ch == '\n') { // 遇到换行符结束
buf[i] = '\0';
return i;
}
}
buf[i] = '\0'; // 补上字符串结束符
return i;
}
int USART1_WaitRecive(void) {
u32 timeout = 0xFFFFF;
while ((USART1_RX_STA & 0x8000) == 0) {
if (--timeout == 0) return -1;
}
memcpy(usart1_buf, USART1_RX_BUF, USART1_RX_STA & 0x7FFF);
usart1_buf[USART1_RX_STA & 0x7FFF] = '\0';
USART1_ClearRxBuffer();
return 0;
}
void USART1_ClearRxBuffer(void) {
memset(USART1_RX_BUF, 0, USART1_REC_LEN);
USART1_RX_STA = 0;
}
int USART2_WaitRecive(char *res) {
u32 timeout = 0xFFFFF;
while ((USART2_RX_STA & 0x8000) == 0) {
if (--timeout == 0) return -1;
}
memcpy(usart2_buf, USART2_RX_BUF, USART2_RX_STA & 0x7FFF);
usart1_buf[USART2_RX_STA & 0x7FFF] = '\0';
USART1_ClearRxBuffer();
return 0;
}
void USART2_ClearRxBuffer(void) {
memset(USART2_RX_BUF, 0, USART2_REC_LEN);
USART2_RX_STA = 0;
}
#pragma import(__use_no_semihosting)
struct __FILE { int handle; };
FILE __stdout;
void _sys_exit(int x) { x = x; }
void _ttywrch(int ch) { ch = ch; }
int __io_putchar(int ch) {
USART_SendData(USART1, (uint8_t)ch);
while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
return ch;
}
int __io_getchar(FILE *f) {
f = f;
while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
return USART_ReceiveData(USART1);
}
usart.h
#ifndef __USART_H__
#define __USART_H__
#include "stm32f10x.h"
// 接收缓冲大小
#define USART1_REC_LEN 256
#define USART2_REC_LEN 256
// 主程序访问接收数据用的缓冲区
#define USART1_BUF_SIZE 256
#define USART2_BUF_SIZE 256
#define USART2_RX_BUFFER_SIZE 2048
// 接收缓冲和状态变量
extern u8 USART1_RX_BUF[USART1_REC_LEN];
extern u16 USART1_RX_STA;
extern u8 USART2_RX_BUF[USART2_REC_LEN];
extern u16 USART2_RX_STA;
// 数据缓冲(供主程序读取)
extern u8 usart1_buf[USART1_BUF_SIZE];
extern u8 usart2_buf[USART2_BUF_SIZE];
// 初始化函数
void USART1_Init(u32 bound);
void USART2_Init(u32 bound);
// 发送函数
void Usart_SendString(USART_TypeDef *USARTx, const char *str);
void Usart_Printf(USART_TypeDef *USARTx, const char *fmt, ...);
// 接收处理函数
int USART1_WaitRecive(void);
void USART1_ClearRxBuffer(void);
int USART2_GetLine(char *buf, int max_len);
int USART2_WaitRecive(char *res);
void USART2_ClearRxBuffer(void);
#endif // __USART_H__
main.c
//头文件
#include "stm32f10x.h"
#include "GPIOLIKE51.h"
#include "usart.h"
#include "esp8266.h"
int main(void)
{
USART1_Init(9600);
USART2_Init(115200);
Usart_Printf(USART1, "Connect WiFi\r\n");
ESP8266_Init();
if(is_wifi_connected==1){
GetWeatherAPI(); //更新天气
}else{
Usart_Printf(USART1,"No connect to");
}
}