【嵌入式】一种基于串口命令的模块测试API模板

news2024/9/17 8:56:48

本文主要记录一种用于嵌入式开发中【模块测试】通用模板,使用 getopt_long()函数作为串口命令行解析的工具,从而进行测试代码逻辑的编写。

本文以ADCuart 测试为例,介绍函数的使用以及测试代码的编写

【测试环境说明 】

本文是在 rt-thread 环境下,确保已经移植好了debug串口接口。。移植过程在此不做赘述

本文主要记录 杰理蓝牙audio接口的使用,包括ADCDAC原理的介绍和API接口的使用。

【杰理蓝牙开发】AC695x 音频部分

  • 0. 个人简介 && 授权须知
  • 1. 测试代码架构
  • 2. 接口 getopt_long() 的分析
    • 2.1 参数说明
    • 2.2 返回值说明
  • 3. 接口 getopt_long() 的使用
    • 3.1 定义 【短选项】字符串 optstring
    • 3.2 定义【长选项】字符串 longopts
    • 3.3 定义提示信息
  • 4. 测试串口的实例
  • 5. 一个通用的测试模板

0. 个人简介 && 授权须知

image-20230911133730620

📋 个人简介

  • 💖 作者简介:大家好,我是喜欢记录零碎知识点的菜鸟打工人。😎
  • 📝 个人主页:欢迎访问我的博客主页🔥
  • 🎉 支持我:点赞👍+收藏⭐️+留言📝
  • 📣 系列专栏:嵌入式开发专栏 🍁 🍁
  • 💬格言:写文档啊不是写文章,重要的还是直白!🔥

转载文章,禁止声明原创;不允许直接二次转载,转载请根据原文链接联系作者

若无需改版,在文首清楚标注作者及来源/原文链接,并删除【原创声明】,即可直接转载。
但对于未注明转载来源/原文链接的文章,我将保留追述的权利。

作者:积跬步、至千里

image-20230911133724204

1. 测试代码架构

测试时,输入的串口指令为:

test_adc -c 2 , 格式只能为这种,其他格式会报错

说明:参数分别为

  • test_adc:测试命令
  • -c :表示channel通道
  • 2:具体的channel
static void cmd_test_adc(int argc, char **argv)
{
    int c;
    u32 ch = 0;

    if (argc < 2) {                   // 若参数少于2个,则提示错误
        cmd_adcim_usage(argv[0]);  	  // 提示错误
        return;
    }

    optind = 0;
    while ((c = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
        switch (c) {
        case 'c':
            ch = atoi(optarg); // 解析通道   
            adc_dm_test(ch);
            continue;
        case 'v':
            continue;
        case 'h':
        default:
            cmd_adcim_usage(argv[0]); // 提示错误
            return;
        }
    }
    return;
}
MSH_CMD_EXPORT_ALIAS(cmd_test_adc, test_adc, adcim dm device sample);   // 设置测试命令行

2. 接口 getopt_long() 的分析

getopt_long() 函数是用于在 CC++ 程序中解析命令行选项的一个强大工具。

#include <getopt.h>

int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);

2.1 参数说明

  • argc:命令行参数的数量。

  • argv:命令行参数的数组。

  • optstring:指定短选项的字符串。每个字符代表一个短选项,如果字符后面跟一个 : ,表示该选项需要一个参数。

    • 例如,"ab:c" 表示 a 选项不需要参数,b 选项需要一个参数,c 选项不需要参数。
  • longopts:这是一个指向 struct option 结构体数组的指针,用于定义长选项。
    在这里插入图片描述

2.2 返回值说明

  • 如果找到一个有效的短选项或长选项,返回选项字符。
  • 如果选项需要一个参数,optarg 指针将被设置为该参数的值。
  • 如果遇到选项解析错误,返回 '?'
  • 如果所有选项都已处理完毕,返回 -1

3. 接口 getopt_long() 的使用

3.1 定义 【短选项】字符串 optstring

/*
c: 表示 -c 命令后边还需要一个参数
h: -h 后边不需要参数
v: -v 后边不需要参数
*/
static const char sopts[] = "c:hv";

3.2 定义【长选项】字符串 longopts

