RT-Thread网络通信 --- AT组件与ESP8266联网实战
前言
嵌入式设备要实现联网通信,AT命令是最常用的方式之一。RT-Thread提供了完善的AT组件,配合ESP8266 AT设备库,可以快速实现WiFi连接和网络通信。本文将介绍AT命令基础、AT组件架构、ESP8266设备库的使用,以及传感器框架的基本用法。
一、AT 命令基础
1.1 什么是AT命令?
AT命令是一种标准化的指令集,最早用于控制调制解调器,后来广泛应用于GSM、WiFi、蓝牙等通信模块的控制。AT命令通过串口传输,格式简单:
发送: AT+CWJAP="SSID","PASSWORD"\r\n
响应: OK
1.2 RT-Thread AT 组件
AT组件包含两个核心部分:
| 组件 | 角色 | 功能 |
|---|---|---|
| AT Server | 接收端 | 接收并解析来自客户端的命令,返回响应 |
| AT Client | 发送端 | 向外部模块发送命令,接收和解析响应 |
在典型的物联网场景中,MCU作为AT Client,通过串口向ESP8266等WiFi模块(AT Server)发送AT命令。
二、AT Server
2.1 配置
在 rtconfig.h 中启用:
c
#define RT_USING_AT
#define AT_USING_SERVER
#define AT_SERVER_DEVICE "uart3"
2.2 初始化
c
int at_server_init(void);
系统会创建 at_server 线程处理命令接收和解析。
2.3 自定义AT命令
c
static at_result_t at_test_exec(void)
{
at_server_printfln("AT test command executed!");
return 0;
}
AT_CMD_EXPORT("AT+TEST", =<value1>[,<value2>], NULL, NULL, NULL, at_test_exec);
参数说明:
- 第1参数:命令名称
- 第2参数:参数格式(
<>必选,[]可选) - 第3-6参数:测试/查询/设置/执行 对应的处理函数
三、AT Client
3.1 配置与初始化
c
#define RT_USING_AT
#define AT_USING_CLIENT
#define AT_CLIENT_NUM_MAX 1
c
int at_client_init(const char *dev_name, rt_size_t recv_bufsz);
3.2 响应结构体
c
struct at_response
{
char *buf; // 接收数据缓冲区
rt_size_t buf_size; // 缓冲区大小
rt_size_t line_num; // 接收行数限制
rt_int32_t timeout; // 响应超时时间
};
3.3 核心API
| API | 说明 |
|---|---|
at_create_resp(buf_size, line_num, timeout) |
创建响应对象 |
at_delete_resp(resp) |
删除响应对象 |
at_exec_cmd(resp, cmd_expr, ...) |
发送命令并接收响应 |
at_resp_get_line(resp, line) |
获取指定行数据 |
at_resp_parse_line_args(resp, line, expr, ...) |
解析指定行数据 |
3.4 URC(非请求信息)处理
URC是指外部模块主动推送的数据(如WiFi连接状态变化、收到网络数据等),通过注册回调表来处理:
c
static struct at_urc urc_table[] = {
{"WIFI CONNECTED", "\r\n", urc_conn_func},
{"+RECV", ":", urc_recv_func},
};
at_set_urc_table(urc_table, sizeof(urc_table) / sizeof(urc_table[0]));
3.5 多客户端支持
AT组件支持同时连接多个外部模块:
c
/* 初始化两个客户端 */
at_client_init("uart2", 512);
at_client_init("uart3", 512);
/* 获取指定客户端 */
at_client_t client = at_client_get("uart3");
at_obj_exec_cmd(client, resp, "AT+CIFSR");
3.6 实战:通过AT命令扫描WiFi并连接
c
#include <at.h>
#define AT_CLIENT_UART_NAME "uart2"
#define AT_RESP_BUFF_SIZE 2048
#define WIFI_SSID "rtthread"
#define WIFI_PASSWORD "12345678"
int scan_wifi_esp8266(void)
{
at_client_t client = RT_NULL;
at_response_t resp = RT_NULL;
/* 初始化AT Client */
at_client_init(AT_CLIENT_UART_NAME, AT_RESP_BUFF_SIZE);
client = at_client_get(AT_CLIENT_UART_NAME);
/* 创建响应对象(10秒超时) */
resp = at_create_resp(AT_RESP_BUFF_SIZE, 0, rt_tick_from_millisecond(10000));
/* 扫描周围WiFi */
if (at_obj_exec_cmd(client, resp, "AT+CWLAP") == RT_EOK)
{
for (int i = 1; i <= 15; i++)
{
const char *line = at_resp_get_line(resp, i);
if (line) rt_kprintf("WiFi: %s\n", line);
else break;
}
}
/* 连接到指定WiFi */
if (at_obj_exec_cmd(client, resp, "AT+CWJAP=\"%s\",\"%s\"",
WIFI_SSID, WIFI_PASSWORD) == RT_EOK)
{
rt_kprintf("WiFi connected!\n");
}
at_delete_resp(resp);
return 0;
}
四、ESP8266 AT 设备库
4.1 为什么用ESP8266库而不直接写AT命令?
| 对比项 | 直接AT命令 | ESP8266库 |
|---|---|---|
| 开发效率 | 需手动拼接命令和解析响应 | 高层API,一行调用 |
| 错误处理 | 需手动处理超时/重试 | 内置自动重试 |
| URC处理 | 需手动注册回调 | 已内置WiFi/Socket事件处理 |
| Socket接口 | 无 | 对接标准BSD Socket |
| 版本兼容 | 需自行适配 | 内置版本检测 |
4.2 主要模块
| 模块 | 文件 | 功能 |
|---|---|---|
| 设备初始化 | at_device_esp8266.c |
WiFi连接、设备复位、版本管理 |
| 网络配置 | at_device_esp8266.c |
IP/DNS/DHCP配置 |
| Socket管理 | at_socket_esp8266.c |
TCP/UDP连接、数据收发 |
4.3 配置与初始化
1. 启用配置(rtconfig.h):
c
#define AT_DEVICE_USING_ESP8266
#define AT_USING_SOCKET
2. 注册设备并连接WiFi:
c
esp8266_device_class_register();
esp8266_wifi_info_set(device, &info);
4.4 核心API
设备初始化与控制
| API | 说明 |
|---|---|
esp8266_init(device) |
初始化设备(配置WiFi模式、连接等) |
esp8266_reset(device) |
复位设备(发送AT+RST) |
esp8266_wifi_info_set(device, info) |
设置WiFi信息并连接 |
esp8266_get_at_version() |
获取AT固件版本 |
网络配置
| API | 说明 |
|---|---|
esp8266_netdev_set_addr_info(...) |
设置IP/网关/子网掩码 |
esp8266_netdev_set_dns_server(...) |
设置DNS服务器 |
esp8266_netdev_set_dhcp(...) |
开启/关闭DHCP |
esp8266_netdev_ping(...) |
Ping测试 |
Socket操作
| API | 说明 |
|---|---|
esp8266_socket_connect(socket, ip, port, type, is_client) |
建立TCP/UDP连接 |
esp8266_socket_send(socket, buff, size, type) |
发送数据 |
esp8266_socket_close(socket) |
关闭连接 |
esp8266_domain_resolve(name, ip) |
域名解析 |
esp8266_socket_set_event_cb(event, cb) |
注册Socket事件回调 |
4.5 事件与回调
ESP8266库内置了URC事件处理:
| 事件 | 触发条件 |
|---|---|
WIFI CONNECTED |
WiFi连接成功 |
WIFI DISCONNECT |
WiFi断开 |
SEND OK |
数据发送完成 |
+IPD |
收到网络数据 |
CLOSED |
Socket连接关闭 |
五、传感器框架
传感器框架为物联网数据采集提供了统一接口,是将传感器数据上传到云平台的基础。
5.1 设计目标
通过标准化接口访问不同厂商的传感器,提高代码复用性。传感器作为I/O设备,遵循 rt_device_* 接口规范。
5.2 工作模式
| 模式 | 打开标志 | 适用场景 |
|---|---|---|
| 轮询模式 | RT_DEVICE_FLAG_RDONLY |
低频数据采集 |
| 中断模式 | RT_DEVICE_FLAG_INT_RX |
数据变化频繁 |
| FIFO模式 | RT_DEVICE_FLAG_FIFO_RX |
低功耗批量采集 |
5.3 电源管理
c
rt_device_control(dev, RT_SENSOR_CTRL_SET_POWER, (void *)RT_SEN_POWER_HIGH);
支持掉电、普通、低功耗、高性能四种模式。
5.4 传感器数据结构
c
struct rt_sensor_data
{
union {
struct { rt_int32_t x, y, z; } acce; /* 加速度 */
struct { rt_int32_t x, y, z; } gyro; /* 陀螺仪 */
struct { rt_int32_t x, y, z; } mag; /* 磁力计 */
rt_int32_t temp; /* 温度 */
rt_int32_t humi; /* 湿度 */
rt_int32_t baro; /* 气压 */
} data;
rt_uint32_t timestamp; /* 时间戳 */
};
5.5 控制命令
| 命令 | 功能 |
|---|---|
RT_SENSOR_CTRL_GET_ID |
获取设备ID |
RT_SENSOR_CTRL_GET_INFO |
获取设备信息 |
RT_SENSOR_CTRL_SET_RANGE |
设置测量范围 |
RT_SENSOR_CTRL_SET_ODR |
设置数据输出速率 |
RT_SENSOR_CTRL_SET_POWER |
设置电源模式 |
5.6 DHT11 温湿度传感器示例
c
#include <rtthread.h>
#include <rtdevice.h>
#include "sensor.h"
#include "sensor_dallas_dht11.h"
#define DHT11_DATA_PIN GET_PIN(A, 7)
static void read_temp_entry(void *parameter)
{
rt_device_t dev = rt_device_find("temp_micu");
if (dev == RT_NULL) return;
rt_device_open(dev, RT_DEVICE_FLAG_RDWR);
rt_uint8_t freq = 1;
rt_device_control(dev, RT_SENSOR_CTRL_SET_ODR, (void *)&freq);
while (1)
{
struct rt_sensor_data data;
if (rt_device_read(dev, 0, &data, 1) == 1)
{
uint8_t temp = data.data.temp & 0xFFFF;
uint8_t humi = (data.data.temp >> 16) & 0xFF;
rt_kprintf("温度: %d°C, 湿度: %d%%\n", temp, humi);
}
rt_thread_delay(1000);
}
}
static int dht11_sample(void)
{
rt_thread_t thread = rt_thread_create("dht_tem", read_temp_entry,
RT_NULL, 1024,
RT_THREAD_PRIORITY_MAX / 2, 20);
if (thread) rt_thread_startup(thread);
return RT_EOK;
}
INIT_APP_EXPORT(dht11_sample);
总结
| 要点 | 内容 |
|---|---|
| AT命令 | 标准化串口指令集,控制通信模块 |
| AT组件 | Server(接收端)+ Client(发送端) |
| URC处理 | 自动处理模块主动推送的事件 |
| ESP8266库 | 封装AT命令,提供WiFi连接和Socket通信 |
| 传感器框架 | 统一接口访问不同传感器 |
到这里,设备已经能够联网并采集数据。