369|0

502

帖子

4

TA的资源

纯净的硅(高级)

楼主
 

【DigiKey创意大赛】基于STM32H7B3I-DK的智能家居助手+Shell命令行交互遥控测试 [复制链接]

 

七.Shell命令行交互

前面我们已经实现了任意红外信号的发送,这样就可以发送任意的红外遥控心好累。

这时已经具备了一个万用红外遥控的雏形,现在开始我们来增加交互功能,实现简单的shell命令行操作。这样我们就可以通过PC或者手机蓝牙串口透传和板子交互,控制板子发送红外遥控信号。

7.1 shell命令行实现

参考一个超级精简高可移植的shell命令行C实现 《https://mp.weixin.qq.com/s/XLmbJn0SKoDT1aLdxHDrbg》,这里直接贴出代码

Shell.c

#include <stdint.h>

#include "shell.h"

 

shell_read_pf s_input_pf = 0;      /* 输入接口指针     */

shell_write_pf s_output_pf = 0;    /* 输出接口指针     */

shell_cmd_cfg* s_cmd_cfg_pst = 0;  /* 命令列表指针     */

uint8_t s_enableecho_u8 = 0;       /* 是否使能echo标志 */

static uint8_t  s_cmd_buf_au8[SHELL_CMD_LEN]="\r"; /* 命令缓冲区 */

static uint32_t s_cmd_buf_index_u32 = 0;               /* 当前命令缓冲区中字符数 */

 

/**

 * 输出字符接口

*/

static void shell_putchar(uint8_t val)

{

    uint8_t tmp;

    if(s_output_pf != 0)

    {

        tmp = val;

        s_output_pf(&tmp, 1);

    }

}

 

/**

 * 输出字符串接口

*/

static void shell_putstring(char* str)

{

    uint32_t len = 0;

    uint8_t*p = (uint8_t*)str;

    while(*str++)

    {

        len++;

    }

    s_output_pf(p, len);

}

 

/**

 * 读字符接口

*/

static int shell_getchar(uint8_t *data)

{

    if(s_input_pf == 0)

    {

        return -1;

    }

if(0 == s_input_pf(data, 1))

    {

return -1;

}

else

{

        return 0;

}

}

 

/**

 * 判断命令字符串的长度

 * 命令字符串不能有空格

*/

static uint32_t shell_cmd_len(uint8_t *cmd)

{

    uint8_t *p = cmd;

    uint32_t len = 0;

    while((*p != ' ') && (*p != 0))

    {

        p++;

        len++;

    }

    return len;

}

 

/**

 * 判断两个字符串是否相等,相等返回0

*/

static int shell_cmd_check(uint8_t *cmd, uint8_t *str)

{

    uint32_t len1 = shell_cmd_len(cmd);

    uint32_t len2 = shell_cmd_len(str);

    if(len1 != len2)

    {

        return -1;

    }

    for(uint32_t i=0; i<len1; i++)

    {

        if(*cmd++ != *str++)

        {

            return -1;

        }

    }

    return 0;

}

 

/**

 * 读取一行命令

*/

static uint32_t shell_read_line(void)