static const struct option lopts[] = {
    {"channel", required_argument, NULL, 'c'},   // required_argument 表示 -c 命令后边还需要一个参数
    {"usage",   no_argument, NULL, 'h'},		// no_argument 表示命令后边不需要参数了
    {"verbose", no_argument, NULL, 'v'},
    {0, 0, 0, 0}							// 必须以{0,0,0,0}结尾
};

3.3 定义提示信息

对命令参数作基本说明

static void cmd_adcim_usage(char *program)
{
    printf("Compile time: %s %s\n", __DATE__, __TIME__);
    printf("Usage: %s [options]\n", program);
    printf("\t -c, --channel\t\tSelect one channel in [0, 15]\n");     // 表示 channel范围【0-15】
    printf("\t -h, --usage \n");
    printf("\n");
    printf("Example: %s -c 0\n", program);        // 示例  test_adc -c 0  测试通道0
}

4. 测试串口的实例

static const char sopts[] = "u:n:t:h";

// optional_argument 表示可能需要采纳数,不是必须的
static const struct option lopts[] = {
    {"uart",       optional_argument,  NULL, 'u'},   // 设置哪一个串口
    {"number",     optional_argument,  NULL, 'n'},	 // 设置串口接收数量
    {"timeout",    optional_argument,  NULL, 't'},	 // 设置接收超时时间
    {"help",       no_argument,        NULL, 'h'},   // 
    {0, 0, 0, 0}
};

// 提示信息
static void test_uart_usage(char *program)
{
    printf("Compile time: %s %s\n", __DATE__, __TIME__);
    printf("Usage: %s [options]\n", program);
    printf("\t -u, --uart\t\tSelect a serial port. Default as uart4\n");
    printf("\t -n, --number\t\treceive max number. Default as 128\n");
    printf("\t -t, --timeout\t\tSerial port receive timeout, Default as forever, unit ms\n");
    printf("\t -h, --help \n");
    printf("\n");
    printf("Example: Serial port loopback test\n");
    printf("         %s -u uart4 -n 128 -t 1000 \n", program);
}


