MSP430 ADC10_B模块实战:从低功耗配置到温度传感器校准

📅 2026/7/24 9:19:21 👁️ 阅读次数 📝 编程学习
MSP430 ADC10_B模块实战:从低功耗配置到温度传感器校准

1. MSP430 ADC10_B模块:从入门到精通的实战指南

在嵌入式开发,尤其是电池供电的低功耗应用里,模数转换器(ADC)的性能和功耗往往是决定系统成败的关键。我接触过不少MCU的ADC模块,但MSP430的ADC10_B模块以其精巧的设计和极致的低功耗特性,给我留下了深刻的印象。它不仅仅是一个简单的ADC,更是一个集成了温度传感、窗口比较、灵活中断管理等高级功能的模拟前端工具箱。很多新手开发者初次接触它的寄存器配置时可能会感到头大,特别是面对温度传感器校准、中断优先级处理这些细节时,容易踩坑。今天,我就结合自己多年的项目经验,把这个模块从基本原理到高级应用,掰开揉碎了讲清楚,让你不仅能看懂手册,更能用得好、用得稳。

2. ADC10_B模块核心架构与设计思路

要玩转ADC10_B,不能只停留在“配置寄存器、读取结果”的层面,必须理解其设计哲学。MSP430作为超低功耗MCU的标杆,其ADC10_B模块的设计处处体现了对功耗和灵活性的极致追求。

2.1 模块整体架构与信号链解析

ADC10_B是一个10位精度的逐次逼近型(SAR)ADC。它的核心工作流程可以概括为:采样 -> 保持 -> 量化 -> 编码。但与许多其他MCU的ADC不同,ADC10_B的架构高度模块化,允许你对每个环节进行精细控制。

首先看时钟系统。ADC10_B的转换时钟(ADC10CLK)并非固定,它由主时钟源(MODCLK、ACLK、MCLK、SMCLK)经过一个预分频器(ADC10PDIVx)和一个可编程分频器(ADC10DIVx)共同产生。这种设计的好处是,你可以根据转换速度的需求,选择低频的ACLK以节省功耗,或者选择高频的SMCLK以获得更快的采样率,同时通过分频来匹配ADC内核的最佳工作频率。一个常见的误区是直接使用最高频率的时钟而不分频,这可能导致转换精度下降,因为SAR ADC的内部开关电容网络需要稳定的时钟边沿来完成逐位比较。

采样保持环节则由ADC10SHTx位控制。它定义了采样电容对输入信号进行充电的ADC10CLK周期数。这个时间必须足够长,以确保采样电容上的电压能够精确跟踪输入信号。手册给出的公式是采样时间Tsample = (ADC10SHTx + 1) * ADC10CLK周期。对于高阻抗信号源,必须增加ADC10SHTx的值。这里有一个关键经验:使用内部温度传感器时,手册明确要求采样周期必须大于30µs。这是因为温度传感器的输出阻抗较高,需要更长的采样时间来建立稳定电压。假设你的ADC10CLK为1MHz(周期1µs),那么ADC10SHTx至少需要设置为能提供31个时钟周期的值,例如0010b(16周期)就不够,应选择0011b(32周期)或更高。

参考电压的选择(ADC10SREFx)直接决定了ADC的量程和精度。你可以选择AVCC/AVSS、内部参考(VREF)、外部参考(VEREF+/VEREF-)等多种组合。对于高精度测量,强烈建议使用内部或外部精密参考电压源,而不是直接使用电源电压(AVCC)。因为电源电压可能存在纹波和噪声,会直接叠加到转换结果上。ADC10_B模块内部有一个参考电压缓冲器,其驱动能力由ADC10SR位控制。当采样率低于50ksps时,可以设置ADC10SR=1来降低缓冲器电流,进一步节省功耗。

2.2 低功耗与高性能的平衡艺术

ADC10_B的功耗控制体现在多个层面。最直接的是ADC10ON位,不用ADC时彻底关闭它。其次是时钟选择,在低速采样应用(如温度监测)中,使用32kHz的ACLK作为时钟源,并设置较大的分频比,可以显著降低动态功耗。

更高级的用法是结合转换模式(ADC10CONSEQx)和中断。ADC10_B支持四种模式:

  • 单通道单次转换(00b):最基础的模式,每次转换都需要软件触发。功耗最低,但CPU干预最多。
  • 序列通道转换(01b):可以自动按顺序对多个通道进行转换,转换完成后产生一次中断。适合周期性扫描多个传感器。
  • 单通道重复转换(10b):对单个通道进行连续转换。结合DMA,可以实现几乎不占用CPU的数据流采集。
  • 序列通道重复转换(11b):对多个通道进行连续循环转换。这是构建自主数据采集系统的核心。

