C语言中如何访问Nordic SDK宏定义的SAADC默认配置成员?
问题:如何复用Nordic SDK中SAADC默认配置的部分字段?
背景
Nordic SDK的SAADC驱动中,定义了NRFX_SAADC_DEFAULT_CONFIG宏用于生成nrfx_saadc_config_t结构体的默认初始化配置:
/** @brief Macro for setting @ref nrfx_saadc_config_t to default settings. */ #define NRFX_SAADC_DEFAULT_CONFIG \ { \ .resolution = (nrf_saadc_resolution_t)NRFX_SAADC_CONFIG_RESOLUTION, \ .oversample = (nrf_saadc_oversample_t)NRFX_SAADC_CONFIG_OVERSAMPLE, \ .interrupt_priority = NRFX_SAADC_CONFIG_IRQ_PRIORITY, \ .low_power_mode = NRFX_SAADC_CONFIG_LP_MODE \ }
用户需求与错误代码
用户希望自定义ADC初始化配置时,指定部分字段的自定义值,同时复用宏中的默认中断优先级,编写了如下代码:
static const nrfx_saadc_config_t adc_conf = { .resolution = NRF_SAADC_RESOLUTION_12BIT, .oversample = NRF_SAADC_OVERSAMPLE_DISABLED, .interrupt_priority = NRFX_SAADC_DEFAULT_CONFIG.interrupt_priority, // 报错行 .low_power_mode = false };
编译时出现以下错误:
drv_adc.c(73): error: #253: 预期"," .interrupt_priority = NRFX_SAADC_DEFAULT_CONFIG.interrupt_priority, drv_adc.c(73): error: #146: 初始化值过多 .interrupt_priority = NRFX_SAADC_DEFAULT_CONFIG.interrupt_priority, drv_adc.c(73): error: #3626: 指示符不能用于非聚合类型"uint8_t" .interrupt_priority = NRFX_SAADC_DEFAULT_CONFIG.interrupt_priority, drv_adc.c: 0 warnings, 3 errors
错误原因
NRFX_SAADC_DEFAULT_CONFIG是展开为结构体初始化列表的宏,并非已定义的结构体变量。C语言中无法直接对结构体初始化列表字面量进行成员访问操作,因此编译器报错。
解决方案
方法1:直接引用原始定义宏
观察默认配置宏的实现可知,中断优先级字段使用的是NRFX_SAADC_CONFIG_IRQ_PRIORITY宏,直接引用该宏即可复用默认值:
static const nrfx_saadc_config_t adc_conf = { .resolution = NRF_SAADC_RESOLUTION_12BIT, .oversample = NRF_SAADC_OVERSAMPLE_DISABLED, .interrupt_priority = NRFX_SAADC_CONFIG_IRQ_PRIORITY, .low_power_mode = false };
这是最简洁高效的方案,因为默认配置的中断优先级本质就是由这个宏定义的。
方法2:先初始化默认配置,再覆盖自定义字段
如果需要复用多个默认字段,可以先通过宏生成完整的默认配置,再修改需要自定义的部分:
// 先创建临时变量初始化默认配置 nrfx_saadc_config_t temp_conf = NRFX_SAADC_DEFAULT_CONFIG; // 覆盖自定义字段 temp_conf.resolution = NRF_SAADC_RESOLUTION_12BIT; temp_conf.oversample = NRF_SAADC_OVERSAMPLE_DISABLED; temp_conf.low_power_mode = false; // 赋值给最终的const变量 static const nrfx_saadc_config_t adc_conf = temp_conf;
注意:直接定义const变量后无法修改,因此需要先使用非const临时变量完成配置修改,再赋值给const变量。
方法3:使用C99复合字面量(编译器需支持C99)
如果编译器支持C99标准,可以将宏展开的初始化列表转换为复合字面量,进而访问其成员:
static const nrfx_saadc_config_t adc_conf = { .resolution = NRF_SAADC_RESOLUTION_12BIT, .oversample = NRF_SAADC_OVERSAMPLE_DISABLED, .interrupt_priority = ((nrfx_saadc_config_t)NRFX_SAADC_DEFAULT_CONFIG).interrupt_priority, .low_power_mode = false };
这里通过强制类型转换将初始化列表转为nrfx_saadc_config_t类型的复合字面量,从而支持成员访问。
内容的提问来源于stack exchange,提问作者ilja
相关产品推荐
相关产品推荐

