/* 通过RTT例子修改 通过ESP8266作为Server,手机作为Client的穿透方式 通过手机控制野火开发板板载RGB灯的程序 */ #include <rtthread.h> #include <rtdevice.h> #include <board.h> #define LED0_PIN GET_PIN(B, 1) //定位到野火开发板上两个RGB相关的寄存器上 #define LED0_PINE GET_PIN(B, 0) #define SAMPLE_UART_NAME "uart3" static rt_device_t serial; /* 串口设备句柄 */ struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 配置参数 */ /* 用于接收消息的信号量 */ static struct rt_semaphore rx_sem; static rt_device_t serial; /* 接收数据回调函数 */ static rt_err_t uart_input(rt_device_t dev, rt_size_t size) { /* 串口接收到数据后产生中断,调用此回调函数,然后发送接收信号量 */ rt_sem_release(&rx_sem); return RT_EOK; } static void serial_thread_entry(void *parameter) { char ch; while (1) { /* 从串口读取一个字节的数据,没有读取到则等待接收信号量 */ while (rt_device_read(serial, -1, &ch, 1) != 1) { /* 阻塞等待接收信号量,等到信号量后再次读取数据 */ rt_sem_take(&rx_sem, RT_WAITING_FOREVER); } // 检测接受缓存区内的字符,与手机发送字符对应,已达到检测开灯的效果 if(ch == 'a'){ rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT); rt_pin_mode(LED0_PINE, PIN_MODE_OUTPUT); } if(ch == '0'){ rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT); rt_pin_mode(LED0_PINE, PIN_MODE_OUTPUT); } if(ch == 'u'){ rt_pin_write(LED0_PIN, PIN_HIGH); rt_thread_mdelay(500); } if(ch == 'n'){ rt_pin_write(LED0_PIN, PIN_LOW); rt_thread_mdelay(500); } if(ch == 'b'){ rt_pin_write(LED0_PINE, PIN_HIGH); rt_thread_mdelay(500); } if(ch == 'i'){ rt_pin_write(LED0_PINE, PIN_LOW); rt_thread_mdelay(500); } } } static int mdr1(int argc, char *argv[]) { rt_err_t ret = RT_EOK; char uart_name[RT_NAME_MAX]; if (argc == 2) { rt_strncpy(uart_name, argv[1], RT_NAME_MAX); } else { rt_strncpy(uart_name, SAMPLE_UART_NAME, RT_NAME_MAX); } /* 查找系统中的串口设备 */ serial = rt_device_find(uart_name); rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config); if (!serial) { rt_kprintf("find %s failed!\n", uart_name); return RT_ERROR; } /* 初始化信号量 */ rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO); /* 以中断接收及轮询发送模式打开串口设备 */ rt_device_open(serial, RT_DEVICE_FLAG_INT_RX); /* 打开设备后才可修改串口配置参数 */ rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config); /* 设置接收回调函数 */ rt_device_set_rx_indicate(serial, uart_input); /* 发送字符串 */ // rt_device_write(serial, 0, str, (sizeof(str) - 1)); /* 创建 serial 线程 */ rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10); /* 创建成功则启动线程 */ if (thread != RT_NULL) { rt_thread_startup(thread); } else { ret = RT_ERROR; } return ret; } /* 导出到 msh 命令列表中 */ MSH_CMD_EXPORT(mdr1, uart JUN);
以上先给出例程,将其放入RTT的工程中进行编译并烧入开发板
在完成实验之前请确保esp8266与手机在同一局域网下
打开SSCOM,看到RTT的开机信息后输入:at client
在AT界面中输入
- AT+CIPMUX=1
- AT+CIPSERVER=1,8081
- AT+CIFSR
msh />at client ======== Welcome to using RT-Thread AT command client cli ======== Cli will forward your command to server port(uart3). Press 'ESC' to exit. AT+CIPMUX=1 OK AT+CIPSERVER=1,8081 OK
AT+CIFSR +CIFSR:STAIP,"192.168.0.110" +CIFSR:STAMAC,"cc:50:e3:72:62:2d" OK
打开手机app 有人网络调试助手
切换到TCP client,选择 增加,在IP地址中填入你esp8266的ip地址
点击增加,显示连接成功
在手机端发送 ‘a’ 字符,可以看到开发板上的RGB灯亮了
再尝试0,u,n,b,i,开发板分别做出了不同反应
分析一下代码,先创建了用于接受消息堵塞的信号量
在创建了一个回调函数<uart_input>,若串口以中断接收模式打开,当串口接收到一个数据产生中断时,就会调用回调函数,并且会把此时缓冲区的数据大小放在 size 参数里,把串口设备句柄放在 dev 参数里供调用者获取。
然后创建了一个用户入口函数<serial_thread_entry>主要用来读取数据后检测并使能GPIO
然后创建了一个线程函数,进行初始化信号量和串口基本环境初始化,成功后启动线程,并调用用户入口函数,来达到预期效果