{

    uint8_t ch;

    uint32_t count;

    /* 初始打印sh> */

    if(s_cmd_buf_au8[0]=='\r')

    {

        shell_putstring("sh>\r\n");

        s_cmd_buf_au8[0] = 0;

    }

 

    /* 非阻塞读取一个字符 */

    if(shell_getchar(&ch) !=0 )

    {

        return 0;

    }

 

    /* 遇到除了退格之外的不可打印字符,则认为收到一行命令

     * 退格需要单独处理,需要删除一个字符

    */

    if((ch == '\r' || ch == '\n' || ch < ' ' || ch > '~') && (ch != '\b'))

    {

        if(s_cmd_buf_index_u32==0)

        {

            /* 缓冲区没有数据就收到了非打印字符串,则打印提示sh> */

            shell_putstring("sh>\r\n");

        }

        else

        {

            /* 收到了非打印字符,且缓冲区有数据则认为收到了一行

             * 返回缓冲区数据长度,并清零计数,打印回车换行

             * 并且添加结束符0

            */

            count = s_cmd_buf_index_u32;

            s_cmd_buf_au8[s_cmd_buf_index_u32]=0;

            s_cmd_buf_index_u32 =0;

            shell_putstring("\r\n");

            return count;

        }

    }

    else

    {

        if(ch == '\b')

        {

            /* 退格处理,注意只有有数据才会删除一个字符,添加结束符 */

            if(s_cmd_buf_index_u32 != 0)

            {

                s_cmd_buf_index_u32--;

                shell_putchar('\b');

                shell_putchar(' ');

                shell_putchar('\b');

                s_cmd_buf_au8[s_cmd_buf_index_u32]= '\0';

            }

        }

        else

        {

            /* 可打印字符,添加到缓冲区

             * 如果数据量已经到了缓冲区大小-1,则也认为是一行命令

             * -1是保证最后有结束符0空间

            */

            if(s_enableecho_u8 != 0)

            {

                shell_putchar(ch);

            }

            s_cmd_buf_au8[s_cmd_buf_index_u32++] = ch;

            if(s_cmd_buf_index_u32>=(sizeof(s_cmd_buf_au8)-1))

            {

                count = s_cmd_buf_index_u32;

                s_cmd_buf_au8[s_cmd_buf_index_u32]=0;

                s_cmd_buf_index_u32 =0;

                shell_putstring("\r\n");

                return count;

            }

        }

    }

    return 0;

}

 

/**

 * 搜寻命令列表处理命令

*/

static int shell_exec_cmdlist(uint8_t* cmd)

{

    int i;

    if(s_cmd_cfg_pst == 0)

    {

        return -1;

    }

    for (i=0; s_cmd_cfg_pst.name != 0; i++)

    {

        if (shell_cmd_check(cmd, s_cmd_cfg_pst.name) == 0)

        {

            s_cmd_cfg_pst.func(cmd);

            return 0;

        }            

    }

    if(s_cmd_cfg_pst.name == 0)

    {

        shell_putstring("unkown command\r\n");

        return -1;

    }

    return 0;

}

 

/**

 * 对外接口,周期执行

*/

void shell_exec(void)

{

    if(shell_read_line() > 0)

    {

        shell_exec_cmdlist(s_cmd_buf_au8);

    }

}

 

/**

 * 对外接口,初始化配置接口

*/

void shell_set_itf(shell_read_pf input, shell_write_pf output, shell_cmd_cfg* cmd_list, uint8_t enableecho)

{

    s_input_pf = input;

    s_output_pf = output;

    s_cmd_cfg_pst = cmd_list;

    s_enableecho_u8 = enableecho;

}

 

 

Shell.h

#ifndef SHELL_H

#define SHELL_H

 

#ifdef __cplusplus

extern "C" {

#endif

 

#include <stdint.h>

 

#define SHELL_CMD_LEN 64                                          /**< 命令缓冲区大小 */

 

typedef void (*shell_command_pf)(uint8_t *);                      /**< 命令回调函数   */

typedef uint32_t (*shell_read_pf)(uint8_t *buff, uint32_t len);   /**< 底层收接口     */

typedef void (*shell_write_pf)(uint8_t *buff, uint32_t len);      /**< 底层发接口     */

 

/**

 * \struct shell_cmd_cfg

 * 命令信息

*/

typedef struct

{

    uint8_t * name;          /**< 命令字符串   */

    shell_command_pf func;   /**< 命令回调函数 */

    uint8_t * helpstr;       /**< 命令帮助信息 */   

}shell_cmd_cfg;

 

/**

 * \fn shell_exec

 * 周期调用该函数,读取底层输入,并判断是否有命令进行处理

 * 非阻塞

*/

void shell_exec(void);

 

/**

 * \fn shell_set_itf

 * 设置底层输入输出接口,以及命令列表

 * 调用shell_exec_shellcmd之前,需要先调用该接口初始化

 * \param[in] input \ref shell_read_pf 输入接口

 * \param[in] output \ref shell_write_pf 输出接口

 * \param[in] cmd_list \ref shell_cmd_cfg 命令列表

 * \param[in] enableecho 0:不使能回显, 其他值:使能回显

*/

void shell_set_itf(shell_read_pf input, shell_write_pf output, shell_cmd_cfg* cmd_list, uint8_t enableecho);

 

#ifdef __cplusplus

}

