找回密码
 立即注册
查看: 86|回复: 6

【小白提问】对Ai8051U库函数的I2C模块的疑问

[复制链接]
  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 最近打卡:2025-07-30 14:33:39
已绑定手机

5

主题

7

回帖

53

积分

注册会员

积分
53
发表于 7 天前 | 显示全部楼层 |阅读模式

【小白提问】【已解决】对Ai8051U库函数的I2C模块的疑问

描述

本人新手,最近学习Ai8051U时用到I2C通讯,故而阅读Ai8051U创新风格库函数的I2C模块,有一部分不知道为什么这么写,想知道这么些有什么好处,若有大佬方便指点一二,在下感激不尽baoquan

这是set_i2c.c中的set_i2c_mode函数

屏幕截图2025-07-25093444.png

78行: arg = va_arg(args, char *)是获取可变参数列表中的下一个参数,并存入arg变量,该函数的所有参数都是字符串(char *)

79到84行: 用sscanf函数匹配arg是否符合下面这些宏的值,并做出对应操作

#define  I2c_End      "end"
#define  I2c_Enable   "\x01enable"  //设置I2C使能,默认为使能状态
#define  I2c_Disable  "\x01disable" //设置I2C外设关闭
#define  I2c_P24_3    "i2c0"        // 引脚切换宏定义,前面的是SCL,后面的是SDA
#define  I2c_P15_4    "i2c1"
#define  I2c_P32_3    "i2c3"

我的问题是

问题1

不理解79到81行为什么要用sscanf函数,82到84行用sscanf函数是因为要匹配整数(%d)和浮点数(%f)。79到81行为什么要用sscanf函数呢?直接判断是否相等不就行了吗,比如改成这样:

if (arg == "end")break;                           //遇到哨兵,结束
i2c_enable = arg == "\x01enable" ? 1 : i2c_enable;  //使能i2c功能
i2c_enable = arg == "\x01disable" ? 0 : i2c_enable; //关闭i2c功能

原写法是:

if (sscanf(arg, "en%c", &_char) == 1)break;        // 遇到哨兵,结束
i2c_enable = sscanf(arg, "\x01enabl%c", &_char) == 1 ? 1 : i2c_enable;//使能i2c功能
i2c_enable = sscanf(arg, "\x01disabl%c", &_char) == 1 ? 0 : i2c_enable;//关闭i2c功能

问题2

还有一个问题是,为什么83和84行的匹配字符串是 "%fkh%c""%fmh%c"而不是 "%fkhz""%fmhz",比如改成这样:

i2c_speed = sscanf(arg, "%fkhz", &_i2c_speed) == 1 ? (_i2c_speed*1e3) : i2c_speed;//获取i2c通讯速率
i2c_speed = sscanf(arg, "%fmhz", &_i2c_speed) == 1 ? (_i2c_speed*1e6) : i2c_speed;//获取i2c通讯速率

原写法是:

i2c_speed = sscanf(arg, "%fkh%c", &_i2c_speed, &_char) == 2 ? (_i2c_speed*1e3) : i2c_speed;//获取i2c通讯速率
i2c_speed = sscanf(arg, "%fmh%c", &_i2c_speed, &_char) == 2 ? (_i2c_speed*1e6) : i2c_speed;//获取i2c通讯速率

原写法有什么好处吗?还是说我自己的写法是完全错误的?求大佬解答,谢谢。

有个建议

khz(千赫兹)和 mhz(兆赫兹)是不符合规范的单位,建议改成 kHz 和 MHz。望采纳ciya

最后感谢创新风格库函数的编写人员,这个函数库真挺好用的。

已解决

问题1

问题1是我搞错了,直接用==判断其实比较的是两个字符串指针的地址是否相同,并不是比较字符串内容,C语言没学好了属于是,实际上应该分别比较每个字符,比如arg == "end"应该为arg[0]=='e'&&arg[1]=='n'&&arg[2]=='d'。然而之所以不这样是因为:

在嵌入式系统中,参数传递往往需要具备一定的灵活性和容错性。使用sscanf可以统一处理不同类型的参数格式,例如同时支持字符串、整数或浮点数的匹配,避免因参数类型不一致导致的错误。虽然当前代码中仅处理字符串,但统一的解析方式有助于后续功能扩展

详见2楼人工智能的回答。

问题2

问题2已经被3楼的大佬解释清楚了。

回复

使用道具 举报 送花

3

主题

247

回帖

-795

积分

等待验证会员

积分
-795
发表于 7 天前 | 显示全部楼层
关于您在使用Ai8051U库函数中对I2C模块的疑问,以下是对seti2cmode函数中sscanf使用逻辑的专业解释。

在seti2cmode函数中,第78行通过vaarg(args, char)获取可变参数列表中的下一个参数,并将其作为字符串处理。随后,从第79行到第84行,依次使用sscanf函数对参数进行匹配与解析。其中,第79至81行的参数匹配(如"I2cEnd"、"I2cEnable"等)确实可以采用直接比较的方式(如if (strcmp(arg, "end") == 0)),但实际设计中使用sscanf的原因可能涉及以下几个方面:

1. 统一参数解析逻辑:  
   在嵌入式系统中,参数传递往往需要具备一定的灵活性和容错性。使用sscanf可以统一处理不同类型的参数格式,例如同时支持字符串、整数或浮点数的匹配,避免因参数类型不一致导致的错误。虽然当前代码中仅处理字符串,但统一的解析方式有助于后续功能扩展。

2. 增强参数匹配的鲁棒性:  
   sscanf能够处理字符串中可能存在的空格、换行符或其他非关键字符,提升参数匹配的稳定性。相比之下,直接比较字符串(如arg == "end")仅适用于精确匹配,且需确保参数字符串的内存地址一致,这在动态生成或外部传入的参数中可能存在风险。

3. 兼容性与可维护性:  
   若未来需支持更复杂的参数格式(如带前缀的标识符或混合类型参数),sscanf的灵活性将显著优于直接比较。此外,统一的解析逻辑便于团队协作与后期维护,减少因不同实现方式导致的代码碎片化。

4. 潜在的宏定义差异:  
   部分宏定义(如I2cEnable)包含特殊字符(如\x01),这些字符可能影响字符串比较的准确性。sscanf能够正确解析这类特殊格式,而直接比较可能因字符编码问题导致误判。

综上所述,尽管在当前场景下直接比较字符串是可行的,但使用sscanf的设计更符合嵌入式系统对参数解析的通用性和扩展性需求。若需优化代码,可考虑在明确参数类型的前提下,结合strcmp与sscanf的混合策略,以兼顾效率与安全性。

[本文内容由国芯人工智能辅助生成,仅供参考]
回复 支持 1 反对 0

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:532
  • 最近打卡:2025-07-31 14:15:17
已绑定手机
已实名认证

116

主题

2499

回帖

6450

积分

版主

积分
6450
发表于 7 天前 | 显示全部楼层
是这样的,sscanf的返回值是匹配正确的个数,如果这么写:i2c_speed = sscanf(arg, "%fkhz", &_i2c_speed) == 1 ? (_i2c_speed*1e3) : i2c_speed;//获取i2c通讯速率,那么会导致输入100也可以被正确读取,因为后面的字符被忽略了(没有匹配,原因是sscanf会觉得后面的没有需要识别的就不匹配了)
所以我将最后一个字符匹配一下,但是并没有用他,算是用来对抗sscanf库中的一个偷懒机制

至于你说的单位不标准问题,后续我考虑一下加入大小写换算,这样就可以任意输入大小写了,目前暂时不打算改,因为可能会导致用户输入起来过于麻烦
回复 支持 1 反对 0

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 最近打卡:2025-07-30 14:33:39
已绑定手机

5

主题

7

回帖

53

积分

注册会员

积分
53
发表于 7 天前 | 显示全部楼层
王*** 发表于 2025-7-25 12:35
是这样的,sscanf的返回值是匹配正确的个数,如果这么写:i2c_speed = sscanf(arg, "%fkhz", &_i2c_speed)  ...

感谢
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 最近打卡:2025-07-30 14:33:39
已绑定手机

5

主题

7

回帖

53

积分

注册会员

积分
53
发表于 7 天前 | 显示全部楼层
王*** 发表于 2025-7-25 12:35
是这样的,sscanf的返回值是匹配正确的个数,如果这么写:i2c_speed = sscanf(arg, "%fkhz", &_i2c_speed)  ...

大佬,为什么可能会导致用户输入起来过于麻烦呢?不理解。

点评

因为并不是所有人都使用了vscode这种带有自动补全的编辑工具 所以我要尽量保证同一种大小写,减少切换大小写的次数,方便手敲,同时减少初学者敲错大小写导致的报错问题  详情 回复 发表于 7 天前
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:532
  • 最近打卡:2025-07-31 14:15:17
已绑定手机
已实名认证

116

主题

2499

回帖

6450

积分

版主

积分
6450
发表于 7 天前 | 显示全部楼层
懒*** 发表于 2025-7-25 13:50
大佬,为什么可能会导致用户输入起来过于麻烦呢?不理解。

因为并不是所有人都使用了vscode这种带有自动补全的编辑工具
所以我要尽量保证同一种大小写,减少切换大小写的次数,方便手敲,同时减少初学者敲错大小写导致的报错问题
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:初来乍到
  • 打卡总天数:5
  • 最近打卡:2025-07-30 14:33:39
已绑定手机

5

主题

7

回帖

53

积分

注册会员

积分
53
发表于 7 天前 | 显示全部楼层
王*** 发表于 2025-7-25 14:18
因为并不是所有人都使用了vscode这种带有自动补全的编辑工具
所以我要尽量保证同一种大小写,减少切换大 ...

原来如此,感谢解惑
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-8-1 01:42 , Processed in 0.119581 second(s), 88 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表