RT-Thread AT组件学习

文章目录

目录

文章目录

前言

一、如何开启AT组件

二、使用步骤

1.修改控制IO引脚

2.修改状态引脚的检测

3.AT 脚手架测试CLI

 


 

前言

操作系统:win10

开发板:正点原子stm32f103旗舰版 + SIM7600CE模块

目的:在RTT中使用AT组件与SIM7600CE等AT命令设备进行快速测试验证


 

一、如何开启AT组件

 

在env工具中输入menuconfig,然后在online packages中选择IOT------AT Device

保存,退出;

然后输入pkgs --update更新包

最后,输入scons --target=mdk5 来编译整个工程。 

二、使用步骤

打开工程,需要根据实际情况修改以下代码。

1.修改控制IO引脚

打开rtconfig.h文件

需要对照自己板子的硬件进行修改

由于笔者的AT_DEVICE_STATUS_PIN状态引脚没有引出,所以还需要修改源码中的一处地方。

2.修改状态引脚的检测

打开at_socket_sim76xx.c文件,注销掉模块的开关机函数对该IO的检测

然后编译,直接烧录代码到单片机中。串口打印信息如下所示:

AT组件显示初始化成功(文件系统因为没有挂载,所以显示失败),输入help查看相关命令

然后测试下网络的连通性,使用at_ping www.baidu.com,注意这里不能使用ping命令。

如果有自己的服务器,可以使用at_connect命令来连接服务器。

以上就是AT组件的简单使用,这里要提一下AT组件的脚手架CLI功能,因为这个功能对于测试来说比较实用。

3.AT 脚手架测试CLI

 

开启该功能后,我们可以直接通过调试串口发送命令给无线模块进行测试,简单的工作原理示意图如下:

开启AT脚手架功能,直接发命令at client 即可。

这样就可以根据无线模块的AT手册进行测试验证了。

上述测试了ATI和AT+CSQ指令,直接在调试串口输入指令,单片机会将调试串口的指令转发到串口3(即无线模块连接的串口)

更多的指令,可以直接参考无线模块sim7600ceAT指令手册进行测试。

AT组件脚手架实现的源码如下:

调试串口相关:

信号量、环形队列、串口接收回调函数定义

static struct rt_semaphore console_rx_notice;
static struct rt_ringbuffer *console_rx_fifo = RT_NULL;
static rt_err_t (*odev_rx_ind)(rt_device_t dev, rt_size_t size) = RT_NULL;

实现如下:主要就是备份原来的环境,设置新的环境(开启)-----恢复原来的环境(关闭),这里的环境指的是串口接收的回调函数

/*调试串口读取数据*/
static char console_getchar(void)
{
    char ch;

    rt_sem_take(&console_rx_notice, RT_WAITING_FOREVER);
    rt_ringbuffer_getchar(console_rx_fifo, (rt_uint8_t *)&ch);

    return ch;
}

/*调试串口的接收中断回调函数*/
static rt_err_t console_getchar_rx_ind(rt_device_t dev, rt_size_t size)
{
    uint8_t ch;
    rt_size_t i;

    for (i = 0; i < size; i++)
    {
        /* read a char */
        if (rt_device_read(dev, 0, &ch, 1))
        {
            rt_ringbuffer_put_force(console_rx_fifo, &ch, 1);
            rt_sem_release(&console_rx_notice);
        }
    }

    return RT_EOK;
}

/*cli init*/
void at_cli_init(void)
{
    rt_base_t int_lvl;
    rt_device_t console;

    rt_sem_init(&console_rx_notice, "cli_c", 0, RT_IPC_FLAG_FIFO);

    /* create RX FIFO */
    console_rx_fifo = rt_ringbuffer_create(AT_CLI_FIFO_SIZE);
    /* created must success */
    RT_ASSERT(console_rx_fifo);

    int_lvl = rt_hw_interrupt_disable();
    console = rt_console_get_device();
    if (console)
    {
        /* backup RX indicate */
        odev_rx_ind = console->rx_indicate;/*备份原来的接收回调函数*/
        rt_device_set_rx_indicate(console, console_getchar_rx_ind);/*设置新的接收回调函数*/
    }

    rt_hw_interrupt_enable(int_lvl);
}

/* cli deinit */
void at_cli_deinit(void)
{
    rt_base_t int_lvl;
    rt_device_t console;

    int_lvl = rt_hw_interrupt_disable();
    console = rt_console_get_device();
    if (console && odev_rx_ind)
    {
        /* restore RX indicate */
        rt_device_set_rx_indicate(console, odev_rx_ind);/*恢复原始的接收回调函数*/
    }
    rt_hw_interrupt_enable(int_lvl);

    rt_sem_detach(&console_rx_notice);
    rt_ringbuffer_destroy(console_rx_fifo);
}

sim7600ce通信的串口类似,源码如下:

static char client_getchar(void)
{
    char ch;

    rt_sem_take(&client_rx_notice, RT_WAITING_FOREVER);
    rt_ringbuffer_getchar(client_rx_fifo, (rt_uint8_t *)&ch);

    return ch;
}

