RT1060 ADC demo 寄存器解析_Part1
RT1060 ADC demo 寄存器解析_Part1
参考RT1060-EVKB SDK demo : adc_12b1msps_sar_polling
要求:
ADC1_IN0 is ADC input. Please sample voltage by J33-2 pin.
详细分析 adc_polling.c 从 API 调用到底层寄存器写入的顺序(软件触发情形),并给出时序说明与 mermaid 流程图,便于调试与理解硬件交互。
RT1062的ADC寄存器全览:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 /** ADC - Size of Registers Arrays */
/** ADC - Register Layout Typedef */
typedef struct {
__IO uint32_t HC[ADC_HC_COUNT]; /**< Control register for hardware triggers, array offset: 0x0, array step: 0x4 */
__I uint32_t HS; /**< Status register for HW triggers, offset: 0x20 */
__I uint32_t R[ADC_R_COUNT]; /**< Data result register for HW triggers, array offset: 0x24, array step: 0x4 */
__IO uint32_t CFG; /**< Configuration register, offset: 0x44 */
__IO uint32_t GC; /**< General control register, offset: 0x48 */
__IO uint32_t GS; /**< General status register, offset: 0x4C */
__IO uint32_t CV; /**< Compare value register, offset: 0x50 */
__IO uint32_t OFS; /**< Offset correction value register, offset: 0x54 */
__IO uint32_t CAL; /**< Calibration value register, offset: 0x58 */
} ADC_Type;
概要
典型动作(软件触发):
- 初始化(
ADC_Init) - 禁用硬件触发并校准(
ADC_EnableHardwareTrigger(false)、ADC_DoAutoCalibration) - 选择通道并触发(
ADC_SetChannelConfig-> 写HC[0]) - 硬件采样/转换(ADC 内部使用 CFG 中的
ADCK/ADSTS/ADLSMP配置) - 写结果到
R[0]并置HS.COCO[0] - CPU 轮询 HS,读
R[0]
下面给出更详细的寄存器写入顺序及每步与时间/注意事项。
步骤与寄存器写入(详细)
ADC_Init(base, config)CLOCK_EnableClock(s_adcClocks[instance])结果:ADC 模块时钟使能,外设开始有时钟脉冲。
注意:若时钟未使能,后续读写寄存器可能无效。
1 | // 保留了 硬件触发or软件触发 + n samples平均 |
- 写入 CFG:配置 ADICLK(决定 ADCK)、ADIV(分频)、MODE(位宽)、ADSTS(采样时钟长度)等。
关于RT1060的ADC参考电压:
唯一有效选项:外部 VREFH/VREFL 引脚
- VREFH:通常接 3.3V 或 1.8V(取决于模拟电源域),必须满足数据手册要求(比如 2.7V–3.6V,如果 ADC 工作在 3.3V 模拟域)。
- VREFL:通常接地(VSSAD)。
关于ADC采样周期 ADSTS:
字段作用:
- ADC 在转换前需要将输入信号采样到内部采样电容上,采样时间越长,电容充电越充分,适合高阻抗信号源。
- 如果信号源阻抗低,可以用短采样时间提高转换速度。
- 长采样模式(ADLSMP=1)会显著增加采样周期,降低速率,但提高精度,尤其在高阻抗输入或低功耗场景。
- ADSTS(Sample Period Mode)是一个 2 位字段,取值 00、01、10、11。
- ADLSMP 决定是短采样还是长采样:
- ADLSMP=0 → 短采样模式
- ADLSMP=1 → 长采样模式
- 每种组合对应不同的采样周期(单位:ADC 时钟周期)。
时间影响:CFG 写入之后,采样/转换的时钟源和采样窗口由这些字段决定;若使用异步时钟(AD),ADCK 会由所选时钟源产生。
1 | tmp32 = base->GC & ~(ADC_GC_ADCO_MASK | ADC_GC_ADACKEN_MASK); |
- 写入
GC:连续模式、异步时钟输出及其他控制位(DMA、校准启动位也存在于 GC)。
禁用硬件触发(若需要)
ADC_EnableHardwareTrigger(base, false)-> clearCFG.ADTRG- 置 ADTRG=0 表示软件触发,写 HC[0] 会触发转换。
自动校准(可选但建议)
base->GS = ADC_GS_CALF_MASK;// 清掉 CALFbase->GC |= ADC_GC_CAL_MASK;// 设置 CAL 位启动校准等待:
while (base->GC & ADC_GC_CAL_MASK) { check GS.CALF }完成后:驱动读取
HS.COCO[0]来确认结果(驱动中会读 R[0] 清 COCO)时间:校准时间与 ADC 的硬件规格有关(可在数据手册查到绝对时间或以 ADCK 周期计)。校准期间不要触发其他转换。
触发一次转换(软件触发)
ADC_SetChannelConfig(base, 0, &cfg) => base->HC[0] = ADC_HC_ADCH(channel) | (AIEN?ADC_HC_AIEN:0)- 写 HC[0] 在软件触发模式下是“启动一次转换命令”。
- 硬件:ADC 在写入后开始采样(采样保持)并随后转换。
硬件采样 -> 转换 -> 把结果写入 R[0] 并在 HS 对应位置 1
ADC 内部:采样期(由 ADSTS/ADLSMP 决定) -> 采样电容充电 -> 转换周期(受 ADCK 影响)
完成:ADC 写 R[0]、设置 HS.COCO[0]。
CPU 读取
使用
ADC_GetChannelStatusFlags检查 HS 的 COCO 位。读 R[0] 得到原始结果;读取可能会清除某些完成标志(驱动用读取来清 COCO)。
时序图(mermaid)
sequenceDiagram
participant App as adc_polling.c (CPU)
participant SDK as fsl_adc.c/h
participant ADC as ADC hardware (registers)
participant CLOCK as Clock controller
participant UART as UART / Printf
App->>SDK: ADC_GetDefaultConfig()
App->>SDK: ADC_Init(base, config)
SDK->>CLOCK: CLOCK_EnableClock(ADC)
SDK->>ADC: write CFG (REFSEL, ADICLK, ADIV, MODE, ADSTS...)
SDK->>ADC: write GC (ADCO, ADACKEN...)
App->>SDK: ADC_EnableHardwareTrigger(false)
SDK->>ADC: clear CFG.ADTRG (software trigger mode)
App->>SDK: ADC_DoAutoCalibration()
SDK->>ADC: GS = CLEAR_CALF
SDK->>ADC: GC |= CAL (start calibration)
Note over SDK,ADC: SDK polls until GC.CAL clears and GS.CALF is set
ADC-->>SDK: Calibration complete
App->>SDK: ADC_SetChannelConfig(base, 0, cfg)
SDK->>ADC: write HC[0] (ADCH=channel, AIEN?) -> triggers conversion
Note over ADC: sample (ADSTS/ADLSMP) -> convert (ADCK cycles) -> write R[0]
ADC-->>SDK: set HS.COCO[0] = 1 (conversion complete)
loop Poll until ready
App->>SDK: ADC_GetChannelStatusFlags()
SDK->>ADC: read HS
end
App->>SDK: ADC_GetChannelConversionValue()
SDK->>ADC: read R[0]
App->>UART: PRINTF(value)
延伸
- 如果你打算改为硬件触发:设置
CFG.ADTRG = 1,然后通过外设(例如 PIT、FTM、GPIO 事件或 ADC_ETC)输出触发信号,HC 寄存器将被外部事件触发转换。 - 若要用 DMA:设置
GC.DMAEN = 1并配置 DMA 控制器为在 COCO 事件后搬运R[n]数据。 - 若要提高稳定性:使用
ADC_SetHardwareAverageConfig()来启用硬件平均(需配置CFG.AVGS与GC.AVGE)。
快速参考表(寄存器 => 关键位)
CFG:REFSEL- 参考电压选择ADSTS- 采样时序选择ADICLK- AD 时钟源选择ADIV- AD 时钟分频MODE- ADC 分辨率ADTRG- 0 = 软件触发,1 = 硬件触发
GC:ADCO- 连续转换ADACKEN- 异步时钟输出CAL- 启动校准DMAEN- 使能 DMA 触发AVGE- 硬件平均使能
HC[n]:ADCH- 要采样的通道号AIEN- 转换完成中断
HS:COCO[n]- channel group n 的转换完成标志
GS:CALF- 校准失败标志ADACT- 转换正在进行标志
附录一(总结版)
- 变量与初始化
- 常量
g_Adc_12bitFullRange = 4096U:12-bit ADC 的满量程值是 4096。 BOARD_InitHardware():板级启动例程,包含引脚复用(Pin mux)、时钟系统初始化与调试串口(UART)初始化。若BOARD_InitHardware()没执行或配置不当,ADC 引脚可能无法作为模拟输入使用。
- ADC 配置与初始化
ADC_GetDefaultConfig(&adcConfigStruct):用 SDK 提供的默认值填充adc_config_t(详见fsl_adc.h)。这一步不会触碰寄存器,只是准备结构体。ADC_Init(DEMO_ADC_BASE, &adcConfigStruct):底层实现会:- 通过
CLOCK_EnableClock(...)打开 ADC 外设时钟(必须); - 写
ADC->CFG(CFG 寄存器)来设置分辨率(MODE)、时钟来源(ADICLK)、分频(ADIV)、采样时序(ADSTS)、参考电压选择(REFSEL)和长采样/低功耗/高速标志; - 写
ADC->GC(GC 寄存器)设置是否连续转换(ADCO)和异步时钟输出(ADACKEN)等。
- 通过
- 触发与校准
ADC_EnableHardwareTrigger(DEMO_ADC_BASE, false):把CFG.ADTRG置 0 —— 软件触发模式(写 HC 寄存器时会立即触发转换)。ADC_DoAutoCalibration(DEMO_ADC_BASE):执行自动校准流程,关键寄存器交互:- 清除
GS.CALF(写ADC->GS = ADC_GS_CALF_MASK); - 在
GC寄存器置CAL(ADC->GC |= ADC_GC_CAL_MASK)来启动校准; - 等待
GC.CAL清零(表示校准结束),中间检查GS.CALF(校准失败标志)。校准完成后 SDK 会检查HS.COCO[0]是否置位并读取R[0]清除 COCO 标志。
- 清除
- 通道选择与轮询读取
adcChannelConfigStruct.channelNumber = DEMO_ADC_USER_CHANNEL:选择模拟输入通道编号(该编号如何映射到引脚由pin_mux.c和器件参考手册决定)。ADC_SetChannelConfig(DEMO_ADC_BASE, DEMO_ADC_CHANNEL_GROUP, &adcChannelConfigStruct):写HC[channelGroup]寄存器(字段 ADCH = channelNumber,AIEN = 中断使能)。在软件触发模式下,写HC[0]即会触发一次采样/转换。while (0U == ADC_GetChannelStatusFlags(...)) { }:轮询HS寄存器对应位(COCO)直到转换完成。ADC_GetChannelConversionValue(...):读R[channelGroup],获得原始 ADC 值(0..4095)。
- 打印与使用
PRINTF("ADC Value: %d\\r\\n", raw):将数值通过串口打印。若要得到电压值,使用 V = raw / (2^N - 1) * Vref(N = 12,2^12 - 1 = 4095)。
附录二 (纯寄存器版代码实现)
1 | int main(void) |
RT1060 ADC demo 寄存器解析_Part1
https://dustofstars.github.io/NXP/RT1060/ADC/rt1060-adc-demo-寄存器解析-part1/