int test_uart(int argc, char *argv[])
{
    /*
        argc: 参数的数量
        argv:命令行参数的字符串数组
        sopts:指定短选项的格式字符串
        lopts:用于定义长选项
        *idx:如果不为空,用于存储匹配到的长选项在 lopts 数组中的索引

    */
    while ((c = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) 
    {
        switch (c) {
        case 'u':
            rt_strncpy(uart_name, optarg, RT_NAME_MAX);
            printf("-u\r\n");
            break;
        case 'n':
            g_recv_max = atoi(optarg);
            g_recv_max = g_recv_max > 128 ? 128 : g_recv_max;
            g_recv_max = g_recv_max < 0 ? 128 : g_recv_max;
            printf("-n\r\n");
            break;
        case 't':
            g_timeout = atoi(optarg);
            g_timeout = g_timeout < 0 ? TIMEOUT_NONE : g_recv_max;
            printf("-t\r\n");
            break;
        case 'h':
            printf("-h\r\n");
            break;
        default:
            printf("-default\r\n");
            test_uart_usage(argv[0]);
            return 0;
        }
    }

}
MSH_CMD_EXPORT(test_uart, MCU Chip Uart Test);

5. 一个通用的测试模板

#include <stdio.h>
#include <getopt.h>

int main(int argc, char *argv[]) {
    int c;
    int verbose_flag = 0;
    char *output_file = NULL;

    struct option long_options[] = {
        {"verbose", no_argument, &verbose_flag, 1},
        {"output", required_argument, 0, 'o'},
        {0, 0, 0, 0}
    };

    while ((c = getopt_long(argc, argv, "vo:", long_options, NULL))!= -1) {
        switch (c) {
            case 'v':
                verbose_flag = 1;
                break;
            case 'o':
                output_file = optarg;
                break;
            case '?':
                printf("Invalid option\n");
                return 1;
            default:
                abort();
        }
    }

    if (verbose_flag) {
        printf("Verbose mode enabled\n");
    }

    if (output_file) {
        printf("Output file: %s\n", output_file);
    }

    for (; optind < argc; optind++) {
        printf("Non-option argument: %s\n", argv[optind]);
    }

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1962813.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一篇长文搭建AI大模型应用平台架构

在研究了6家知名公司如何部署生成式AI应用程序后&#xff0c;注意到它们的平台有很多相似之处。概述了生成式AI大模型应用平台的常见组件、它们的作用以及它们的实现方式。尽力保持架构的通用性&#xff0c;但某些应用程序可能会有所不同。 Generative AI大模型应用平台整体架…

数据集相关类代码回顾理解 | StratifiedShuffleSplit\transforms.ToTensor\Counter

【PyTorch】图像多分类项目 目录 StratifiedShuffleSplit transforms.ToTensor Counter StratifiedShuffleSplit sss StratifiedShuffleSplit(n_splits1, test_size0.2, random_state0) 创建StratifiedShuffleSplit对象&#xff0c;用于将数据集划分为训练集和测试集。 …

农业物联网气象站的工作原理

TH-NQ10农业物联网气象站是一款集成了物联网与气象技术的创新设备&#xff0c;它在现代农业中扮演着重要角色&#xff0c;为农业生产提供了精准、实时的气象数据支持。以下是对农业物联网气象站的详细介绍&#xff1a; 定义与特点 农业物联网气象站通过物联网技术将气象观测设…

详解校门外的树(树状数组)

前言 在看之前建议先看一下 【学习笔记】详解树状数组-CSDN博客 题目 思路 建立两个树状数组,维护左括号与右括号。 假设有一个长度为10的数轴&#xff0c;我们要将区间[ 2 , 5 ]中种树&#xff0c;这时&#xff0c;我们将 2 处放一个左括号 ” ( ” ,5处放一个 ” )” &…

负载均衡的作用、负载均衡常用处理方式、四层和七层负载均衡的区别、及配置方法

一、负载均衡的作用 解决服务器的高并发压力&#xff0c;提高应用程序的处理性能&#xff1b; 提供故障转移&#xff0c;实现高可用&#xff1b; 通过添加或减少服务器数量&#xff0c;增强网站的可扩展性&#xff1b; 在负载均衡器上进行过滤&#xff0c;可以提高系统的安…

FreeModbus学习——定时器

FreeModbus版本&#xff1a;1.6 协议栈初始化时会初始化定时器&#xff1a; eMBInit → eMBRTUInit → xMBPortTimersInit( ( USHORT ) usTimerT35_50us ) 协议栈使能时会使能定时器&#xff1a; eMBEnable → pvMBFrameStartCur → eMBRTUStart → vMBPortTimersEnable 定时…

【Vulnhub系列】Vulnhub_Dr4g0n_b4ll 靶场渗透(原创)

【Vulnhub系列靶场】Vulnhub_Dr4g0n_b4ll靶场渗透 原文转载已经过授权 原文链接&#xff1a;Lusen的小窝 - 学无止尽&#xff0c;不进则退 (lusensec.github.io) 一、环境搭建 选择打开.ovf 文件 配置名称和路径 打开后调整网络连接模式为【NAT】即可 二、信息收集 1、主机…

MySQL安装教程(保姆级)

1. 首先要了解自己的计算机 打开设置——系统——系统信息 然后就可以知道自己计算机的类型了。 2. 下载MySQL 2.1. 来到MySQL官网 点击进入 我们下拉页面&#xff0c;可以找到DOWNLOADS 页面默认给咱们选择最新的版本&#xff0c;咱们不用&#xff0c;咱们尽量选一个稳定的版…

解决vscode+UE5中vscode无法识别头文件,无法函数无法跳转,也无法自动补全的问题。

一、概述 接上一条博客&#xff0c;虽然解决了报错的问题&#xff0c;但是实际上的问题却没有解决&#xff0c;无论我怎么点击&#xff0c;其都无法完成跳转&#xff0c;也无法完成自动补全的问题。 在网络上搜索了很多资料后&#xff0c;发现是在使用vscode时候UE5在vscode中的…

对零基础想转行网络安全同学的一点建议

最近有同学在后台留言&#xff0c;0基础怎么学网络安全&#xff1f;0基础可以转行做网络安全吗&#xff1f;以前也碰到过类似的问题&#xff0c;想了想&#xff0c;今天简单写一下。 我的回答是先了解&#xff0c;再入行。 具体怎么做呢&#xff1f; 首先&#xff0c;你要确…

深入源码:解析SpotBugs (5)BugReportor

常见的 Bug 定位后&#xff0c;通过 bugReport的reportBug&#xff08;BugInstance&#xff09; 方法&#xff0c;将bug 发布出来。 一般的 Detector 经检测后会调用 bugReportor.reportBug 方法或者 BugAccumulator.accumulateBug 。 在GUI中&#xff0c;分析结束后会在下框…

2024年投放必应bing国内广告,顶级技巧与策略!

随着企业对于高效、精准的广告投放需求日益增强&#xff0c;微软必应Bing广告平台以其独特的优势&#xff0c;正成为众多品牌投放广告的理想选择。云衔科技凭借其专业的必应Bing国内广告开户及代运营服务&#xff0c;助力企业精准触达目标受众&#xff0c;实现品牌影响力和市场…

ESP-ADF适配到自定义开发板中

ESP-ADF适配到自定义开发板中 前言:项目开发完了,来记录一下开发过程。 安装: 这里采用vscode+ESP-IDF+ESP-ADF的开发方式。 安装esp-idf的方法很简单,网上都是,这里不说了。想用esp-adf那么你idf的环境肯定是已经搭建好了。 安装adf也很简单,一步完成。 按下F1,选…

软考网工:2024年下半年各地区报名时间(附赠真题)

根据软考办《关于2024年度计算机技术与软件专业技术资格(水平)考试工作安排及有关事项的通知》(计考办〔2024〕1号)可以得知&#xff0c;2024年下半年网络工程师将于8月19日至9月15日开放考务管理服务平台&#xff0c;各地组织报名。 各地2024年下半年网络工程师报名时间不同&…

科普文:万字梳理高性能 Kafka快的8个原因

概叙 科普文&#xff1a;万字详解Kafka基本原理和应用-CSDN博客 科普文&#xff1a;万字梳理31个Kafka问题-CSDN博客 我们都知道 Kafka 是基于磁盘进行存储的&#xff0c;但 Kafka 官方又称其具有高性能、高吞吐、低延时的特点&#xff0c;其吞吐量动辄几十上百万。 在座的…

绝密!OceanBase OBCP备考模拟题讲解(1)

博主首页 &#xff1a; 「源de爸讲数据库」每天优先更新OceanBase OBCP题库及全网独家超详细题目解析&#xff01; 现如今&#xff0c;一大批国产数据库随着国产化浪潮&#xff0c;已经逐步被越来越多的人认可。OceanBase便是其中一个优秀代表。 做这个日更专题&#xff0c;…

麒麟V10系统统一认证子系统国际化

在适配麒麟V10系统统一认证子系统国际化过程中&#xff0c; 遇到了很多的问题&#xff0c;关键是麒麟官方的文档对这部分也是粗略带过&#xff0c;遇到的问题有: &#xff08;1&#xff09;xgettext无法提取C源文件中目标待翻译的字符串。 &#xff08;2&#xff09;使用msgf…

【Python正则-驯化】一文学会通过Python中的正则表达式提取文本中的网址

【Python正则-驯化】一文学会通过Python中的正则表达式提取文本中的网址 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 免费获取相关内容…

Redis 与 Scrapy:无缝集成的分布式爬虫技术

1. 分布式爬虫的概念 分布式爬虫系统通过将任务分配给多个爬虫节点&#xff0c;利用集群的计算能力来提高数据抓取的效率。这种方式不仅可以提高爬取速度&#xff0c;还可以在单个节点发生故障时&#xff0c;通过其他节点继续完成任务&#xff0c;从而提高系统的稳定性和可靠性…

Gooxi荣获2024年深圳市计算机行业协会最具成长奖

近日&#xff0c;由深圳市计算机行业协会举办的2024年度深圳市计算机行业协会年中工作会议圆满落幕。本次会议邀请了多位行业专家以及深圳地区的理事会成员、企业家参会。会议的重点是总结上半年的经验&#xff0c;分析行业热点与痛点&#xff0c;探讨以新质生产力促进高质量发…