static void at_client_entry(void *param)
{
    char ch;

    while(1)
    {
        ch = client_getchar();
        rt_kprintf("%c", ch);
    }
}

static rt_err_t client_getchar_rx_ind(rt_device_t dev, rt_size_t size)
{
    uint8_t ch;
    rt_size_t i;

    for (i = 0; i < size; i++)
    {
        /* read a char */
        if (rt_device_read(dev, 0, &ch, 1))
        {
            rt_ringbuffer_put_force(client_rx_fifo, &ch, 1);
            rt_sem_release(&client_rx_notice);
        }
    }

    return RT_EOK;
}
static void client_cli_parser(at_client_t  client)
{
#define ESC_KEY                 0x1B
#define BACKSPACE_KEY           0x08
#define DELECT_KEY              0x7F

    char ch;
    char cur_line[FINSH_CMD_SIZE] = { 0 };
    rt_size_t cur_line_len = 0;
    static rt_err_t (*client_odev_rx_ind)(rt_device_t dev, rt_size_t size) = RT_NULL;
    rt_base_t int_lvl;
    rt_thread_t at_client;
    at_status_t client_odev_status;

    if (client)
    {
        /* backup client status */
        {
            client_odev_status = client->status;
            client->status = AT_STATUS_CLI;
        }

        /* backup client device RX indicate */
        {
            int_lvl = rt_hw_interrupt_disable();
            client_odev_rx_ind = client->device->rx_indicate;
            rt_device_set_rx_indicate(client->device, client_getchar_rx_ind);
            rt_hw_interrupt_enable(int_lvl);
        }

        rt_sem_init(&client_rx_notice, "cli_r", 0, RT_IPC_FLAG_FIFO);
        client_rx_fifo = rt_ringbuffer_create(AT_CLI_FIFO_SIZE);

        at_client = rt_thread_create("at_cli", at_client_entry, RT_NULL, 512, 8, 8);
        if (client_rx_fifo && at_client)
        {
            rt_kprintf("======== Welcome to using RT-Thread AT command client cli ========\n");
            rt_kprintf("Cli will forward your command to server port(%s). Press 'ESC' to exit.\n", client->device->parent.name);
            rt_thread_startup(at_client);
            /* process user input */
            while (ESC_KEY != (ch = console_getchar()))
            {
                if (ch == BACKSPACE_KEY || ch == DELECT_KEY)
                {
                    if (cur_line_len)
                    {
                        cur_line[--cur_line_len] = 0;
                        rt_kprintf("\b \b");
                    }
                    continue;
                }
                else if (ch == '\r' || ch == '\n')
                {
                    /* execute a AT request */
                    if (cur_line_len)
                    {
                        rt_kprintf("\n");
                        /*转发执行的指令*/
                        at_obj_exec_cmd(client, RT_NULL, "%.*s", cur_line_len, cur_line);
                    }
                    cur_line_len = 0;
                }
                else
                {
                    rt_kprintf("%c", ch);
                    /*获取输入的AT命令*/
                    cur_line[cur_line_len++] = ch;
                }
            }

            /* restore client status */
            client->status = client_odev_status;

            /* restore client device RX indicate */
            {
                int_lvl = rt_hw_interrupt_disable();
                rt_device_set_rx_indicate(client->device, client_odev_rx_ind);
                rt_hw_interrupt_enable(int_lvl);
            }

            rt_thread_delete(at_client);
            rt_sem_detach(&client_rx_notice);
            rt_ringbuffer_destroy(client_rx_fifo);
        }
        else
        {
            rt_kprintf("No mem for AT cli client\n");
        }
    }
    else
    {
        rt_kprintf("AT client not initialized\n");
    }
}
#endif /* AT_USING_CLIENT */

static void at(int argc, char **argv)
{

    if (argc != 2 && argc != 3)
    {
        rt_kprintf("Please input '<server|client [dev_name]>' \n");
        return;
    }

    at_cli_init();

    if (!strcmp(argv[1], "server"))
    {
#ifdef AT_USING_SERVER
        server_cli_parser();
#else
        rt_kprintf("Not support AT server, please check your configure!\n");
#endif /* AT_USING_SERVER */
    }
    else if (!strcmp(argv[1], "client"))
    {
#ifdef AT_USING_CLIENT
        at_client_t client = RT_NULL;

        if (argc == 2)
        {
            client_cli_parser(at_client_get_first());
        }
        else if (argc == 3)
        {
            client = at_client_get(argv[2]);
            if (client == RT_NULL)
            {
                rt_kprintf("input AT client device name(%s) error.\n", argv[2]);
            }
            else
            {
                client_cli_parser(client);
            }
        }
#else
        rt_kprintf("Not support AT client, please check your configure!\n");
#endif /* AT_USING_CLIENT */
    }
    else
    {
        rt_kprintf("Please input '<server|client [dev_name]>' \n");
    }

    at_cli_deinit();
}
MSH_CMD_EXPORT(at, RT-Thread AT component cli: at <server|client [dev_name]>);

RTT AT组件方便测试验证无线模块,节省了很多时间。

脚手架源文件请参考at_cli.c文件。更多模块支持请参考下载的包中exmaple文件夹。

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值