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

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

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

【测试环境说明 】

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

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

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

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

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

📋 个人简介

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

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

若无需改版,在文首清楚标注作者及来源/原文链接,并删除【原创声明】,即可直接转载。

但对于未注明转载来源/原文链接的文章,我将保留追述的权利。

作者:积跬步、至千里

1. 测试代码架构

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

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

说明:参数分别为

  • test_adc:测试命令
  • -c :表示channel通道
  • 2:具体的channel
c 复制代码
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++ 程序中解析命令行选项的一个强大工具。

c 复制代码
#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: 表示 -c 命令后边还需要一个参数
h: -h 后边不需要参数
v: -v 后边不需要参数
*/
static const char sopts[] = "c:hv";

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

c 复制代码
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 定义提示信息

对命令参数作基本说明

c 复制代码
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. 测试串口的实例

c 复制代码
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. 一个通用的测试模板

c 复制代码
#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;
}
相关推荐
智商偏低5 小时前
单片机之helloworld
单片机·嵌入式硬件
青牛科技-Allen6 小时前
GC3910S:一款高性能双通道直流电机驱动芯片
stm32·单片机·嵌入式硬件·机器人·医疗器械·水泵、
森焱森8 小时前
无人机三轴稳定控制(2)____根据目标俯仰角,实现俯仰稳定化控制,计算出升降舵输出
c语言·单片机·算法·架构·无人机
白鱼不小白8 小时前
stm32 USART串口协议与外设(程序)——江协教程踩坑经验分享
stm32·单片机·嵌入式硬件
S,D9 小时前
MCU引脚的漏电流、灌电流、拉电流区别是什么
驱动开发·stm32·单片机·嵌入式硬件·mcu·物联网·硬件工程
芯岭技术12 小时前
PY32F002A单片机 低成本控制器解决方案,提供多种封装
单片机·嵌入式硬件
youmdt12 小时前
Arduino IDE ESP8266连接0.96寸SSD1306 IIC单色屏显示北京时间
单片机·嵌入式硬件
嘿·嘘12 小时前
第七章 STM32内部FLASH读写
stm32·单片机·嵌入式硬件
Meraki.Zhang12 小时前
【STM32实践篇】:I2C驱动编写
stm32·单片机·iic·驱动·i2c
几个几个n15 小时前
STM32-第二节-GPIO输入(按键,传感器)
单片机·嵌入式硬件