在低功耗应用中,一个黄金法则是:让ADC在CPU睡眠时工作。你可以配置ADC10_B使用定时器触发(ADC10SHSx选择Timer_A/B输出),设置为单通道重复模式,并使能转换完成中断。然后让CPU进入低功耗模式(LPM0/LPM3)。当ADC完成一次转换并产生中断时,CPU被唤醒,在中断服务程序中读取数据并做简单处理,然后继续睡眠。这样,系统平均电流可以降至微安级别。

3. 集成温度传感器的原理、使用与校准实战

ADC10_B模块内部集成了一个温度传感器,这是一个非常实用的功能,常用于监测芯片结温,进行温度补偿或实现简单的温度报警功能。

3.1 温度传感器的工作原理与电气特性

这个温度传感器本质上是一个工作在正向偏压下的PN结(二极管)。其正向压降Vf与绝对温度T成反比关系,具有大约-2mV/°C的温度系数。模块内部已经将这个电压信号连接到了一个专用的模拟输入通道。

使用它非常简单:只需要将通道选择位ADC10INCHx设置为1010b(即十进制10),即可选中内部温度传感器通道。其他配置(参考电压、采样时间等)与测量外部通道完全相同。

但是,直接读取ADC值并按照理想公式计算温度,结果往往偏差很大。这是因为半导体制造工艺的偏差,导致每个芯片的温度传感器其绝对电压值和温度系数都存在差异。这就是手册中强调的“温度传感器偏移误差可能很大,大多数应用需要校准”的原因。

上图展示了典型的温度传感器传输特性曲线。你可以看到,电压与温度大致呈线性负相关,但不同芯片的曲线会在垂直方向(偏移)和斜率(增益)上有所偏移。

3.2 温度测量的详细步骤与校准方法

要获得可用的温度数据,必须遵循以下步骤,其中校准是关键:

  1. 基础配置

    • 选择温度传感器通道:ADC10INCHx = 1010b
    • 确保采样时间 > 30µs:根据ADC10CLK频率计算并设置ADC10SHTx
    • 选择稳定的参考电压:推荐使用内部1.5V或2.5V参考(ADC10SREFx = 001b011b),精度更高。
    • 根据需要使能中断。
  2. 两点校准法(推荐): 这是最有效的校准方法,需要已知两个不同的温度点(T1, T2)及其对应的ADC原始读数(N1, N2)。

    • 获取校准数据:有些MSP430型号(如MSP430FRxx系列)在信息存储器(Info Memory)或TLV(Tag-Length-Value)结构中,存储了芯片在30°C和85°C下的ADC校准值。这是最方便的方式。
    • 手动校准:如果没有预存数据,你需要创造一个已知温度环境。例如,将芯片置于室温(用精度较高的温度计测量,得T1),记录ADC值N1;然后用手指或温控设备给芯片加热到一个较高温度(T2),记录ADC值N2。注意:加热要均匀,并等待温度稳定后再读数。
  3. 温度计算: 得到两点数据后,温度T与ADC读数N之间的关系可视为线性:T = A * N + B其中,斜率A = (T2 - T1) / (N2 - N1),截距B = T1 - A * N1。 在代码中,应使用浮点数或定点数进行这些计算。为了避免运行时进行浮点运算(在低功耗MCU上开销较大),通常将A和B预先计算好,并以缩��整数的形式存储。

    // 示例:假设在30.0°C时读数为850,在60.0°C时读数为650 // 计算斜率和截距(使用浮点) float N1 = 850.0, T1 = 30.0; float N2 = 650.0, T2 = 60.0; float A = (T2 - T1) / (N2 - N1); // (60-30)/(650-850) = 30/-200 = -0.15 float B = T1 - A * N1; // 30 - (-0.15)*850 = 30 + 127.5 = 157.5 // 最终公式:T = -0.15 * N + 157.5 // 可以将A和B转换为定点数,例如放大100倍:A_fixed = -15, B_fixed = 15750 // 计算时:T_centi = (A_fixed * N + B_fixed) / 100;
  4. 软件滤波: 温度传感器输出可能存在噪声,尤其是电源噪声。可以在软件中对连续多次的采样结果进行平均,例如取16次或32次的移动平均,能有效提高读数稳定性。