#endif

 

 

Shell_func.h

#ifndef SHELL_FUNC_H

#define SHELL_FUNC_H

 

#include <stdint.h>

 

#ifdef __cplusplus

 extern "C" {

#endif

 

extern const shell_cmd_cfg g_shell_cmd_list_ast[ ];

 

#ifdef __cplusplus

}

#endif

 

#endif

 

Shell_func.c

#include <stdio.h>

#include <stdint.h>

#include <string.h>

#include <stdlib.h>

 

#include "shell.h"

#include "shell_func.h"

#include "uart_api.h"

 

static void helpfunc(uint8_t* param);

 

 

/**

 * 最后一行必须为0,用于结束判断

*/

const shell_cmd_cfg g_shell_cmd_list_ast[ ] =

{

  { (uint8_t*)"help",         helpfunc,         (uint8_t*)"help"},

  { (uint8_t*)0,           0 ,               0},

};

 

void helpfunc(uint8_t* param)

{

  (void)param;

    unsigned int i;

    printf("\r\n");

    printf("**************\r\n");

    printf("*   SHELL    *\r\n");

    printf("*   V1.0     *\r\n");

    printf("**************\r\n");

    printf("\r\n");

    for (i=0; g_shell_cmd_list_ast.name != 0; i++)

    {

        printf("%02d.",i);

        printf("%-16s",g_shell_cmd_list_ast.name);

        printf("%s\r\n",g_shell_cmd_list_ast.helpstr);

    }

}

 

7.2 万用遥控-遥控电视开关测试

我们使用前面设计的红外模块接收电视遥控的开关机信号,采集到信号如下

 

 

对应如下数据

 

iostate_t s_iostate[2][40]=

{

{

{0,3000}, /* 0 - 3mS 1000 25uS*/

{1,3000}, /* 1 - 3ms */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,2500}, /* 1 -2,5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,2500}, /* 1 -2.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,2500}, /* 1 -2.5mS */

{0,500}, /* 0- 500uS */

{1,2500}, /* 1 -2.5mS */

{0,500}, /* 0- 500uS */

{1,4000}, /* 1 -4mS */

{0,500}, /* 0- 500uS */

{1,60000}, /* 1 -1000mS */

{0Xff,0}

},

{

{0,3000}, /* 0 - 3mS 1000 25uS*/

{1,3000}, /* 1 - 3ms */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,2500}, /* 1 -2,5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,2500}, /* 1 -2.5mS */

{0,500}, /* 0- 500uS */

{1,1500}, /* 1 -1.5mS */

{0,500}, /* 0- 500uS */

{1,2500}, /* 1 -2.5mS */

{0,500}, /* 0- 500uS */

{1,2500}, /* 1 -2.5mS */

{0,500}, /* 0- 500uS */

{1,4000}, /* 1 -4mS */

{0,500}, /* 0- 500uS */

{1,22500}, /* 1 -22.5mS */

{0Xff,0}

}

};

 

 

 

添加命令行

 

 

shell_func.c中

#include "ir.h"

 

g_shell_cmd_list_ast中添加两行

  { (uint8_t*)"pwron",        pwronfunc,         (uint8_t*)"pwron"},

  { (uint8_t*)"pwroff",       pwrofffunc,         (uint8_t*)"pwroff"},

 

开始申明函数

static void pwronfunc(uint8_t* param);

static void pwrofffunc(uint8_t* param);

 

 

 

 

实现

void pwronfunc(uint8_t* param)

{

for(int i=0;i<3;i++)

  {

ir_send(0);

}

}

 

void pwrofffunc(uint8_t* param)

{

for(int i=0;i<3;i++)

  {

ir_send(1);

}

}

 

可以看到添加了如下命令

 

输入pwron on和pwr off就可以发送对应的信号,遥控电视开关机。

 

详见视频

点赞 关注
 
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表