外部 ADC 模拟输入引脚总表(LQFP48)
| 物理 PIN | GPIO 名称 | ADC 信号名 | ADC 实例 | Channel | 备注 |
|---|---|---|---|---|---|
| 47 | PA27 | A0_0 | ADC0 | CH0 | ⚠️ 同脚可为 DAC_OUT |
| 46 | PA26 | A0_1 | ADC0 | CH1 | |
| 45 | PA25 | A0_2 | ADC0 | CH2 | |
| 44 | PA24 | A0_3 | ADC0 | CH3 | |
| 43 | PA23 | A0_4 | ADC0 | CH4 | |
| 42 | PB22 | A0_5 | ADC0 | CH5 | |
| 41 | PB20 | A0_6 | ADC0 | CH6 | |
| 40 | PA22 | A0_7 | ADC0 | CH7 | |
| 29 | PA14 | A0_12 | ADC0 | CH12 | |
| 30 | PA15 | A1_0 | ADC1 | CH0 | ⚠️ DAC_OUT 复用 |
| 31 | PA16 | A1_1 | ADC1 | CH1 | |
| 32 | PA17 | A1_2 | ADC1 | CH2 | |
| 33 | PA18 | A1_3 | ADC1 | CH3 | |
| 36 | PB17 | A1_4 | ADC1 | CH4 | |
| 38 | PB19 | A1_5 | ADC1 | CH5 | |
| 37 | PB18 | A1_6 | ADC1 | CH6 | |
| 39 | PA21 | A1_7 | ADC1 | CH7 |
adc_singlechannel 解析
TI Drivers Config
根据外部 ADC 模拟输入引脚总表配置ADC, PA22是ADC0_7, PA17是ADC1_2
c
/*
* ======== ADC ========
*/
#define ADC_0_INST ADC0
#define ADC_1_INST ADC1
/* PA22_ADC0_7 */
extern const uint_least8_t CONFIG_ADC_0_CONST;
#define CONFIG_ADC_0 0
/* PA17_ADC1_2 */
extern const uint_least8_t CONFIG_ADC_1_CONST;
#define CONFIG_ADC_1 1
#define CONFIG_TI_DRIVERS_ADC_COUNT 2
/*
* ======== GPIO ========
*/
/* Owned by CONFIG_ADC_0 as */
extern const uint_least8_t CONFIG_GPIO_ADC_0_AIN_CONST;
/* This is actual port pin */
#define CONFIG_GPIO_ADC_0_AIN (22)
#define CONFIG_GPIO_ADC_0_AIN_PINCM (IOMUX_PINCM47)
#define CONFIG_GPIO_ADC_0_AIN_PINMUX (IOMUX_PINCM47_PF_GPIOA_DIO22)
/* Owned by CONFIG_ADC_1 as */
extern const uint_least8_t CONFIG_GPIO_ADC_1_AIN_CONST;
/* This is actual port pin */
#define CONFIG_GPIO_ADC_1_AIN (17)
#define CONFIG_GPIO_ADC_1_AIN_PINCM (IOMUX_PINCM39)
#define CONFIG_GPIO_ADC_1_AIN_PINMUX (IOMUX_PINCM39_PF_GPIOA_DIO17)
c
/*
* =============================== ADC ===============================
*/
#include <ti/drivers/ADC.h>
#include <ti/drivers/adc/ADCMSPM0.h>
#define CONFIG_ADC_COUNT 2
/*
* ======== adcMSPM0Objects ========
*/
ADCMSPM0_Object adcObjects[CONFIG_ADC_COUNT];
/*
* ======== adcMSPM0HWAttrs ========
*/
const ADCMSPM0_HWAttrs adcHWAttrs[CONFIG_ADC_COUNT] = {
/* CONFIG_ADC_0 */
{.adc = ADC_0_INST,
.adcInputDIO = CONFIG_GPIO_ADC_0_AIN,
.adcInputPincm = CONFIG_GPIO_ADC_0_AIN_PINCM,
.adcInputPinMux = CONFIG_GPIO_ADC_0_AIN_PINMUX,
.adcPosRefDIO = GPIO_INVALID_INDEX,
.adcNegRefDIO = GPIO_INVALID_INDEX,
.adcChannel = 7,
.refSource = ADCMSPM0_VDDA_REFERENCE,
.samplingDuration = 16,
.refVoltage = 3300000, /* uV */
.resolutionBits = ADCMSPM0_RESOLUTION_12_BIT,
.adcClkkDivider = ADCMSPM0_CLKDIV_8,
.adcClkSelect = ADCMSPM0_CLK_ULPCLK,
.adcClkFreqRange = ADCMSPM0_CLK_FREQ_RANGE_24TO32,
.conversionMode = ADCMSPM0_SINGLE_CH_SINGLE_CONV,
.conversionStartAddr = 0,
.conversionEndAddr = 0,
.repeatConversionMode = ADCMSPM0_REPEAT_MODE_ENABLED,
.samplingMode = ADCMSPM0_SAMPLING_MODE_AUTO,
.sampleTrigger = ADCMSPM0_SAMPLING_TRIG_SW,
.conversionDataFormat = ADCMSPM0_CONV_DATA_FORMAT_UNSIGNED,
.sampleTimerSrc = ADCMSPM0_SAMP_TMR_SOURCE_SCOMP0,
.conversionTrigger = ADCMSPM0_NEXT_CONV_WITH_TRIG,
.adcHWAveraging = ADCMSPM0_HW_AVG_DISABLED,
.idxMEMCTLx = 0},
/* CONFIG_ADC_1 */
{.adc = ADC_1_INST,
.adcInputDIO = CONFIG_GPIO_ADC_1_AIN,
.adcInputPincm = CONFIG_GPIO_ADC_1_AIN_PINCM,
.adcInputPinMux = CONFIG_GPIO_ADC_1_AIN_PINMUX,
.adcPosRefDIO = GPIO_INVALID_INDEX,
.adcNegRefDIO = GPIO_INVALID_INDEX,
.adcChannel = 2,
.refSource = ADCMSPM0_VDDA_REFERENCE,
.samplingDuration = 16,
.refVoltage = 3300000, /* uV */
.resolutionBits = ADCMSPM0_RESOLUTION_12_BIT,
.adcClkkDivider = ADCMSPM0_CLKDIV_8,
.adcClkSelect = ADCMSPM0_CLK_SYSOSC,
.adcClkFreqRange = ADCMSPM0_CLK_FREQ_RANGE_24TO32,
.conversionMode = ADCMSPM0_SINGLE_CH_SINGLE_CONV,
.conversionStartAddr = 0,
.conversionEndAddr = 0,
.repeatConversionMode = ADCMSPM0_REPEAT_MODE_ENABLED,
.samplingMode = ADCMSPM0_SAMPLING_MODE_AUTO,
.sampleTrigger = ADCMSPM0_SAMPLING_TRIG_SW,
.conversionDataFormat = ADCMSPM0_CONV_DATA_FORMAT_UNSIGNED,
.sampleTimerSrc = ADCMSPM0_SAMP_TMR_SOURCE_SCOMP0,
.conversionTrigger = ADCMSPM0_NEXT_CONV_WITH_TRIG,
.adcHWAveraging = ADCMSPM0_HW_AVG_DISABLED,
.idxMEMCTLx = 0},
};
/*
* ======== ADC_config ========
*/
const ADC_Config ADC_config[CONFIG_ADC_COUNT] = {
/* CONFIG_ADC_0 */
{.fxnTablePtr = &ADCMSPM0_fxnTable,
.object = &adcObjects[CONFIG_ADC_0],
.hwAttrs = &adcHWAttrs[CONFIG_ADC_0]},
/* CONFIG_ADC_1 */
{.fxnTablePtr = &ADCMSPM0_fxnTable,
.object = &adcObjects[CONFIG_ADC_1],
.hwAttrs = &adcHWAttrs[CONFIG_ADC_1]},
};
const uint_least8_t CONFIG_ADC_0_CONST = CONFIG_ADC_0;
const uint_least8_t CONFIG_ADC_1_CONST = CONFIG_ADC_1;
const uint_least8_t ADC_count = CONFIG_ADC_COUNT;
ADC模块配置代码注释
该代码实现了TI MSPM0系列微控制器的ADC(模数转换器)驱动配置,包含硬件属性初始化、对象实例化和全局配置表。
硬件属性配置结构体
ADCMSPM0_HWAttrs结构体数组包含两个ADC实例的硬件参数配置:
c
{
.adc = ADC_0_INST, // ADC模块实例标识符
.adcInputDIO = CONFIG_GPIO_ADC_0_AIN, // 模拟输入引脚编号
.adcChannel = 7, // ADC通道号
.refSource = ADCMSPM0_VDDA_REFERENCE, // 参考电压源(使用VDDA)
.samplingDuration = 16, // 采样周期时长
.refVoltage = 3300000, // 参考电压值(单位:微伏)
.resolutionBits = ADCMSPM0_RESOLUTION_12_BIT, // 12位分辨率
.adcClkkDivider = ADCMSPM0_CLKDIV_8, // 时钟分频系数
.conversionMode = ADCMSPM0_SINGLE_CH_SINGLE_CONV // 单通道单次转换模式
}
ADC对象实例化
创建两个ADC对象实例用于运行时状态管理:
c
ADCMSPM0_Object adcObjects[CONFIG_ADC_COUNT]; // CONFIG_ADC_COUNT定义为2
驱动配置表
ADC_Config结构体数组将驱动函数表、对象实例和硬件属性关联:
c
{
.fxnTablePtr = &ADCMSPM0_fxnTable, // 指向ADC驱动函数表
.object = &adcObjects[CONFIG_ADC_0], // 指向对象实例
.hwAttrs = &adcHWAttrs[CONFIG_ADC_0] // 指向硬件属性
}
全局常量定义
c
const uint_least8_t CONFIG_ADC_0_CONST = CONFIG_ADC_0; // ADC实例0的索引常量
const uint_least8_t CONFIG_ADC_1_CONST = CONFIG_ADC_1; // ADC实例1的索引常量
const uint_least8_t ADC_count = CONFIG_ADC_COUNT; // 可用ADC实例总数
关键配置参数说明
-
时钟配置:使用ULPCLK(超低功耗时钟)或SYSOSC(系统振荡器)
-
触发模式 :
ADCMSPM0_SAMPLING_TRIG_SW表示软件触发采样 -
数据格式 :
ADCMSPM0_CONV_DATA_FORMAT_UNSIGNED无符号数据格式 -
参考电压:3.3V(3300000uV)对应12位分辨率时LSB≈0.8mV
main thread
- ADC_init();
初始化ADC模块 - 分别创建thread来读取ADC0, ADC1的值
c/* * ======== mainThread ======== */ void *mainThread(void *arg0) { pthread_t thread0, thread1; pthread_attr_t attrs; struct sched_param priParam; int retc; int detachState; /* Call driver init functions */ Display_init(); GPIO_init(); ADC_init(); /* Configure the LED and if applicable, the TMP_EN pin */ GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_HIGH | CONFIG_GPIO_LED_0_IOMUX); /* Open the UART display for output */ display = Display_open(Display_Type_UART, NULL); if (display == NULL) { /* Failed to open display driver */ while (1) { } } /* Turn on user LED to indicate successful initialization */ GPIO_write(CONFIG_GPIO_LED_0, CONFIG_LED_ON); Display_printf(display, 0, 0, "Starting the adcsinglechannel example\n"); /* Create application threads */ pthread_attr_init(&attrs); detachState = PTHREAD_CREATE_DETACHED; /* Set priority and stack size attributes */ retc = pthread_attr_setdetachstate(&attrs, detachState); if (retc != 0) { /* pthread_attr_setdetachstate() failed */ while (1) { } } retc |= pthread_attr_setstacksize(&attrs, THREADSTACKSIZE); if (retc != 0) { /* pthread_attr_setstacksize() failed */ while (1) { } } /* Create threadFxn0 thread */ priParam.sched_priority = 1; pthread_attr_setschedparam(&attrs, &priParam); retc = pthread_create(&thread0, &attrs, threadFxn0, NULL); if (retc != 0) { /* pthread_create() failed */ while (1) { } } /* Create threadFxn1 thread */ retc = pthread_create(&thread1, &attrs, threadFxn1, (void *) 0); if (retc != 0) { /* pthread_create() failed */ while (1) { } } return (NULL); } - ADC_init();
threadFxn0
对 一个 ADC 通道做一次单次采样
c
/*
* ======== threadFxn0 ========
* Open an ADC instance and get a sampling result from a one-shot conversion.
*/
void *threadFxn0(void *arg0)
{
ADC_Handle adc;
ADC_Params params;
int_fast16_t res;
ADC_Params_init(¶ms);
adc = ADC_open(CONFIG_ADC_0, ¶ms);
if (adc == NULL) {
Display_printf(display, 0, 0, "Error initializing CONFIG_ADC_0\n");
while (1) {
}
}
/* Blocking mode conversion */
res = ADC_convert(adc, &adcValue0);
if (res == ADC_STATUS_SUCCESS) {
adcValue0MicroVolt = ADC_convertRawToMicroVolts(adc, adcValue0);
Display_printf(
display, 0, 0, "CONFIG_ADC_0 raw result: %d\n", adcValue0);
Display_printf(display, 0, 0, "CONFIG_ADC_0 convert result: %d uV\n",
adcValue0MicroVolt);
} else {
Display_printf(display, 0, 0, "CONFIG_ADC_0 convert failed\n");
}
ADC_close(adc);
return (NULL);
}
threadFxn1
对 ADC 通道做 10 次采样
c
/*
* ======== threadFxn1 ========
* Open a ADC handle and get an array of sampling results after
* calling several conversions.
*/
void *threadFxn1(void *arg0)
{
uint16_t i;
ADC_Handle adc;
ADC_Params params;
int_fast16_t res;
ADC_Params_init(¶ms);
adc = ADC_open(CONFIG_ADC_1, ¶ms);
if (adc == NULL) {
Display_printf(display, 0, 0, "Error initializing CONFIG_ADC_1\n");
while (1) {
}
}
for (i = 0; i < ADC_SAMPLE_COUNT; i++) {
res = ADC_convert(adc, &adcValue1[i]);
if (res == ADC_STATUS_SUCCESS) {
adcValue1MicroVolt[i] = ADC_convertToMicroVolts(adc, adcValue1[i]);
Display_printf(display, 0, 0, "CONFIG_ADC_1 raw result (%d): %d\n",
i, adcValue1[i]);
Display_printf(display, 0, 0,
"CONFIG_ADC_1 convert result (%d): %d uV\n", i,
adcValue1MicroVolt[i]);
} else {
Display_printf(
display, 0, 0, "CONFIG_ADC_1 convert failed (%d)\n", i);
}
}
ADC_close(adc);
return (NULL);
}