在RT-THREAD建立工程
修改程序下载
启动cubemx配置
4.下载RT-THREAD组件
https://www.rt-thread.org/download/cube/RealThread.RT-Thread.pdsc
正常配置cubemx下各个管脚
(1)2个led对应,PB5,PE5,
- UART1串口1PA9,PA10,
- debug调试先swd
生成代码
不用keil打开,关闭cubemx
工程分析
起作用的还是rt-thread中main函数,因此需要把cubemx下的设备硬件初始化程序移植到rt-thread下main函数中。
cubemx设备驱动初始化代码移植
在main函数中移植对应的驱动文件.h文件
编译后会报错,这是因为,在rt-thread工程中默认只加载了cubemx生成的main.c文件,其他用户的.c文件都没有加载,需要自己手动加载。
加载其他驱动.c文件
右键同步就在工程中添加了对应的文件,然后在编译就不报错了。
添加LED灯闪烁
可以使用hal库进行编程控制
RT-thread多任务流水灯
2.1定义任务入口函数和任务初始化函数
//自定义线程
#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 512
#define THREAD_TIMESLICE 5
/* 使用静态线程时,线程的栈需要设置字节对齐 */
ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t thread_stack[THREAD_STACK_SIZE];
static struct rt_thread tid1;
/* 线程 1 的入口函数 */
static void thread1_entry(void *parameter)
{
rt_uint32_t count = 0;
while (1)
{
rt_kprintf("thread1 count: %d\n", count ++);
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5);
rt_thread_mdelay(500);
}
}
/* 线程示例 */
int thread_sample(void)
{
/* 静态创建线程 */
/* 初始化线程 1,名称是 thread1,入口是 thread1_entry*/
rt_thread_init(&tid1,
"thread1",
thread1_entry,
RT_NULL,
thread_stack,
THREAD_STACK_SIZE,
THREAD_PRIORITY,
THREAD_TIMESLICE);
/* 启动线程 */
rt_thread_startup(&tid1);
return 0;
}
2.2 main函数中进行任务调用
下载后,程序及可以正常执行
添加OLED驱动插件
添加软件I2C驱动
定义I2C使用的引脚,和I2C编号
这里使用I2C1,PB6/PB7
编译过程中如果有报错Error_Handler,屏蔽这个报错语句
添加SSD1306插件驱动
这个需要联网进行git下载,一次不行就在下载一次
修改设备地址和对应的I2C设备名称
编写使用代码
github上有使用案例可以参考
https://github.com/luhuadong/rtt-ssd1306/blob/main/examples/
AT指令控制ESP8266
https://blog.csdn.net/weixin_42328389/article/details/125152975
开启UART3的PB10/PB11
(正点原子的精英开发板)
在cubemx进行配置,然后在board.h中配置
开启控制引脚为高电平PA4
(正点原子的精英开发板)
启用AT指令插件
在msh下启用AT指令模式
然后可以测试各种AT指令
利用代码发送指令进行指令交互
服务器下发数据给MCU接收
https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/at/at?id=at-client
启用at_device插件
https://github.com/RT-Thread-packages/at_device
https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/application-note/components/at/an0014-at-client?id=%e5%ba%94%e7%94%a8-at-%e7%bb%84%e4%bb%b6%e8%bf%9e%e6%8e%a5-esp8266-%e6%a8%a1%e5%9d%97
启用插件
配置参数
参考案例代码1-cli下使用ping命令
应用特定协议进行应用
TCPClient模式使用
https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/tutorial/qemu-network/tcpclient/tcpclient?id=%e5%87%86%e5%a4%87%e5%b7%a5%e4%bd%9c
https://github.com/RT-Thread-packages/network-sample/blob/master/tcpclient_sample.c
/*
* Copyright (c) 2006-2022, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
*
*/
/*
* 程序清单:tcp 客户端
*
* 这是一个 tcp 客户端的例程
* 导出 tcpclient 命令到控制终端
* 命令调用格式:tcpclient URL PORT
* URL:服务器地址 PORT::端口号
* 程序功能:接收并显示从服务端发送过来的信息,接收到开头是 'q' 或 'Q' 的信息退出程序
*/
#include <rtthread.h>
#include <sys/socket.h> /* 使用BSD socket,需要包含socket.h头文件 */
#include <netdb.h>
#include <string.h>
#include <finsh.h>
#define BUFSZ 1024
static const char send_data[] = "This is TCP Client from RT-Thread."; /* 发送用到的数据 */
static void tcpclient(int argc, char **argv)
{
int ret;
char *recv_data;
struct hostent *host;
int sock, bytes_received;
struct sockaddr_in server_addr;
const char *url;
int port;
if (argc < 3)
{
rt_kprintf("Usage: tcpclient URL PORT\n");
rt_kprintf("Like: tcpclient 192.168.12.44 5000\n");
return ;
}
url = argv[1];
port = strtoul(argv[2], 0, 10);
/* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */
host = gethostbyname(url);
/* 分配用于存放接收数据的缓冲 */
recv_data = rt_malloc(BUFSZ);
if (recv_data == RT_NULL)
{
rt_kprintf("No memory\n");
return;
}
/* 创建一个socket,类型是SOCKET_STREAM,TCP类型 */
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
/* 创建socket失败 */
rt_kprintf("Socket error\n");
/* 释放接收缓冲 */
rt_free(recv_data);
return;
}
/* 初始化预连接的服务端地址 */
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
/* 连接到服务端 */
if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
/* 连接失败 */
rt_kprintf("Connect fail!\n");
closesocket(sock);
/*释放接收缓冲 */
rt_free(recv_data);
return;
}
else
{
/* 连接成功 */
rt_kprintf("Connect successful\n");
}
while (1)
{
/* 从sock连接中接收最大BUFSZ - 1字节数据 */
bytes_received = recv(sock, recv_data, BUFSZ - 1, 0);
if (bytes_received < 0)
{
/* 接收失败,关闭这个连接 */
closesocket(sock);
rt_kprintf("\nreceived error,close the socket.\r\n");
/* 释放接收缓冲 */
rt_free(recv_data);
break;
}
else if (bytes_received == 0)
{
/* 默认 recv 为阻塞模式,此时收到0认为连接出错,关闭这个连接 */
closesocket(sock);
rt_kprintf("\nreceived error,close the socket.\r\n");
/* 释放接收缓冲 */
rt_free(recv_data);
break;
}
/* 有接收到数据,把末端清零 */
recv_data[bytes_received] = '\0';
if (strncmp(recv_data, "q", 1) == 0 || strncmp(recv_data, "Q", 1) == 0)
{
/* 如果是首字母是q或Q,关闭这个连接 */
closesocket(sock);
rt_kprintf("\n got a 'q' or 'Q',close the socket.\r\n");
/* 释放接收缓冲 */
rt_free(recv_data);
break;
}
else
{
/* 在控制终端显示收到的数据 */
rt_kprintf("\nReceived data = %s ", recv_data);
}
/* 发送数据到sock连接 */
ret = send(sock, send_data, strlen(send_data), 0);
if (ret < 0)
{
/* 接收失败,关闭这个连接 */
closesocket(sock);
rt_kprintf("\nsend error,close the socket.\r\n");
rt_free(recv_data);
break;
}
else if (ret == 0)
{
/* 打印send函数返回值为0的警告信息 */
rt_kprintf("\n Send warning,send function return 0.\r\n");
}
}
return;
}
MSH_CMD_EXPORT(tcpclient, a tcp client sample);