重要提示:温度传感器测量的是芯片内核的结温,而非环境温度。芯片自身功耗(CPU活动、外设工作)会产生热量,导致结温高于环境温度。在低功耗待机状态下,两者接近;在高负荷运行时,结温可能显著升高。在精确环境温度测量中,需要考虑这个因素。

4. ADC10_B中断系统深度解析与高效编程

中断是MCU实现高效、实时响应的核心机制。ADC10_B提供了一个高度集成的中断系统,将多个事件源合并到一个中断向量中,并通过ADC10IV寄存器进行高效管理。

4.1 六大中断源及其应用场景

ADC10_B共有六个中断标志,对应不同的事件:

  1. ADC10IFG0(转换完成中断):这是最常用的中断。当一次A/D转换完成,结果被装入ADC10MEM0寄存器后,此标志置位。如果你使能了该中断(ADC10IE0=1且总中断GIE=1),CPU将跳转到中断服务程序(ISR)读取数据。

  2. ADC10OVIFG(结果溢出中断):当一次转换完成,新的结果准备写入ADC10MEM0时,如果上一次的转换结果还未被读取(即ADC10IFG0仍为1),就会发生溢出,此标志置位。这通常意味着你的程序读取结果的速度跟不上ADC转换的速度,在高速连续采样模式下需要特别注意。

  3. ADC10TOVIFG(转换超时中断):当一次转换尚未完成,又收到了一个新的采样转换触发信号时,此标志置位。这通常是由于触发速率过快,超过了ADC的转换能力。

  4. ADC10HIIFG/ADC10LOIFG/ADC10INIFG(窗口比较器中断):这是ADC10_B的一个高级功能。你可以设置一个高阈值(ADC10HI)和一个低阈值(ADC10LO)。当转换结果高于高阈值时,ADC10HIIFG置位;低于低阈值时,ADC10LOIFG置位;在高低阈值之间时,ADC10INIFG置位。这个功能非常强大,可以用于实现硬件级的上下限报警,而无需CPU持续参与比较。例如,在电池电压监控中,设置电压过高和过低的阈值,一旦触发相应中断,CPU才被唤醒进行处理,极大节省了功耗。

4.2 中断向量生成器(ADC10IV)的妙用

多个中断源共享一个中断向量,如何区分是谁触发了中断?传统做法是在ISR开始处依次检查每个中断标志位(ADC10IFG寄存器),但这样效率低下。

ADC10_B引入了ADC10IV寄存器,它是一个“智能”的中断向量生成器。该寄存器存储了一个代表当前最高优先级待处理中断的编码值。读取这个寄存器有两个重要作用:第一,你可以直接得到这个编码值,用于判断中断源;第二,读取操作会自动清除该最高优先级中断的标志位(除了ADC10IFG0,它需要读取ADC10MEM0来清除)。

手册提供的汇编示例完美展示了如何利用ADC10IV实现高效的跳转表式中断处理:

INT_ADC10_B ADD &ADC10IV, PC ; PC = PC + ADC10IV的值,实现跳转 RETI ; Vector 0: 无中断 JMP ADOV ; Vector 2: ADC10OVIFG (溢出) JMP ADTOV ; Vector 4: ADC10TOVIFG (超时) JMP ADHI ; Vector 6: ADC10HIIFG (高于高阈值) JMP ADLO ; Vector 8: ADC10LOIFG (低于低阈值) JMP ADIN ; Vector 10: ADC10INIFG (在窗口内) ; ADC10IFG0 处理程序从这里开始,无需跳转 ADMEM MOV &ADC10MEM0, R5 ; 读取结果,同时清除ADC10IFG0标志 ... ; 处理数据 RETI ADOV ... ; 处理溢出错误 RETI ; ... 其他中断处理例程

在C语言中,我们通常用switch语句来实现同样的逻辑:

#pragma vector=ADC10_VECTOR __interrupt void ADC10_ISR(void) { switch(__even_in_range(ADC10IV, ADC10IV_ADC10IFG)) { case ADC10IV_NONE: break; // 无中断 case ADC10IV_ADC10OVIFG: // 溢出 // 处理溢出错误,例如重置状态 ADC10CTL0 &= ~ADC10ENC; // 先禁用ADC ADC10CTL0 |= ADC10ENC; // 再使能 break; case ADC10IV_ADC10TOVIFG: // 转换超时 // 通常意味着触发太快,需要调整触发间隔 break; case ADC10IV_ADC10HIIFG: // 高于高阈值 // 执行超限报警操作 P1OUT |= BIT0; // 例如,点亮LED报警 break; case ADC10IV_ADC10LOIFG: // 低于低阈值 // 执行欠限报警操作 P1OUT |= BIT1; break; case ADC10IV_ADC10INIFG: // 在窗口内 // 数值恢复正常范围的处理 P1OUT &= ~(BIT0 | BIT1); // 关闭报警LED break; case ADC10IV_ADC10IFG: // 转换完成 // 这是最常进入的分支 int adc_result = ADC10MEM0; // 读取结果,清除ADC10IFG0 // 进行数据处理,例如存入数组、计算实际电压/温度 g_adc_value = adc_result; __bic_SR_register_on_exit(LPM0_bits); // 退出低功耗模式 break; default: break; } }

使用__even_in_range这个编译器内置函数可以让编译器生成更高效的跳转代码。务必注意ADC10IFG0的清除方式与其他中断不同,它是通过读取ADC10MEM0来清除的,而不是通过ADC10IV

5. 关键寄存器配置详解与实战代码

理解了原理,最终都要落实到寄存器配置上。ADC10_B的寄存器不多,但每个位都至关重要。下面我以一个完整的“单通道单次转换,使用内部温度传感器,并使能转换完成中断”的实例,来拆解每个关键寄存器的配置。

5.1 控制寄存器(ADC10CTL0, ADC10CTL1, ADC10CTL2)配置解析

配置ADC10_B通常遵循一个固定顺序:先配置ADC10CTL1ADC10CTL2,再配置ADC10CTL0,最后使能转换。

第一步:配置ADC10CTL1 – 时钟与序列控制

ADC10CTL1 = ADC10SHP // 采样定时器源选择为采样定时器本身(常用) | ADC10SSEL_3 // 选择SMCLK作为时钟源(假设SMCLK=1MHz) | ADC10DIV_0; // 时钟不分频,ADC10CLK = SMCLK = 1MHz
  • ADC10SHP:通常设为1,使用内部采样定时器来控制采样时间,这样更精确。
  • ADC10SSELx:时钟源选择。对于需要低功耗的场合,可以选择ACLK(32kHz)。这里为了演示,选择SMCLK。
  • ADC10DIVx:分频系数。如果时钟源频率过高,需要分频以满足ADC内核要求。

第二步:配置ADC10CTL2 – 分辨率与参考缓冲

ADC10CTL2 = ADC10RES; // 选择10位分辨率
  • ADC10RES:选择10位模式以获得更高精度(结果范围0-1023)。如果对速度要求极高而对精度要求一般,可选8位模式(转换周期更短)。
  • ADC10SR:参考缓冲器速度控制。当采样率要求不高(<50ksps)时,可以置1以降低功耗。

第三步:配置ADC10CTL0 – 核心控制与启动这是最关键的寄存器。

ADC10CTL0 = ADC10SHT_3 // 采样保持时间:32个ADC10CLK周期(32µs @1MHz),满足温度传感器>30µs要求 | ADC10ON // 打开ADC10_B模块电源 | ADC10IE; // 使能ADC10IFG0中断 // 注意:此时ADC10ENC还是0,ADC未就绪
  • ADC10SHTx:如前所述,根据信号源阻抗和温度传感器要求设置。这里设32个周期。
  • ADC10ON:必须置1以开启ADC模块的模拟电路。
  • ADC10IE:这是ADC10IE寄存器的ADC10IE0位缩写,使能转换完成中断。

第四步:配置输入通道与参考电压(ADC10MCTL0)

ADC10MCTL0 = ADC10INCH_10 // 输入通道选择:10 = 内部温度传感器 | ADC10SREF_1; // 参考电压:VR+ = VREF+ (内部参考),VR- = AVSS
  • ADC10INCHx:选择通道。1010b(即10)是温度传感器。
  • ADC10SREFx:选择参考电压。使用内部参考电压(如1.5V)可以获得更稳定、更精确的基准。

第五步:使能转换并启动

ADC10CTL0 |= ADC10ENC; // 使能转换模块(此时配置被锁存,某些位不能再修改) ADC10CTL0 |= ADC10SC; // 开始采样和转换

