资讯中心

【凌鸥LKS32】基础篇(七)·软件触发ADC采集电位器电压

📅 2026/8/26 17:46:45
【凌鸥LKS32】基础篇(七)·软件触发ADC采集电位器电压
目录1. 简介2. 逐次逼近型ADCADC08093. 功能框图LKS324. ADC基本结构4.1 量词含义约定4.2 触发方式4.3 ADC 通道选择4.4 中断配置4.5 ADC 输出数制4.6 ADC 量程4.7 ADC 阈值监测5. 库函数5.1 ADC_TypeDef5.2 ADC_InitTypeDef5.3 API库函数6. 软件触发代码编写6.1 引脚初始化6.2 ADC初始化6.3 主函数部分1. 简介ADC全称是Analog-to-Digital Converter模拟-数字转换器一般我们把模拟信号(Analog signal) 用A来进行简写数字信号(digital signal) 用D来表示。主要用于将连续传输的模拟信号转换为数字信号便于数字系统如中央处理器CPU、微控制器MCU等对传输信息进行快速处理和分析。模拟信号是指用连续变化的物理量所表达的信息如温度、湿度、压力、电压、电流等。ADC模块所采集的模拟信号是连续变化的电压或电流信号其数值在一定范围内连续变化如下所示在单片机的使用中我们可以通过ADC的转换将引脚上连续变化的模拟电压转换为内存中存储的数字变量建立模拟电路到数字电路的桥梁。ADC采样的实现方式主要有两种外接采样芯片和控制核心内部的采样模块。以前的一些芯片是外挂ADC芯片不过现在许多MCU和DSP内部集成了ADC模块。对于LKS32MC07x 系列芯片其内部集成了 2 个 12bit SAR-ADC 转换核心14 个模拟 IO 输入信号、4 个 OPA输出、2 个 DAC 输出、温度传感器输出、内部电源 AVDD 均可作为 ADC 的被采样信号。不过我们还是来了解一下外挂芯片的原理方便理解。2. 逐次逼近型ADCADC0809我们先来了解一下ADC0809的工作原理。首先是通道选择开关通过通道选择开关选择IN0~IN7其中的一路输入到这个点进行转换对于0809只有8路选然后是地址锁存和译码这里你想要选择哪一路需要将通道号放到ADDA、ADDB、ADDC这三个脚上然后通过ALE给出锁存信号对应的通道选择开关就会自动拨好了比较器是一个电压比较器他可以判断两个输入信号电压的大小关系其中通道选择开关输入的是待测的电压另一端是DAC数模转换器的电压这里待测电压是未知的但是DAC所出的电压是我们通过数模转换来的其编码是已知的我们通过比较器进行比较当待测电压大于DAC所示电压我们就调大DAC的值如果待测电压小于DAC所示电压我们就调小DAC的值直到待测电压等于DAC所示电压这样DAC的输入数据就是待测电压的数据我们就可以知道待测电压的编码类似于二分法。得出待测电压的编码通过三态锁存缓冲器进行输出8位就有8根线12位就有12根3. 功能框图LKS32每个 ADC 接口包括 16 个数据寄存器ADC 16 次采样各个通道模拟量对应的数字量以及若干控制寄存器14 个常规触发采样寄存器2 个空闲采样触发寄存器。可以同一时刻进行 2 个通道的采样拆分了解一下首先是输入部分其中最左侧代表多路输入选择器其中OPA0/1/2/34 路片内运算放大器输出ADC Channels14 路外部模拟 IO 通道Temperature Sensor芯片内置温度传感器AVDD模拟电源内部采样S/H代表Sample/Hold采样/保持。在采集阶段对外部电压采样电容充电ADC 转换阶段保持电压稳定保证转换期间输入电压不变。SAR‑ADC 内核12 位逐次逼近 ADC把模拟电压转换成数字量输出。ADC 的启动触发来源Hardware trigger 硬件触发来自定时器 UTimer/MCPWM 输出 T0/T1/T2/T3。定时器事件自动启动 ADC 转换常用于电机控制PWM 中点同步采样不需要 CPU 软件干预。Software trigger 软件触发寄存器写位软件手动启动一次 ADC 转换。Sampling Control logic 采样控制状态机Sample State Control采样状态机管理采样、保持、转换时序Trigger counter触发计数器统计触发事件Channel Select通道选择输出信号给左侧模拟多路开关选哪一路模拟输入对于最上面几个操作主要为了稳定最终采集数据-16h8000(0)偏移补偿-ADC_DC直流偏移校准修正 ADC 零点误差ADC_AMC增益校准修正 ADC 增益误差乘法器、饱和溢出处理处理采样结果溢出 / 下溢防止数值越界。经过偏移、增益校准之后才输出最终采样数字值。最右侧部分是数据寄存器组ADC_IDAT0~IDAT1中间数据缓存ADC_DAT0 ~ ADC_DAT13 共 14 个加上 IDAT 合计 16 个数据寄存器对应知识点每个 ADC 有 16 个数据寄存器保存多次采样结果。ADC_IF转换完成中断标志位。左侧是存放全部 ADC 配置寄存器ADC_CHN0 ...通道号配置寄存器选择要采样的模拟通道ADC_TRIG触发源配置选择软件触发 / 哪个定时器硬件触发ADC_CFGADC 功能配置采样时间、使能、模式等ADC_CHNT通道计数配置一轮要采集多少个通道ADC_SWT软件触发寄存器写该寄存器软件启动 ADCAMC/DC增益、直流偏移校准参数寄存器。右侧是中断产生逻辑转换完成后若中断使能打开就向 NVIC 申请中断通知 CPU 读取采样结果。ADC_IE[n]中断使能位ADC_IF[n]中断标志位与门逻辑标志位 使能位 → 输出IRQ中断信号送给 NVIC。完整的工作流程CPU 通过总线配置adc_reg寄存器设置采样通道列表、选择触发源定时器硬件触发 / 软件触发、开启中断。触发事件到来硬件UTimer/MCPWM 定时器事件或者软件写ADC_SWT软件触发位。Sampling Control logic状态机工作输出Channel Select选通一路模拟输入控制 S/H 采样保持电路。SAR‑ADC 完成模数转换数字结果做 DC 偏移、AMC 增益校准、饱和处理。转换结果存入ADC_DATx数据寄存器。置ADC_IF中断标志。如果中断使能位打开产生 IRQ 信号给到 NVIC进入 ADC 中断服务函数。CPU/DMA 通过 BUS 读取ADC_DATx拿到采样值软件写对应标志位清除中断标志。4. ADC基本结构4.1 量词含义约定1 次采样完成对应的一次模拟信号量到数字信号量的采样转换并存储至 ADC_DATx 寄存器1 段采样可能包含 1 次或若干次采样若干次采样可以是相同的模拟信号也可以是不同的模拟信号。采样开始通常由MCPWM、TIMER 或软件进行触发一个触发信号完成一段采样采样完成后产生相应的段采样完成中断。名词定义关键要点次采样一次模拟→数字转换结果存入 1 个ADC_DATxADC 最小执行单元N 次采样结果存ADC_DAT[N]段采样1 个触发信号启动的一组采样任务一段内可 1 次 / 多次次采样可同通道重复采样整段全部次采样做完才产生段完成中断4.2 触发方式ADC 触发分为常规触发(NT: Normal Trigger)和空闲触发(IT: Idle Trigger)两种触发。常规触发比空闲触发有更高优先级。如果 ADC 正在进行常规采样转换此时发生了空闲触发则 ADC 会继续完成常规触发的通道采样转换完成后再进行空闲触发采样转换如果 ADC 正在进行空闲采样转换此时发生了常规触发则常规触发会打断空闲采样转换等常规触发采样完成后再进行空闲触发。NT 常规触发 Normal Trigger高优先级用于业务必需采样电机电流、传感器信号等实时任务。 对应硬件14 个常规触发采样寄存器由 MCPWM/UTimer 硬件触发或者软件触发。IT 空闲触发 Idle Trigger低优先级后台非紧急采样芯片温度、AVDD 电源电压等不要求严格实时。 对应硬件2 个空闲采样触发寄存器一般在系统空闲的时候执行。触发类型优先级寄存器资源行为特性适用场景NT 常规触发高14 个常规采样寄存器可抢占空闲触发空闲采样运行时NT 到来立刻打断空闲先执行 NT之后恢复空闲NT 运行时 IT 到来IT 排队等待电机电流、实时传感器IT 空闲触发低2 个空闲采样寄存器不能抢占常规触发仅系统空闲时执行后台监测温度、AVDD 电压触发方式支持单段触发和两段触发可以设置采样触发事件发生次数从而实现间隔触发可以软件触发每段采样触发完成可产生对应中断标志如果使能中断请求则会向 NVIC 产生中断服务请求触发指示信号可以通过 GPIO 送出用于调试支持空闲触发采样其手册配置寄存器如下对于常规触发部分我们细化一下软件触发软件触发向 ADC_SWT 写入 0x5AA5 可以产生一次软件触发信号。UTIME 触发硬件触发ADC 的触发来源为 UTimer 的比较事件ADC 四段触发采样事件对应 UTimer_T0/UTimer_T1/UTimer_T2/UTimer_T3其依次对应 Timer2 通道 0/1、Timer3 通道 0/1 的比较事件。MCPWM 触发硬件触发MCPWM 可以提供 ADC 采样控制。当计数器计数到 MCPWM_TMR0/MCPWM_TMR1/MCPWM_TMR2/MCPWM_TMR3 时可产生定时事件 MCPWM_T0/MCPWM_T1/MCPWM_T2/MCPWM_T3触发 ADC 采样。该触发信号可通过 ADC_TRIGGER 输出到 GPIO便于调试之用。ADC 触发信号在芯片内部为一个 ADC 时钟周期的窄脉冲。每发生一次 ADC 触发ADC_TRIGGER 信号翻转一次以便于输出捕捉。触发源触发方式关键说明软件触发写寄存器ADC_SWT 0x5AA5写魔法字产生 1 次触发启动一段常规采样UTIMER 硬件触发定时器比较事件UTimer_T0~T3 依次对应Timer2_CH0、Timer2_CH1、Timer3_CH0、Timer3_CH1 比较事件MCPWM 硬件触发PWM 计到 MCPWM_TMR0‑3 产生事件1 个 ADC 时钟窄脉冲可输出 GPIOADC_TRIGGER调试每触发一次引脚电平翻转需要注意ADC 无论被配置为几段转换模式每一段都需要一个触发事件才能进行开始采样转换否则 ADC 处于等待状态。单段触发模式可以是一次硬件事件即触发也可以是达到一定次数的硬件事件才触发采样4 个 MCPWM/UTimer 触发事件均可触发或参与计数但两段触发和四段触发4 个 MCPWM/UTimer 触发事件只能按顺序触发 ADC 采样。工作模式触发规则说明单段模式一次硬件事件直接触发支持累计 N 次硬件事件后才触发4 路 MCPWM/UTimer 均可参与计数两段模式硬件触发必须严格按顺序触发各段不允许乱序每一段需要收到对应触发才开始采样无触发则等待四段模式硬件触发必须严格按顺序 T0→T1→T2→T3来一次触发只执行对应一段不会自动跑完全部 4 段无触发 ADC 处于等待无论几段模式每一段都必须收到对应触发事件才会开始采样转换否则 ADC 等待。4.3 ADC 通道选择每个 ADC 模块有 5 个通道信号来源寄存器控制采样序列 0~15 的信号选择。寄存器管控的次采样序号归属类型ADC_CHN0第 03 次采样常规 NTADC_CHN1第 47 次采样常规 NTADC_CHN2第 811 次采样常规 NTADC_CHN3第 1213 次采样常规 NTADC_ICHN空闲段第 01 次采样空闲 IT每次采样通道值选择范围都是 0~15对应通道 0~15 也就是可以对某一个通道进行多次采样。每一个采样对应一个结果寄存器转换结束后可以直接到对应结果寄存器中获取到 ADC 采样结果。4.4 中断配置ADC 一共有七种中断序号中断名称含义说明1第一段采样完成中断第 1 段采样全部次采样执行完毕段完成中断2第二段采样完成中断第 2 段采样全部次采样执行完毕段完成中断3第三段采样完成中断第 3 段采样全部次采样执行完毕段完成中断4第四段采样完成中断第 4 段采样全部次采样执行完毕段完成中断5软件触发发生在非空闲状态中断ADC正在工作非空闲时又来了软件触发此时触发无法执行产生报错中断6硬件触发发生在非空闲状态中断ADC正在工作非空闲时又来了硬件触发触发无法执行产生报错中断7ADC0_DAT0 超阈值中断ADC0 的 DAT0 采样结果高于 / 低于设定阈值触发告警中断监控模拟信号其寄存器配置如下4.5 ADC 输出数制ADC 输出数据为 12bit 补码输入信号 0 对应 12’b0000_0000_0000。 ADC 有两种量程设置 3.6V 和 7.2V。 以 3.6V 量程为例输入电压12bit 补码十进制‑3.6V12b1000_0000_0000‑20480V12b0000_0000_000003.6V12b0111_1111_11112047ADC 转换后的 12bit 补码需要符号扩展存入 16bit 的ADC_DAT寄存器支持左对齐、右对齐配置。左对齐把 12bit 数据向 16bit 寄存器高位靠齐低位补 0这样符号位在 16bit 的最高 bit做数值运算时直接对 16 位数右移 4 位即可还原原始 12bit 补码12bit: 1000 0000 1101 左对齐: 1000 0000 1101 0000 低4位补0右对齐2bit 向 16bit 寄存器低位靠齐高位填充符号位符号扩展如果原 12bit 最高位是 1负数所以高 4 位全部填 1如果原始是正数符号位 0则高 4 位全部填 0。12bit: 1000 0000 1101 右对齐: 1111 1000 0000 1101 高4位复制符号位14.6 ADC 量程ADC 在 2.4V 的默认基准电压配置下有两种量程设置3.6V 和 7.2V。ADC 量程基准电压可承受输入幅度适用场景3.6V2.4V±3.6V运放 OPA 输出信号电机电流采样推荐7.2V2.4V±5V外部大幅度差分信号输入注意7.2V 量程虽然叫 7.2V 量程但芯片实际允许最大输入是±5V不要输入超过 ±5V损坏芯片。4.7 ADC 阈值监测ADC 阈值监测又叫做模拟看门狗硬件实时监控 ADC 采样结果不需要 CPU 不停轮询读取寄存器一旦采样值超出设定上下边界硬件直接置超限中断标志。每个 ADC 模块拥有1 组阈值监测电路同时配置上阈值高门限12bit 有符号补码下阈值低门限12bit 有符号补码阈值本身是 12 位有符号补码和 ADC 原始转换数据位宽一致。比较逻辑不受左 / 右对齐影响无论配置左对齐还是右对齐硬件自动提取有效的 12bit 采样数值做对比软件不用因为对齐方式修改阈值参数。阈值是 12bit 有符号数左对齐模式ADCx_DATx[15:4]高 12 位真正的 12bit 采样补码拿出来和阈值比较忽略低 4 位填充 0右对齐模式ADCx_DATx[11:0]低 12 位符号扩展后的有效采样数据拿出来和阈值比较比较触发时机ADC 完成一次次采样经过增益、偏移校正结果写入ADCx_DATx寄存器的瞬间硬件自动做阈值比较采样结果 上阈值 → 置阈值超限中断标志采样结果 下阈值 → 置阈值超限中断标志结果介于上下阈值之间不动作。5. 库函数都有注释应该还是很容易理解的。5.1 ADC_TypeDef这里主要是寄存器地址映射结构体编译器会根据结构体成员顺序、偏移对应芯片实际寄存器地址ADC0/ADC1是外设基地址强制转换的结构体指针typedef struct { __IO uint32_t DAT0; /** 偏移地址: 0x00 ADCx 第 0 次常规采样数据*/ __IO uint32_t DAT1; /** 偏移地址: 0x04 ADCx 第 1 次常规采样数据*/ __IO uint32_t DAT2; /** 偏移地址: 0x08 ADCx 第 2 次常规采样数据*/ __IO uint32_t DAT3; /** 偏移地址: 0x0C ADCx 第 3 次常规采样数据*/ /** */ __IO uint32_t DAT4; /** 偏移地址: 0x10 ADCx 第 4 次常规采样数据*/ __IO uint32_t DAT5; /** 偏移地址: 0x14 ADCx 第 5 次常规采样数据*/ __IO uint32_t DAT6; /** 偏移地址: 0x18 ADCx 第 6 次常规采样数据*/ __IO uint32_t DAT7; /** 偏移地址: 0x1C ADCx 第 7 次常规采样数据*/ /** */ __IO uint32_t DAT8; /** 偏移地址: 0x20 ADCx 第 8 次常规采样数据*/ __IO uint32_t DAT9; /** 偏移地址: 0x24 ADCx 第 9 次常规采样数据*/ __IO uint32_t DAT10; /** 偏移地址: 0x28 ADCx 第 10 次常规采样数据 */ __IO uint32_t DAT11; /** 偏移地址: 0x2C ADCx 第 11 次常规采样数据 */ __IO uint32_t DAT12; /** 偏移地址: 0x30 ADCx 第 12 次常规采样数据*/ __IO uint32_t DAT13; /** 偏移地址: 0x34 ADCx 第 13 次常规采样数据 */ __IO uint32_t IDAT0; /** 偏移地址: 0x38 ADCx 第 0 次空闲采样数据*/ __IO uint32_t IDAT1; /** 偏移地址: 0x3C ADCx 第 1 次空闲采样数据*/ __IO uint32_t ICHN; /** 偏移地址: 0x40 ADCx 空闲采样通道配置*/ __IO uint32_t null; /** 偏移地址: 0x44 地址对齐无意义*/ __IO uint32_t null1; /** 偏移地址: 0x48 地址对齐无意义*/ __IO uint32_t null2; /** 偏移地址: 0x4C 地址对齐无意义*/ __IO uint32_t CHN0; /** 偏移地址: 0x50 ADCx 第 0~ 3 次常规采样输入信号选择 Signal 0 Signal 0 Signal 0 Signal 0 Signal 0 Signal 0*/ __IO uint32_t CHN1; /** 偏移地址: 0x54 ADCx 第 4~ 7 次常规采样输入信号选择*/ __IO uint32_t CHN2; /** 偏移地址: 0x58 ADCx 第 8~11 次常规采样输入信号选择*/ __IO uint32_t CHN3; /** 偏移地址: 0x5C ADCx 第 12~15 次常规采样输入信号选择*/ __IO uint32_t CHNT; /** 偏移地址: 0x60 ADCx 各种触发模式下采样次数*/ __IO uint32_t GAIN; /** 偏移地址: 0x64 ADCx 增益选择*/ __IO uint32_t null3; /** 偏移地址: 0x68 地址对齐无意义*/ __IO uint32_t null4; /** 偏移地址: 0x6C 地址对齐无意义*/ __IO uint32_t null5; /** 偏移地址: 0x70 地址对齐无意义*/ __IO uint32_t CFG; /** 偏移地址: 0x74 ADCx 模式配置*/ __IO uint32_t TRIG; /** 偏移地址: 0x78 ADCx 采样触发配置*/ __IO uint32_t SWT; /** 偏移地址: 0x7C ADCx 软件触发*/ __IO uint32_t DC0; /** 偏移地址: 0x80 ADCx 增益为 0 时 DC offset*/ __IO uint32_t AMC0; /** 偏移地址: 0x84 ADCx 增益为 0 时增益校正系数*/ __IO uint32_t DC1; /** 偏移地址: 0x88 ADCx 增益为 1 时 DC offset*/ __IO uint32_t AMC1; /** 偏移地址: 0x8C ADCx 增益为 1 时增益校正系数*/ __IO uint32_t IE; /** 偏移地址: 0x90 ADCx 中断使能*/ __IO uint32_t IF; /** 偏移地址: 0x94 ADCx 中断标志*/ __IO uint32_t null6; /** 偏移地址: 0x98 地址对齐无意义*/ __IO uint32_t null7; /** 偏移地址: 0x9C 地址对齐无意义*/ __IO uint32_t null8; /** 偏移地址: 0xA0 地址对齐无意义*/ __IO uint32_t null9; /** 偏移地址: 0xA4 地址对齐无意义*/ __IO uint32_t null10; /** 偏移地址: 0xA8 地址对齐无意义*/ __IO uint32_t null11; /** 偏移地址: 0xAC 地址对齐无意义*/ __IO uint32_t null12; /** 偏移地址: 0xB0 地址对齐无意义*/ __IO uint32_t null13; /** 偏移地址: 0xB4 地址对齐无意义*/ __IO uint32_t null14; /** 偏移地址: 0xB8 地址对齐无意义*/ __IO uint32_t null15; /** 偏移地址: 0xBC 地址对齐无意义*/ __IO uint32_t null16; /** 偏移地址: 0xCC 地址对齐无意义*/ __IO uint32_t LTH; /** 偏移地址: 0xC4 ADCx 数据低阈值*/ __IO uint32_t HTH; /** 偏移地址: 0xC8 ADCx 数据高阈值*/ __IO uint32_t GEN; /** 偏移地址: 0xCC ADCx 阈值监测使能*/ } ADC_TypeDef;5.2 ADC_InitTypeDef始化结构体调用ADC_Init()时把这里成员写入硬件寄存器集中配置 ADC 参数typedef struct { u16 IE; /** 中断使能*/ u16 RE; /** DMA请求使能*/ u16 NSMP; /** 两段采样使能*/ u16 DATA_ALIGN; /** DAT右对齐使能*/ u16 CSMP; /** 连续采样使能*/ u16 TCNT; /** 触发一次采样所需的事件数*/ u16 TROVS; /** 手动触发过采样使能开启后一次采样需要多次触发*/ u16 OVSR; /** 过采样率*/ u16 TRIG; /** 触发信号*/ u16 S1; /** 第一段常规采样次数*/ u16 S2; /** 第二段常规采样次数*/ u16 IS1; /** 空闲采样次数*/ u16 GAIN; /** 低增益7.2V量程使能*/ u16 LTH; /** ADC 模拟看门狗 0 下阈值*/ u16 HTH; /** ADC 模拟看门狗 0 上阈值*/ u16 GEN; /** ADC 模拟看门狗 0 对应使能位*/ } ADC_InitTypeDef;5.3 API库函数函数原型功能简述注意事项ADC_Init(ADC_TypeDef *ADCx, ADC_InitTypeDef *ADC_InitStruct)根据结构体配置初始化 ADC 外设先结构体初始化再修改参数再调用本函数ADC_StructInit(ADC_InitTypeDef *ADC_InitStruct)结构体填充默认参数必须最先调用避免随机垃圾值ADC_GetIRQFlag(ADC_TypeDef *ADCx, uint16_t INT_flag)读取中断标志位中断服务函数内判断中断事件ADC_ClearIRQFlag(ADC_TypeDef *ADCx, uint16_t INT_flag)清除中断标志必须软件清除否则重复进中断ADC_CHN_GAIN_CFG(ADC_TypeDef *ADCx, CHNx CHNum, u8 nChannel, ADC_GAINx GAIN3V6_or_7V2)配置某一次采样通道号、ADC 量程每一次次采样可独立选择量程s16 ADC_GetConversionValue(ADC_TypeDef *ADCx, DATx DATNum)读取 DATx 采样结果返回s16有符号存在负数ADC_SoftTrgEN(ADC_TypeDef *ADCx, FuncState state)开启 / 关闭软件触发功能使能后才可以写 ADC_SWT 软件触发6. 软件触发代码编写我们从上面了解到三种触发方式软件触发、UTIME 触发和 MCPWM 触发。这里先用软件触发。6.1 引脚初始化我想要做的是读取电位器电压值的变化这里初始化引脚P0.5也就是通道9可以查看数据手册GPIO_InitStruct.GPIO_Mode GPIO_Mode_ANA; GPIO_InitStruct.GPIO_Pin GPIO_Pin_5; GPIO_InitStruct.GPIO_PuPd DISABLE; GPIO_Init(GPIO0, GPIO_InitStruct);6.2 ADC初始化初始化代码非常简单把我们上方给出的初始化结构体全部写下来这里只初始化了一次常规采样用于软件触发采样void ADC0_init(void) { ADC_InitTypeDef ADC_InitStructure; ADC_StructInit(ADC_InitStructure); ADC_InitStructure.IE 0; //中断使能 ADC_InitStructure.RE 0; //DMA请求使能 ADC_InitStructure.NSMP DISABLE; //两段采样使能 ADC_InitStructure.DATA_ALIGN DISABLE; //DAT右对齐使能 ADC_InitStructure.CSMP DISABLE; //连续采样使能 ADC_InitStructure.TCNT 0; //触发一次采样所需的事件数 ADC_InitStructure.TROVS DISABLE; //手动触发过采样使能开启后一次采样需要多次触发 ADC_InitStructure.OVSR 0; //过采样率 ADC_InitStructure.TRIG 0; //触发信号 ADC_InitStructure.S1 1; //第一段常规采样次数 ADC_InitStructure.S2 0; //第二段常规采样次数 ADC_InitStructure.IS1 0; //空闲采样次数 ADC_InitStructure.LTH 0; //ADC 模拟看门狗 0 下阈值 ADC_InitStructure.HTH 0; //ADC 模拟看门狗 0 上阈值 ADC_InitStructure.GEN 0; //ADC 模拟看门狗 0 对应使能位 ADC_InitStructure.GAIN 0; //低增益7.2V量程使能 ADC_Init(ADC0, ADC_InitStructure); ADC_ClearIRQFlag(ADC0, ADC_ALL_IF); //清除所有中断标志位 ADC_CHN_GAIN_CFG(ADC0, CHN0, ADC_CHANNEL_9, ADC_GAIN3V6);//配置ADC通道9的增益为3.6V量程 }然后初始化通道9电压。6.3 主函数部分首先是采样触发部分我们实验软件触发采样更具手册需要向SWT发送0x5AA5然后轮询等待采样完成清楚相关中断标志位ADC0-SWT 0x5AA5; // 写0x5AA5软件触发ADC0执行一次采样转换 // 轮询等待SF1第一段ADC采样转换完成等待转换完成标志位置1 while((ADC0-IF ADC_SF1_IF) 0); ADC0-IF ADC_SF1_IF; // 软件写1清除ADC转换完成中断标志位之后调用ADC_GetConversionValue()函数读取ADC采集值注意此时的值是左移四位的结果要想得到实际值需要向右移四位adc_raw ADC_GetConversionValue(ADC0, DAT0); adc_val (u16)(adc_raw 4);之后将所得的实际值根据公式转换成电压在OLED屏幕上显示出来float v_srn (float)adc_val * 3.6f / 2048.0f; voltage v_srn * 3.0f / 2.0f; OLED_ShowNum(1, 1,adc_val, 6); OLED_ShowNum(2, 1,adc_raw, 6); uint16_t v_int (uint16_t)voltage; uint16_t v_dec (uint16_t)((voltage - v_int) * 100); OLED_ShowNum(3, 1, v_int, 2); OLED_ShowString(3,3,.); OLED_ShowNum(3,4, v_dec, 2);也可以根据所得的值进行一些其他判断例如开关LEDif(adc_val 1500) { LED1_ON; } else { LED1_OFF; } if(adc_val 1000) { LED2_ON; } else { LED2_OFF; } if(adc_val 500) { LED3_ON; } else { LED3_OFF; } SoftDelay(0x80000);此时完整主函数代码#include lks32mc07x_lib.h #include hardware_init.h #include led.h #include key.h #include delay.h #include OLED.h s16 adc_raw; // ADC原始采样寄存器值LKS32 ADC左对齐16位 u16 adc_val; // 转换后12位ADC有效值 0~4095 float voltage; // 最终换算得到的实际输入电压 int main(void) { Hardware_init(); // 系统硬件初始化GPIO、ADC、OLED、按键、LED等外设 while(1) { ADC0-SWT 0x5AA5; // 写0x5AA5软件触发ADC0执行一次采样转换 // 轮询等待SF1第一段ADC采样转换完成等待转换完成标志位置1 while((ADC0-IF ADC_SF1_IF) 0); ADC0-IF ADC_SF1_IF; // 软件写1清除ADC转换完成中断标志位 adc_raw ADC_GetConversionValue(ADC0, DAT0); // 读取DAT0通道原始ADC寄存器数据 adc_val (u16)(adc_raw 4); // 左对齐数据右移4位得到12位有效ADC值(0~4095) // 计算采样点电压参考电压3.6V12位ADC满量程2048注意这里是单极性半量程 float v_srn (float)adc_val * 3.6f / 2048.0f; voltage v_srn * 3.0f / 2.0f; // 硬件分压补偿还原电位器实际输入电压 OLED_ShowNum(1, 1,adc_val, 6); // OLED第1行第1列打印12位ADC有效值占6位 OLED_ShowNum(2, 1,adc_raw, 6); // OLED第2行第1列打印ADC原始寄存器值占6位 // 将浮点数电压拆分为整数部分、小数后两位OLED不支持直接打印float uint16_t v_int (uint16_t)voltage; // 电压整数部分 uint16_t v_dec (uint16_t)((voltage - v_int) * 100); // 电压小数点后2位 OLED_ShowNum(3, 1, v_int, 2); // 打印电压整数 OLED_ShowString(3,3,.); // 打印小数点 OLED_ShowNum(3,4, v_dec, 2); // 打印电压小数部分 // ADC阈值判断ADC数值大于1500点亮LED1 if(adc_val 1500) { LED1_ON; } else { LED1_OFF; } // ADC数值大于1000点亮LED2 if(adc_val 1000) { LED2_ON; } else { LED2_OFF; } // ADC数值大于500点亮LED3 if(adc_val 500) { LED3_ON; } else { LED3_OFF; } SoftDelay(0x80000); // 软件延时降低采样刷新速度防止OLED刷屏过快 } }烧录可以看到电压正常采集可以扭动电位器旋钮看一下效果完整工程凌鸥LKS32MC071系列单片机·软件触发ADC采集电位器电压资源-CSDN下载6.4 拓展ISR触发上面只是通过简单的轮询进行软件触发我们也可以通过中断进行标志位的发送触发ADC采集数据由于我们初始化ADC的通道0的中断因此只需要对ADC初始化代码进行第一采集中断使能即可void ADC0_init(void) { ADC_InitTypeDef ADC_InitStructure; ADC_StructInit(ADC_InitStructure); ADC_InitStructure.IE ADC_SF1_IE; ADC_InitStructure.RE 0; ADC_InitStructure.NSMP DISABLE; ADC_InitStructure.DATA_ALIGN DISABLE; ADC_InitStructure.CSMP DISABLE; ADC_InitStructure.TCNT 0; ADC_InitStructure.TROVS DISABLE; ADC_InitStructure.OVSR 0; ADC_InitStructure.TRIG 0; ADC_InitStructure.S1 1; ADC_InitStructure.S2 0; ADC_InitStructure.IS1 0; ADC_InitStructure.LTH 0; ADC_InitStructure.HTH 0; ADC_InitStructure.GEN 0; ADC_Init(ADC0, ADC_InitStructure); ADC_ClearIRQFlag(ADC0, ADC_ALL_IF); ADC_CHN_GAIN_CFG(ADC0, CHN0, ADC_CHANNEL_9, ADC_GAIN7V2); }然后在Hardware_init()初始化NVICvoid Hardware_init(void) { __disable_irq(); SYS_WR_PROTECT 0x7a83; IWDG_DISABLE(); GPIO_init(); GPIO_init_key(); ADC0_init(); OLED_Init(); TIMER2_init(); NVIC_SetPriority(ADC0_IRQn, 1); NVIC_EnableIRQ(ADC0_IRQn); SoftDelay(100); __enable_irq(); }然后来到中断服务函数部分判读ADC0是否发生第一段常规采样完成中断如果是则读取数据中断标志位置1volatile s16 ADCSample; volatile u8 adc_data_ready 0; void ADC0_IRQHandler(void) { if(ADC_GetIRQFlag(ADC0,ADC_SF1_IF)) { ADC_ClearIRQFlag(ADC0,ADC_SF1_IF); ADCSample ADC_GetConversionValue(ADC0,DAT0) ; adc_data_ready 1; } else { ADC_ClearIRQFlag(ADC0,ADC_ALL_IF); } }来到主函数如果触发中断则进行数据显示#include lks32mc07x_lib.h #include hardware_init.h #include led.h #include key.h #include delay.h #include OLED.h extern volatile s16 ADCSample; extern volatile u8 adc_data_ready; s16 adc_raw; u16 adc_val; float voltage; float v_srn; int main(void) { Hardware_init(); while(1) { //ADC_SoftTrgEN(ADC0, ENABLE); ADC0-SWT 0x5AA5; //软件触发 if(adc_data_ready 1) // 检查ISR是否已完成 { adc_data_ready 0; // 清除通知标志 adc_raw ADCSample; adc_val (u16)(adc_raw 4); v_srn (float)adc_val * 7.2f / 2048.0f; voltage v_srn * 3.0f / 2.0f; uint16_t v_int1 (uint16_t)v_srn; uint16_t v_dec1 (uint16_t)((v_srn - v_int1) * 100); uint16_t v_int (uint16_t)voltage; uint16_t v_dec (uint16_t)((voltage - v_int) * 100); OLED_ShowNum(1, 1,adc_raw, 6); OLED_ShowNum(2, 1,adc_val, 6); OLED_ShowNum(3, 1, v_int1, 2); OLED_ShowString(3,3,.); OLED_ShowNum(3,4, v_dec1, 2); OLED_ShowNum(4, 1, v_int, 2); OLED_ShowString(4,3,.); OLED_ShowNum(4,4, v_dec, 2); if(adc_val 700) { LED1_ON; } else { LED1_OFF; } if(adc_val 500) { LED2_ON; } else { LED2_OFF; } if(adc_val 300) { LED3_ON; } else { LED3_OFF; } } } }这里为了方便观察实验现象采用凌鸥官方给的一个图形化工具Tools Software-南京凌鸥创芯电子有限公司安装按照下图操作想要观察什么参数直接拖拽即可然后点击开始运行旋转电位器可以观察到上图电压的变换。完整工程凌鸥LKS32MC071系列单片机·中断触发软件触发ADC采集电位器电压资源-CSDN下载对于UTIME 触发和 MCPWM 触发由于涉及到二者知识点等把二者文章基础部分写完后续在做补充补充部分会存放到下方博客当中。凌鸥LKS32_时光の尘的博客-CSDN博客