这里有一个非常重要的顺序和细节:必须先设置ADC10ENC=1来“锁定”配置,然后才能通过设置ADC10SC=1来启动转换。在ADC10ENC=1期间,ADC10CTL0/1/2ADC10MCTL0的某些位是只读的,这是为了防止转换过程中配置被意外改变。如果需要修改配置,必须先清除ADC10ENC

5.2 窗口比较器寄存器(ADC10HI, ADC10LO)配置示例

假设我们要监控一个电源电压,正常范围是3.0V到3.6V,使用内部2.5V参考电压,10位分辨率。

  • 满量程数字值 = 1023 (2^10 -1)
  • 对应电压 = Vref = 2.5V
  • 因此,LSB = 2.5V / 1024 ≈ 2.441 mV

计算阈值:

  • 高阈值电压 3.6V 对应的数字值 = 3.6V / 2.5V * 1024 ≈ 1474.56,取整为1475。
  • 低阈值电压 3.0V 对应的数字值 = 3.0V / 2.5V * 1024 ≈ 1228.8,取整为1229。

配置代码:

// 设置窗口比较器阈值(右对齐,无符号格式) ADC10HI = 1475; // 高阈值 ADC10LO = 1229; // 低阈值 // 使能窗口比较器中断(假设我们只关心电压过高和过低) ADC10IE |= ADC10HIIE | ADC10LOIE; // 在ADC10MCTL0中配置对应的模拟输入通道(例如通道A0) ADC10MCTL0 = ADC10INCH_0 | ADC10SREF_1;

这样,当A0通道的电压超过3.6V或低于3.0V时,就会触发相应的中断,CPU可以立即响应,而不需要不断进行软件比较。

6. PCB布局、接地与噪声抑制的硬件实战经验

ADC的性能不仅取决于软件配置,硬件设计至少占一半的重要性。手册中专门强调了接地和噪声考虑,这些都是血泪教训总结出来的。

6.1 地环路与星型接地

地环路是精度杀手。当ADC的返回电流流经与其他模拟或数字电路共享的路径时,就会形成地环路。这段公共路径的阻抗会产生一个微小的电压降(V_noise = I_return * R_path),这个噪声电压会叠加到ADC的参考地或输入信号上。

解决方案是采用星型接地或单点接地。具体做法:

  1. 分割模拟地和数字地:在PCB布局上,将模拟部分(ADC、模拟传感器、参考电压源、运放)和数字部分(MCU数字IO、时钟、通信接口)的地平面在物理上分开。
  2. 单点连接:在一点,通常是ADC芯片的AGND引脚下方,通过一个0欧姆电阻或磁珠将模拟地和数字地连接起来。这个连接点必须是整个系统接地的唯一交汇点,所有模拟和数字部分的电流最终都通过这一点返回电源。
  3. ADC的电源去耦:在AVCC和AVSS(模拟电源和地)引脚附近,尽可能靠近引脚放置一个10µF的钽电容或电解电容(用于低频滤波)并联一个100nF的陶瓷电容(用于高频滤波)。DVCC和DVSS(数字电源和地)同样需要。

6.2 电源噪声与信号走线

开关电源和数字电路的快速开关会在电源线上产生高频纹波和尖峰噪声,这些噪声会通过电源引脚耦合进ADC,污染转换结果。

  • 使用LDO为模拟部分供电:如果系统有开关电源,建议使用一个独立的低压差线性稳压器(LDO)为模拟电路(包括ADC和传感器)供电。LDO的噪声远低于开关电源。
  • 模拟信号走线远离噪声源:ADC的输入信号线应远离时钟线、高频数字信号线(如PWM)、电源线。如果必须交叉,应垂直交叉以减小耦合面积。
  • 使用屏蔽或双绞线:对于从外部传感器引来的长线,使用屏蔽线或将信号线与地线双绞,可以有效抑制空间电磁干扰。
  • 在信号输入端添加滤波:对于低频信号(如温度、压力),可以在ADC输入引脚前添加一个简单的RC低通滤波器(例如1kΩ电阻和100nF电容到地),可以滤除高频噪声。但要注意,滤波器的电阻会与ADC的输入阻抗形成分压,并影响采样时间,需要重新计算ADC10SHTx

一个实测技巧:在调试ADC精度问题时,如果怀疑是电源噪声,可以用示波器的带宽限制功能(通常为20MHz)观察AVCC引脚和信号输入引脚。如果看到高频毛刺,基本可以确定是布局或去耦问题。此时,在关键引脚上临时焊接一个贴近引脚的100nF电容,往往能立即看到改善。

7. 常见问题排查与调试技巧实录

即使按照手册配置,在实际项目中还是会遇到各种奇怪的问题。下面是我总结的几个典型问题及其排查思路。

7.1 问题排查速查表

问题现象可能原因排查步骤与解决方案
ADC读数始终为0或接近01. 输入通道选择错误。
2. 模拟输入引脚未配置为模拟功能(数字输入缓冲器未关闭)。
3. 参考电压配置错误(如选择了未启用的内部参考)。
4. ADC10ON或ADC10ENC未使能。
1. 检查ADC10INCHx位。
2. 对于MSP430,模拟输入引脚需要将方向寄存器设为输入,并且通常需要将功能选择寄存器设为模拟IO,以禁用数字输入缓冲器(具体请查芯片数据表)。
3. 检查ADC10SREFx,如果使用内部参考(VREF),需要确保REF模块已打开并稳定(例如,设置`REFCTL0
ADC读数跳动大,噪声严重1. 采样时间不足,信号未稳定。
2. 电源噪声或地环路干扰。
3. 信号源阻抗过高。
4. 未使用参考电压缓冲器(ADC10SR设置不当)。
1. 增大ADC10SHTx值,特别是对于高阻抗源(如温度传感器)。
2. 检查硬件布局,确保星型接地和充分去耦。用示波器查看AVCC和信号线。
3. 对于高阻抗信号,建议使用电压跟随器(运放)进行缓冲。
4. 在低采样率下,设置ADC10SR=1以降低缓冲器噪声。
温度传感器读数不准1. 采样时间小于30µs。
2. 未进行校准。
3. 参考电压不稳定。
4. 芯片自发热影响。
1. 确认ADC10SHTx设置满足>30µs要求。
2. 实施两点校准法,获取芯片特定的斜率和偏移。
3. 使用内部精密参考电压(如1.5V)。
4. 在低功耗模式下测量,或测量后计算时考虑功耗带来的温升��
中断无法进入1. 总中断未使能(GIE)。
2. 特定中断使能位未设置(如ADC10IE0)。
3. 中断标志未正确清除。
4. 中断向量函数未正确定义或链接。
1. 在main函数中调用__enable_interrupt()或设置SR寄存器。
2. 检查ADC10IE寄存器相应位。
3.牢记ADC10IFG0通过读ADC10MEM0清除;其他标志通过读ADC10IV清除。检查ISR中是否有对应操作。
4. 检查编译器中断语法(如#pragma vector=...)是否正确,函数名是否与启动文件匹配。
窗口比较器不触发中断1. 阈值寄存器ADC10HI/ADC10LO设置错误(对齐方式)。
2. 窗口比较器中断未使能(ADC10HIIE等)。
3. 结果数据格式与阈值格式不匹配(ADC10DF位)。
1. 确认ADC10DF位。如果为0(默认无符号右对齐),阈值应右对齐(高6位为0)。如果为1(有符号左对齐),阈值需左对齐。
2. 检查ADC10IE寄存器中对应的使能位。
3. 确保ADC10DF位在设置阈值和读取结果时保持一致。

7.2 调试技巧与心得

  • 从简单到复杂:调试ADC时,先不要用中断和复杂模式。配置为单次转换,用查询方式(轮询ADC10IFG0)读取一个已知电压(如分压后的VCC),看结果是否合理。这是验证ADC基本功能是否正常的最快方法。
  • 善用寄存器查看:在调试器中,实时查看ADC10_B相关的所有寄存器值,确保与你代码中设置的一致。特别注意那些“仅在ADC10ENC=0时可写”的位,在转换过程中尝试修改它们是不会成功的。
  • 计算与实际结合:对于采样时间、转换时间等参数,不要只依赖感觉。根据时钟频率和寄存器设置,实际计算一下时间参数。例如,一次10位转换需要13个ADC10CLK周期(1个采样+12个转换),如果ADC10CLK是1MHz,那么一次转换至少需要13µs,这意味着理论最大采样率约为76.9ksps。如果你的定时器触发间隔小于13µs,就一定会触发ADC10TOVIFG(转换超时)中断。
  • 理解“忙”状态ADC10BUSY位在采样和转换期间为1。在连续转换模式下,它可能一直为1。在单次转换模式下,你可以查询此位变为0来确认转换结束,作为轮询的另一种方式。