5.1 ADC 使用说明
本章说明 N32G033 标准外设库中 ADC 驱动的文件组成、24 个公开函数,以及 ADC_SingleRead、ADC_Temp、AnalogWatchdog、ExtLinesTrigger、TIMTrigger_MutiPhase 5 个示例。分段触发方式、通道与内部信号源、模拟看门狗请配合用户手册的“ADC”章节阅读,芯片已知问题以勘误手册为准。
5.1.1 相关文件
| 相对路径 | 作用 |
|---|---|
firmware/n32g033_std_periph_driver/inc/n32g033_adc.h |
定义 ADC_InitType 结构体与通道、触发源、段模式、标志位、中断、采样时间等宏,并按复位与初始化、触发控制、数据与看门狗、内部信号源与通道配置四个区段声明 24 个公开函数 |
firmware/n32g033_std_periph_driver/src/n32g033_adc.c |
实现上述 24 个函数:ADC 复位与初始化、分段触发与看门狗配置、转换数据读取、标志与中断处理 |
projects/n32g033_EVAL/examples/ADC/ |
ADC 示例根目录,含 ADC_SingleRead、ADC_Temp、AnalogWatchdog、ExtLinesTrigger、TIMTrigger_MutiPhase 5 个示例 |
projects/n32g033_EVAL/examples/ADC/ADC_SingleRead/ |
该示例的工程目录组成:MDK-ARM/、EWARM/、inc/、src/、readme.txt |
projects/n32g033_EVAL/bsp/ |
示例共用的板级支持文件:delay.h 的 SysTick 延时与 log.h 的串口日志接口 |
5.1.2 API 参考
以下 24 个公开函数按 n32g033_adc.h 的声明顺序分为 4 组;每个条目给出功能摘要与 n32g033_adc.c 中该函数正上方的注释原文。
复位与初始化
ADC_DeInit、ADC_Init、ADC_InitStruct、ADC_Enable、ADC_ConfigInt
触发控制与状态
ADC_EnableSoftwareTrig、ADC_EnableExternalLineTrig、ADC_GetSoftwareTrigStatus、ADC_GetExtiLineTrigStatus
数据读取、看门狗与标志中断
ADC_GetDat、ADC_GetGroupConvDat、ADC_ConfigAnalogWatchdogModeChannel、ADC_ConfigAnalogWatchdogThresholds、ADC_GetFlagStatus、ADC_ClearFlag、ADC_GetIntStatus、ADC_ClearIntPendingBit
内部信号源、通道与启动配置
ADC_EnableInternalInputBuffer、ADC_EnableTempSensor、ADC_EnableVREFPAsReferenceVoltag、ADC_ConfigRegularChannel、ADC_ClockModeConfig、ADC_SampleModeConfig、ADC_EnableChannelStartConv
void ADC_DeInit(void)复位 ADC 寄存器。
name ADC_DeInit.
fun Reset the ADC registers.
return none
void ADC_Init(ADC_InitType* ADC_initstruct)按 ADC_initstruct 初始化 ADC。
name ADC_Init.
fun Initializes the ADC according to ADC_initstruct.
param ADC_initstruct :
- ContinueConvEn
- DISABLE
- ENABLE
- ExtTrigSelect1/ExtTrigSelect2/ExtTrigSelect3/ExtTrigSelect4
- ADC_EXT_TRIGCONV_T1_CC1
- ADC_EXT_TRIGCONV_T1_CC2
- ADC_EXT_TRIGCONV_T1_CC3
- ADC_EXT_TRIGCONV_T1_CC4
- ADC_EXT_TRIGCONV_T1_CC5
- ADC_EXT_TRIGCONV_T1_CC6
- ADC_EXT_TRIGCONV_T1_CC7
- ADC_EXT_TRIGCONV_T1_TRGO
- ADC_EXT_TRIGCONV_T3_CC1
- ADC_EXT_TRIGCONV_T3_CC2
- ADC_EXT_TRIGCONV_T3_TRGO
- ADC_EXT_TRIGCONV_T4_CC1
- ADC_EXT_TRIGCONV_T4_CC2
- ADC_EXT_TRIGCONV_T4_TRGO
- ADC_EXT_TRIGCONV_EXT_LINE
- ADC_EXT_TRIGCONV_SWSTRRCH
- DatAlign
- ADC_DAT_ALIGN_R
- ADC_DAT_ALIGN_L
- PhsMode
- ADC_PHS_TRG_MODE_SINGLE
- ADC_PHS_TRG_MODE_TWO
- ADC_PHS_TRG_MODE_THREE
- ADC_PHS_TRG_MODE_FOUR
- Phs1ChNumber
- 1-10
- Phs2ChNumber
- 1-10
- Phs3ChNumber
- 1-10
- Phs4ChNumber
- 1-10
return none
void ADC_InitStruct(ADC_InitType* ADC_initstruct)用默认值填充 ADC_initstruct 的各个成员。
name ADC_InitStruct.
fun Fills each ADC_initstruct member with its default value.
param ADC_initstruct :
- ContinueConvEn
- ExtTrigSelect
- DatAlign
return none
void ADC_Enable(FunctionalState Cmd)使能或关闭 ADC 外设。
name ADC_Enable.
fun Enables or disables ADC peripheral.
param Cmd : new state of the ADC peripheral.
-ENABLE
-DISABLE
return none
void ADC_ConfigInt(uint16_t ADC_IT, FunctionalState Cmd)配置 ADC 中断。
name ADC_ConfigInt.
fun Config ADC interrupts.
param ADC_IT:
- ADC_INT_AWD
- ADC_INT_ENDCA
- ADC_INT_ENDC
- ADC_INT_PHS4
- ADC_INT_PHS3
- ADC_INT_PHS2
- ADC_INT_PHS1
param Cmd : new state of the ADC peripheral.
-ENABLE
-DISABLE
return none
void ADC_EnableSoftwareTrig(FunctionalState Cmd)使能或关闭软件触发。
name ADC_EnableSoftwareTrig.
fun Enables or disables software trigger.
param Cmd : new state of the ADC peripheral.
-ENABLE
-DISABLE
return none:
void ADC_EnableExternalLineTrig(FunctionalState Cmd)使能或关闭 EXTI 线触发。
name ADC_EnableExternalLineTrig.
fun Enables or disables exti line trigger.
param Cmd : new state of the ADC peripheral.
-ENABLE
-DISABLE
return none:
FlagStatus ADC_GetSoftwareTrigStatus(void)获取 ADC 软件触发转换状态。
name ADC_GetSoftwareTrigStatus.
fun Get ADC software trigger conversion status.
param none
return FlagStatus:
- SET
- RESET
FlagStatus ADC_GetExtiLineTrigStatus(void)获取 ADC EXTI 线触发转换状态。
name ADC_GetExtiLineTrigStatus.
fun Get ADC exti line trigger conversion status.
param none
return FlagStatus:
- SET
- RESET
uint16_t ADC_GetDat(void)获取 ADC 转换数据。
name ADC_GetDat.
fun Get ADC conversion data.
return ADC group conversion data.
uint16_t ADC_GetGroupConvDat(uint8_t number)获取 ADC 组转换数据。
name ADC_GetGroupConvDat.
fun Get ADC group conversion data.
param number :
- 0~9
return ADC group conversion data.
void ADC_ConfigAnalogWatchdogModeChannel(uint16_t channel)配置 ADC 模拟看门狗监测。
name ADC_ConfigAnalogWatchdogModeChannel.
fun Configures ADC analog watchdog monitor.
param channel :
- ADC_ANALOG_WTDG_DAT0
- ADC_ANALOG_WTDG_DAT1
- ADC_ANALOG_WTDG_DAT2
- ADC_ANALOG_WTDG_DAT3
- ADC_ANALOG_WTDG_DAT4
- ADC_ANALOG_WTDG_DAT5
- ADC_ANALOG_WTDG_DAT6
- ADC_ANALOG_WTDG_DAT7
- ADC_ANALOG_WTDG_DAT8
- ADC_ANALOG_WTDG_DAT9
return none
void ADC_ConfigAnalogWatchdogThresholds(uint16_t HighThreshold, uint16_t LowThreshold)配置模拟看门狗的高阈值。
name ADC_Analog_Watchdog_HighThresholds_Config.
fun Configures the high thresholds of the analog watchdog.
param HighThreshold : 12bit high thresholds value(0 ~ 0xFFF)
param LowThreshold : 12bit low thresholds value(0 ~ 0xFFF)
return none
使用提示: 注释 name 写作 ADC_Analog_Watchdog_HighThresholds_Config.,与函数名不一致;实现同时把两个参数分别写入 ADC->AWDHIGH 与 ADC->AWDLOW,高低阈值都会配置。
FlagStatus ADC_GetFlagStatus(uint16_t ADC_FLAG)获取 ADC 标志状态。
name ADC_GetFlagStatus.
fun Get ADC flag Status.
param ADC_FLAG :
- ADC_FLAG_RDY : ADC ready flag
- ADC_FLAG_PD_RDY ADC powerdown ready flag
- ADC_FLAG_BUF_RDY : VREFBUF ready flag
- ADC_FLAG_AWDG
- ADC_FLAG_ENDC
- ADC_FLAG_ENDCA
- ADC_FLAG_STR
- ADC_FLAG_PHS4
- ADC_FLAG_PHS3
- ADC_FLAG_PHS2
- ADC_FLAG_PHS1
return SET or RESET
void ADC_ClearFlag(uint16_t ADC_FLAG)清除 ADC 标志状态。
name ADC_ClearFlag.
fun Clear ADC flag Status.
param ADC_FLAG :
- ADC_FLAG_AWDG
- ADC_FLAG_ENDC
- ADC_FLAG_ENDCA
- ADC_FLAG_STR
- ADC_FLAG_PHS4
- ADC_FLAG_PHS3
- ADC_FLAG_PHS2
- ADC_FLAG_PHS1
return none
INTStatus ADC_GetIntStatus(uint16_t ADC_IT)获取 ADC 中断状态。
name ADC_GetIntStatus.
fun Get ADC Interrupt Status.
param ADC_IT :
- ADC_INT_FLAG_AWDG
- ADC_INT_FLAG_ENDC
- ADC_INT_FLAG_ENDCA
- ADC_INT_FLAG_PHS4
- ADC_INT_FLAG_PHS3
- ADC_INT_FLAG_PHS2
- ADC_INT_FLAG_PHS1
return SET or RESET
void ADC_ClearIntPendingBit(uint16_t ADC_IT)清除 ADC 中断标志状态。
name ADC_ClearIntPendingBit.
fun Clear ADC interrupt flag Status.
param ADC_IT :
- ADC_INT_FLAG_AWDG
- ADC_INT_FLAG_ENDC
- ADC_INT_FLAG_ENDCA
- ADC_INT_FLAG_PHS4
- ADC_INT_FLAG_PHS3
- ADC_INT_FLAG_PHS2
- ADC_INT_FLAG_PHS1
return none
void ADC_EnableInternalInputBuffer(FunctionalState Cmd)使能或关闭 ADC 内部输入 buffer。
name ADC_EnableInternalInputBuffer.
fun Enable and disable ADC internal input buffer.
param Cmd : new state of the ADC peripheral.
-ENABLE
-DISABLE
return none
void ADC_EnableTempSensor(FunctionalState Cmd)使能或关闭温度传感器通道。
name ADC_EnableTempSensor.
fun Enable and disable temperature sensor channel .
param Cmd : new state of the ADC peripheral.
-ENABLE
-DISABLE
return none
void ADC_EnableVREFPAsReferenceVoltag(FunctionalState Cmd)选择或不选择 VREF+ 作为 ADC 参考电压源。
name ADC_EnableVREFPAsReferenceVoltag.
fun Select VREF+ as ADC reference voltage source or not.
param Cmd : new state of the ADC peripheral.
-ENABLE
-DISABLE
return none
void ADC_ConfigRegularChannel(uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime)配置 ADC 通道在序列中的相应次序及其采样时间。
name ADC_ConfigRegularChannel.
fun Configures ADC channel its corresponding
rank in the sequencer and its sample time.
param ADC_Channel :
- ADC_CH_0
- ADC_CH_1
- ADC_CH_2
- ADC_CH_3
- ADC_CH_4
- ADC_CH_5
- ADC_CH_6
- ADC_CH_7
- ADC_CH_8
- ADC_CH_9
- ADC_CH_10
- ADC_CH_TS
- ADC_CH_VREFINT
- ADC_CH_OPA1OUT
- ADC_CH_OPA2OUT
- ADC_CH_OPA3OUT
param Rank : The rank in the group sequencer. This parameter must be between 1 to 10.
param ADC_SampleTime : The sample time value to be set for the selected channel.
- ADC_SAMP_TIME_4CYCLES
- ADC_SAMP_TIME_6CYCLES
- ADC_SAMP_TIME_14CYCLES
- ADC_SAMP_TIME_20CYCLES
- ADC_SAMP_TIME_29CYCLES
- ADC_SAMP_TIME_42CYCLES
- ADC_SAMP_TIME_56CYCLES
- ADC_SAMP_TIME_72CYCLES
- ADC_SAMP_TIME_88CYCLES
- ADC_SAMP_TIME_120CYCLES
- ADC_SAMP_TIME_182CYCLES
- ADC_SAMP_TIME_240CYCLES
- ADC_SAMP_TIME_300CYCLES
- ADC_SAMP_TIME_400CYCLES
- ADC_SAMP_TIME_480CYCLES
- ADC_SAMP_TIME_600CYCLES
return none
void ADC_ClockModeConfig(uint32_t RCC_ADCHCLKprescaler)配置 ADCHCLK 分频系数。
name ADC_ClockModeConfig
fun Configures the ADCHCLK prescaler.
param RCC_ADCHCLKprescaler:
- RCC_ADCHCLK_DIV2
- RCC_ADCHCLK_DIV4
- RCC_ADCHCLK_DIV8
- RCC_ADCHCLK_DIV16
- RCC_ADCHCLK_DIV32
return none
void ADC_SampleModeConfig(uint32_t mode,uint8_t PH1CHNUM,uint8_t PH2CHNUM,uint8_t PH3CHNUM,uint8_t PH4CHNUM)配置 ADC 分段采样模式。
name ADC_SampleModeConfig.
fun Configures the ADC sample mode.
param mode : Trigger mode selection.
-ADC_PHS_TRG_MODE_SINGLE
-ADC_PHS_TRG_MODE_TWO
-ADC_PHS_TRG_MODE_THREE
-ADC_PHS_TRG_MODE_FOUR
param PH1CHNUM,PH2CHNUM,PH3CHNUM,PH4CHNUM :
- 1~ 10
return none
void ADC_EnableChannelStartConv(uint32_t PHSWSTART)软件启动第 x 段转换。
name ADC_EnableChannelStartConv.
fun Software start phase x conversion.
param swstart:
- ADC_SWSTRRCH_PHS1_START
- ADC_SWSTRRCH_PHS2_START
- ADC_SWSTRRCH_PHS3_START
- ADC_SWSTRRCH_PHS4_START
return none:
5.1.3 Demo 示例说明
本节说明 ADC 的 5 个示例:ADC_SingleRead 用软件触发轮流转换 PA0、PA1,ADC_Temp 读取内部温度传感器并换算成温度,AnalogWatchdog 用模拟看门狗越限中断计数,ExtLinesTrigger 用 EXTI 线事件触发两通道转换,TIMTrigger_MutiPhase 用 TIM1 的四个捕获比较通道分段触发五个通道。
5.1.3.1 ADC_SingleRead 单次软件触发采样
工程目录: projects/n32g033_EVAL/examples/ADC/ADC_SingleRead/
使能 GPIO 与 ADC 时钟→配置 PA0、PA1 为模拟输入→初始化 ADC 并等待上电就绪→主循环逐通道软件触发并读取转换数据
| 项目 | 源码解读 |
|---|---|
| 功能 | 以软件触发的方式对 PA0、PA1 两个通道各做一次单次转换,结果依次存入 ADCConvertedValue 数组。 |
| 源码组成 | src/main.c 含 ADC_Initial、RCC_Configuration、GPIO_Configuration 与取数函数 ADC_Config_And_Get_Data;src/n32g033_it.c 与 inc/n32g033_it.h 为中断函数;inc/main.h 声明外部变量;readme.txt 给出配置与测试步骤;工程文件在 MDK-ARM/ 与 EWARM/。 |
| 关键配置 | 引脚:PA0、PA1 为模拟输入; 时钟:ADC 时钟分频取 RCC_ADCHCLK_DIV4;模式:单段触发、连续转换关闭、12 位数据右对齐; 采样:单通道采样时间 72 周期; 触发:软件触发。 |
| 程序与数据路径 | main → RCC_Configuration 打开 GPIO 与 ADC 时钟并设置分频 → GPIO_Configuration 把 PA0、PA1 设为模拟输入 → ADC_Initial 初始化并使能 ADC → 主循环调用 ADC_Config_And_Get_Data 逐通道配置、触发、等待结束标志后取数。 |
| 主要 API | ADC_InitStruct、ADC_Init、ADC_Enable、ADC_GetFlagStatus、ADC_ClearFlag、ADC_ClockModeConfig、ADC_ConfigRegularChannel、ADC_EnableChannelStartConv、ADC_GetDat |
| 验证方法 | 编译后进入调试模式,把 ADCConvertedValue 加入 watch 窗口;改变 PA0、PA1 引脚电压时转换结果同步变化。 |
| 使用提示 | 开发环境为 KEIL MDK-ARM V5.34.0.0 或 IAR EWARM 8.50.1,硬件基于评估板 N32G033K8Q7-1_STB V1.0; 系统时钟 64 MHz。 |
核心代码解读与移植
示例先用分频后的 ADC 时钟完成上电与初始化,再由主循环逐通道软件触发取数。
数据路径: RCC_Configuration 开 GPIO 与 ADC 时钟 → GPIO_Configuration 写 PA0、PA1 模式 → ADC_Initial 调用 ADC_Init 与 ADC_Enable → 主循环 ADC_Config_And_Get_Data 触发转换 → ADC_GetDat 取回结果写入 ADCConvertedValue
1. 先开 GPIO 与 ADC 时钟,再设置 ADC 时钟分频。 ADC 挂在 AHB 上,其工作时钟由 ADC_ClockModeConfig 单独分频,取 64 MHz 的四分频。
void RCC_Configuration(void)
{
/* Enable peripheral clocks ------------------------------------------------*/
/* Enable GPIO clocks */
RCC_EnableAPBPeriphClk(RCC_APB_PERIPH_GPIO, ENABLE);
/* Enable ADC clocks */
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC, ENABLE);
/* RCC_ADCHCLK_DIV4*/
ADC_ClockModeConfig(RCC_ADCHCLK_DIV4);
}
移植到其他主频时同步核对这一分频系数,保证 ADC 工作时钟不超过手册规定的上限。
2. 把待测引脚配成模拟输入。 模拟模式下引脚不接数字输入通道,两路通道共用一次配置。
GPIO_InitStruct(&GPIO_InitStructure);
/* Configure PA0 PA1 as analog input -----------------------*/
GPIO_InitStructure.Pin = GPIO_PIN_0 | GPIO_PIN_1;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_ANALOG;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
换用其他通道时,同一处要同步修改引脚与后面 ADC_Config_And_Get_Data 传入的通道号。
3. 初始化 ADC 并使能后等待上电就绪。 结构体成员决定触发源、对齐方式与段模式,此处关闭连续转换、选软件触发并让四个段各占一个通道。
ADC_InitStruct(&ADC_InitStructure);
/* ADC configuration ------------------------------------------------------*/
ADC_InitStructure.ContinueConvEn = DISABLE;
/* Initialize the ExtTrigSelect1 member */
ADC_InitStructure.ExtTrigSelect1 = ADC_EXT_TRIGCONV_SWSTRRCH;
/* Initialize the DatAlign member */
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
/* Initialize the phase mode member */
ADC_InitStructure.PhsMode = ADC_PHS_TRG_MODE_SINGLE ;
/* Initialize the phase 1 channel number member */
ADC_InitStructure.Phs1ChNumber = 1U;
/* Initialize the phase 2 channel number member */
ADC_InitStructure.Phs2ChNumber = 1U;
/* Initialize the phase 3 channel number member */
ADC_InitStructure.Phs3ChNumber = 1U;
/* Initialize the phase 4 channel number member */
ADC_InitStructure.Phs4ChNumber = 1U;
ADC_Init(&ADC_InitStructure);
/* Enable ADC */
ADC_Enable(ENABLE);
/*Check ADC Ready*/
while(ADC_GetFlagStatus(ADC_FLAG_RDY) == RESET)
;
while 等待的 ADC_FLAG_RDY 对应上电完成,去掉这一轮询会在 ADC 尚未就绪时启动转换。
4. 每次取值都重新配置通道、软件触发并读取。 函数按传入通道号排队,等待本段转换结束后清标志再取数,因此同一个相位寄存器可被反复用于不同通道。
uint16_t dat;
ADC_ConfigRegularChannel(ADC_Channel, 1, ADC_SAMP_TIME_72CYCLES);
/* Start ADC Software Conversion */
ADC_EnableChannelStartConv(ADC_SWSTRRCH_PHS1_START);
while(ADC_GetFlagStatus(ADC_FLAG_ENDC)==0){
}
ADC_ClearFlag(ADC_FLAG_ENDC);
ADC_ClearFlag(ADC_FLAG_STR);
dat=ADC_GetDat();
return dat;
采样时间随信号源阻抗调整,改动触发方式时同步核对 ADC_InitStructure.ExtTrigSelect1 与这里的启动宏是否一致。
对应源码: src/main.c、firmware/n32g033_std_periph_driver/inc/n32g033_adc.h
5.1.3.2 ADC_Temp 内部温度传感器采样
工程目录: projects/n32g033_EVAL/examples/ADC/ADC_Temp/
使能 GPIO、UART 与 ADC 时钟→配置 PA9、PA10 为串口复用引脚→打开内部温度传感器通道→连续转换并换算温度→日志串口周期输出温度值
| 项目 | 源码解读 |
|---|---|
| 功能 | 采集内部温度传感器通道的转换值,用片内校准值换算成摄氏度,并每 100 ms 通过日志串口打印。 |
| 源码组成 | src/main.c 含 ADC_Initial、RCC_Configuration、GPIO_Configuration、取数函数与换算函数 TempCal;src/n32g033_it.c 与 inc/n32g033_it.h 为中断函数;inc/main.h 与 readme.txt 给出声明与使用说明;工程文件在 MDK-ARM/ 与 EWARM/。 |
| 关键配置 | 引脚:PA9、PA10 为 UART1 复用推挽; 时钟:ADS 时钟分频取 RCC_ADCHCLK_DIV4;模式:单段触发、连续转换使能、12 位数据右对齐; 采样:采样时间 400 周期; 换算:参考电压 VREF_VALUE 取 3.3,斜率 AVG_SLOPE 为 0.00407。 |
| 程序与数据路径 | main → RCC_Configuration 开 GPIO、UART1 与 ADC 时钟 → log_init 初始化串口 → ADC_Initial 打开温度传感器通道并使能 ADC → 主循环取数后调用 TempCal 换算温度 → printf 经串口输出。 |
| 主要 API | ADC_EnableTempSensor、ADC_InitStruct、ADC_Init、ADC_Enable、ADC_GetFlagStatus、ADC_ClearFlag、ADC_ConfigRegularChannel、ADC_EnableChannelStartConv、ADC_GetDat、ADC_ClockModeConfig |
| 验证方法 | 把串口工具接到 PA9 并打开接收; 全速运行时串口约每 100 ms 输出一次温度,室温下接近 25 摄氏度,也可在 watch 窗口观察 ADCConvertedValue 与 TempValue。 |
| 使用提示 | 内部传感器在环境温度 30 摄氏度下校准,读数会随实际环境温度偏移; 开发环境为 KEIL MDK-ARM V5.34.0.0 或 IAR EWARM 8.50.1。 |
核心代码解读与移植
示例先打开温度传感器通道,再用片内校准值把原始码值换算成温度并从串口输出。
数据路径: ADC_EnableTempSensor 打开通道 → ADC_Config_And_Get_Data 触发并取回原始码值 → TempCal 读片内校准值计算温度 → TempValue → printf 经 log_init 配好的 UART1 输出
1. 换算所需的参考电压与斜率在文件头给出。 参考电压由外部实际供电决定,注释提示需按实测值配置,斜率来自数据手册。
/*xx mv per degree Celsius by datasheet define*/
#define AVG_SLOPE 0.00407f
//#define VDDA_5V
#ifdef VDDA_5V
#define VREF_VALUE (5.0) //this value need be configured by the actual voltage reference.
#define VTS_CODE_ADDR (0x1FFFF048U)
#else
#define VREF_VALUE (3.3)
#define VTS_CODE_ADDR (0x1FFFF048U)
#endif
供电改为 5 V 时打开 VDDA_5V,同时核对 VREF_VALUE 与取校准值的位段。
2. 使能温度传感器通道后再使能 ADC。 通道 16 对应内部温度传感器,只有打开该位才能被规则通道选择;两处使能都写在同一个函数里。
ADC_EnableTempSensor(ENABLE);
/* Enable ADC */
ADC_Enable(ENABLE);
/*Check ADC Ready*/
while(ADC_GetFlagStatus(ADC_FLAG_RDY) == RESET)
;
通道使能与 ADC 使能的先后顺序不要对调;改用其他内部信号源时,在这里换成对应的使能函数。
3. 每次取数都冲着结束标志等待,并用更长的采样时间。 内部传感器输出高阻,采样时间取 400 周期;连续转换下每次取数仍需等待本次结束标志。
ADC_ConfigRegularChannel(ADC_Channel, 1, ADC_SAMP_TIME_400CYCLES);
/* Start ADC Software Conversion */
ADC_EnableChannelStartConv(ADC_SWSTRRCH_PHS1_START);
while(ADC_GetFlagStatus(ADC_FLAG_ENDCA)==0){
}
ADC_ClearFlag(ADC_FLAG_ENDCA);
ADC_ClearFlag(ADC_FLAG_STR);
dat=ADC_GetDat();
这里等待的是 ADC_FLAG_ENDCA,与单人取数示例用的 ADC_FLAG_ENDC 不同;改采样时间时同步核对外部信号源的输出阻抗。
4. 换算函数读取片内校准值并按斜率求温度。 校准值存放在固定地址,VDDA_5V 决定取高 16 位还是低 16 位。
float Temperate,tempValue,VTS;
uint32_t TSValue;
/* Voltage value of temperature sensor */
tempValue=TempAdVal*(VREF_VALUE/4095);
下一段与上面隔着 VDDA_5V 条件编译区,选值的位段随供电电压而定。
/* Get the temperature inside the chip */
Temperate= (VTS-tempValue)/AVG_SLOPE + 30;
return Temperate;
参考电压或芯片批次变化时要重新核对校准值地址与斜率,换算出的温度才有意义。
对应源码: src/main.c、firmware/n32g033_std_periph_driver/inc/n32g033_adc.h
5.1.3.3 AnalogWatchdog 模拟看门狗越限中断
工程目录: projects/n32g033_EVAL/examples/ADC/AnalogWatchdog/
使能 GPIO 与 ADC 时钟→配置 PA3 为模拟输入→设置模拟看门狗阈值与中断→软件触发单次转换→越限后进入中断累加计数
| 项目 | 源码解读 |
|---|---|
| 功能 | 转换 PA3 的模拟电压,转换值超出模拟看门狗设定的高、低阈值范围时进入中断,在中断里累加计数。 |
| 源码组成 | src/main.c 含 ADC_Initial、RCC_Configuration、GPIO_Configuration、NVIC_Configuration 与阈值宏;src/n32g033_it.c 中的 ADC_IRQHandler 判断看门狗标志并计数;inc/main.h、inc/n32g033_it.h 给出声明;工程文件在 MDK-ARM/ 与 EWARM/。 |
| 关键配置 | 引脚:PA3 为模拟输入; 阈值:高阈值 0xB00、低阈值 0x300;监测: ADC_ANALOG_WTDG_DAT0;中断: ADC_INT_AWD 使能,ADC_IRQn 优先级 0;模式:单段触发、连续转换使能、右对齐,采样 72 周期。 |
| 程序与数据路径 | main → RCC_Configuration 开时钟 → GPIO_Configuration 设 PA3 模拟输入 → NVIC_Configuration 使能 ADC 中断 → ADC_Initial 配置通道、阈值与监测对象 → 软件触发一次转换 → 主循环空转累加 gCnt,越限由 ADC_IRQHandler 累加 gCntAwdg。 |
| 主要 API | ADC_ConfigInt、ADC_ConfigAnalogWatchdogThresholds、ADC_ConfigAnalogWatchdogModeChannel、ADC_ConfigRegularChannel、ADC_EnableChannelStartConv、ADC_InitStruct、ADC_Init、ADC_Enable、ADC_GetIntStatus、ADC_ClearIntPendingBit |
| 验证方法 | 把 gCntAwdg 加入 watch 窗口;改变 PA3 电压,超出高、低阈值范围时计数增加一次,范围之内不增加。 |
| 使用提示 | 开发环境为 KEIL MDK-ARM V5.34.0.0 或 IAR EWARM 8.50.1,硬件基于评估板 N32G033K8Q7-1_STB V1.0; 阈值按 12 位码值给出。 |
核心代码解读与移植
示例先用一次配置把看门狗阈值、监测对象与中断串起来,再靠中断里的标志判断完成计数。
数据路径: ADC_ConfigAnalogWatchdogThresholds 写高、低阈值 → ADC_ConfigAnalogWatchdogModeChannel 选 DAT0 → ADC_ConfigInt 使能 ADC_INT_AWD → 转换结果超出范围置 ADC_INT_FLAG_AWDG → ADC_IRQHandler 清标志并累加 gCntAwdg
1. 先在 NVIC 里打开 ADC 中断。 中断向量使能与 ADC 侧的中断源使能是两个开关,这一处负责前者。
NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
移植到实际工程时按系统优先级规划调整 NVIC_IRQChannelPriority,并保持中断向量名与启动文件一致。
2. 先配阈值与监测对象,再使能中断。 阈值以 12 位码值给出,监测对象选转换结果寄存器 DAT0。
ADC_ConfigRegularChannel(ADC_Channel_03_PA3, 1, ADC_SAMP_TIME_72CYCLES);
/*Enable anolog watchdog*/
ADC_ConfigInt(ADC_INT_AWD, ENABLE);
ADC_ConfigAnalogWatchdogThresholds(HIGH_THRESHOLD, LOW_THRESHOLD);
/*Enable DAT0 watchdog*/
ADC_ConfigAnalogWatchdogModeChannel(ADC_ANALOG_WTDG_DAT0);
/* Anolog watchdog monitor DAT0 enable */
ADC_Enable(ENABLE);
阈值按被测信号允许的范围改写;若监测的是其他数据寄存器,这里的 ADC_ANALOG_WTDG_DATx 要同步改。
3. 中断服务函数按标志分支处理。 只有看门狗标志置位时才清标志并计数。
void ADC_IRQHandler(void)
{
if(ADC_GetIntStatus(ADC_INT_FLAG_AWDG) != RESET)
{
ADC_ClearIntPendingBit(ADC_INT_FLAG_AWDG);
gCntAwdg++;
}
}
gCntAwdg 是文件内静态变量,要在 watch 窗口观察需按源码里的声明方式访问;新增其他中断源时保持清标志在分支内完成。
对应源码: src/main.c、src/n32g033_it.c、firmware/n32g033_std_periph_driver/inc/n32g033_adc.h
5.1.3.4 ExtLinesTrigger EXTI 线事件触发采样
工程目录: projects/n32g033_EVAL/examples/ADC/ExtLinesTrigger/
使能 GPIO 与 ADC 时钟→配置 PA0、PA1 为模拟输入、PA4 为上拉输入→把 EXTI 线事件接为 ADC 触发源→配置两通道序列→主循环等待转换结束并读取组数据
| 项目 | 源码解读 |
|---|---|
| 功能 | 用 EXTI 线事件触发 ADC,依次转换 PA0、PA1 两个通道,主循环等待结束标志后读取组转换数据。 |
| 源码组成 | src/main.c 含 ADC_Initial、RCC_Configuration、GPIO_Configuration、EXTI_Configuration;src/n32g033_it.c 与 inc/n32g033_it.h 为中断函数;inc/main.h、readme.txt 给出声明与使用说明;工程文件在 MDK-ARM/ 与 EWARM/。 |
| 关键配置 | 引脚:PA0、PA1 为模拟输入,PA4 为上拉输入; 触发: ADC_EXT_TRIGCONV_EXT_LINE,EXTI 重映射选 AFIO_ADC_TRIG_EXTI_1;序列:相位 1 两个通道,PA0 为第 1 序、PA1 为第 2 序; 采样:72 周期; EXTI:事件模式、下降沿。 |
| 程序与数据路径 | main → RCC_Configuration 开时钟 → GPIO_Configuration 设三个引脚 → EXTI_Configuration 把 PA4 接到 EXTI 线并设为事件下降沿 → ADC_Initial 配置触发源与两通道 → 主循环等待 ADC_FLAG_ENDC 后清标志,用 ADC_GetGroupConvDat 取回两个结果。 |
| 主要 API | ADC_InitStruct、ADC_Init、ADC_Enable、ADC_GetFlagStatus、ADC_ClearFlag、ADC_ConfigRegularChannel、ADC_GetGroupConvDat、AFIO_ConfigADCExternalTrigRemap |
| 验证方法 | 把 ADCConvertedValue 加入 watch 窗口;把 PA4 拉低产生一次下降沿,改变 PA0、PA1 电压后可看到两个结果同步更新。 |
| 使用提示 | 开发环境为 KEIL MDK-ARM V5.34.0.0 或 IAR EWARM 8.50.1,硬件基于评估板 N32G033K8Q7-1_STB V1.0; PA4 既作触发输入也作按键使用。 |
核心代码解读与移植
示例把 EXTI 线事件接成 ADC 触发源,再用两通道序列在一次触发中顺序转换。
数据路径: GPIO_Configuration 设 PA0、PA1 模拟输入与 PA4 上拉输入 → EXTI_Configuration 把 PA4 接到 EXTI 线 → AFIO_ConfigADCExternalTrigRemap 选触发线 → ADC_ConfigRegularChannel 排两通道 → 主循环等 ADC_FLAG_ENDC → ADC_GetGroupConvDat 取回两个结果
1. 触发源改为 EXTI 线,并重映射到具体线号。 触发源由结构体成员选择,具体用哪条 EXTI 线由 AFIO 的重映射函数决定。
ADC_InitStruct(&ADC_InitStructure);
/* ADC configuration ------------------------------------------------------*/
ADC_InitStructure.ContinueConvEn = DISABLE;
/* Initialize the ExtTrigSelect1 member */
ADC_InitStructure.ExtTrigSelect1 = ADC_EXT_TRIGCONV_EXT_LINE;
/* Initialize the DatAlign member */
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
/* Initialize the phase mode member */
ADC_InitStructure.PhsMode = ADC_PHS_TRG_MODE_SINGLE ;
/* Initialize the phase 1 channel number member */
ADC_InitStructure.Phs1ChNumber = 2U;
//select EXTI1 as adc triagger source
AFIO_ConfigADCExternalTrigRemap(AFIO_ADC_TRIG_EXTI_1);
换用其他触发线时同时改 AFIO_ADC_TRIG_EXTI_x 与外部引脚的 EXTI 线号,两者必须对应。
2. 两通道在同一相位内排定次序,取数按序读寄存器。 相位 1 配两个通道,转换结果分别落在第 0、1 个数据寄存器。
//ExtTrigSelect1 exti
ADC_ConfigRegularChannel(ADC_Channel_00_PA0, 1, ADC_SAMP_TIME_72CYCLES);
ADC_ConfigRegularChannel(ADC_Channel_01_PA1, 2, ADC_SAMP_TIME_72CYCLES);
while(ADC_GetFlagStatus(ADC_FLAG_ENDC)==0){
}
ADC_ClearFlag(ADC_FLAG_ENDC);
ADC_ClearFlag(ADC_FLAG_STR);
ADCConvertedValue[0] =ADC_GetGroupConvDat(0);
ADCConvertedValue[1] =ADC_GetGroupConvDat(1);
序数与寄存器下标一一对应,增删通道时要同时改 Phs1ChNumber 与取数下标。
3. EXTI 侧的引脚来源与线号需与 ADC 侧一致。 源配置把 PA4 接到引脚源 4,中断结构体配置的却是 EXTI 线 1,注释写的是“EXTI line10 configuration”。
GPIO_ConfigEXTILine(GPIOA_PORT_SOURCE,GPIO_PIN_SOURCE4);
/* EXTI line10 configuration -----------------------------------------------*/
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_Line = EXTI_LINE1;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_InitPeripheral(&EXTI_InitStructure);
按源码现状,实际生效的触发线是 EXTI_LINE1;移植时若要改用 PA4 对应的线,需要把引脚源与线号改成同一编号。
对应源码: src/main.c、firmware/n32g033_std_periph_driver/inc/n32g033_adc.h
5.1.3.5 TIMTrigger_MutiPhase TIM1 分段触发多通道采样
工程目录: projects/n32g033_EVAL/examples/ADC/TIMTrigger_MutiPhase/
使能 GPIO、TIM1 与 ADC 时钟→配置五个引脚为模拟输入、四个引脚为 PWM 输出→初始化四段采样模式与各段触发源→启动 TIM1 计数与 PWM 输出→第四段结束时进中断读取组数据
| 项目 | 源码解读 |
|---|---|
| 功能 | 用 TIM1 的四个捕获比较通道分别触发 ADC 的四段采样,依次转换 PA1、PA4、PA0、PB0、PB1,第四段结束时进中断把五个结果搬进缓冲区。 |
| 源码组成 | src/main.c 含 ADC_Initial、RCC_Configuration、GPIO_Configuration、TIM_Configuration、NVIC_Configuration;src/n32g033_it.c 中的 ADC_IRQHandler 搬运组数据并翻转 PB7;inc/main.h、inc/n32g033_it.h 给出声明;工程文件在 MDK-ARM/ 与 EWARM/。 |
| 关键配置 | 引脚:PA0、PA1、PA4、PB0、PB1 为模拟输入,PB3~PB6 为 TIM1 复用推挽,PB7 为推挽输出; 模式:四段触发,相位 1 两个通道、相位 2~4 各一个; 触发:相位 1~4 分别为 ADC_EXT_TRIGCONV_T1_CC1~T1_CC4;采样:4 周期; 中断: ADC_INT_PHS4,ADC_IRQn 优先级 0;TIM1:中心对齐模式 3,周期 1600,脉冲 1500/1200/800/200。 |
| 程序与数据路径 | main → RCC_Configuration 开 GPIO、TIM1 与 ADC 时钟 → GPIO_Configuration 设模拟、复用与输出引脚 → NVIC_Configuration 使能 ADC 中断 → ADC_Initial 配置四段触发与五通道 → TIM_Configuration 配时基与四路 PWM → 使能 PWM 输出与计数 → 每轮第四段完成由中断搬运数据。 |
| 主要 API | ADC_InitStruct、ADC_Init、ADC_Enable、ADC_ConfigRegularChannel、ADC_ConfigInt、ADC_GetIntStatus、ADC_ClearIntPendingBit、ADC_GetGroupConvDat |
| 验证方法 | 把 ADCConvertedValue 加入 watch 窗口;改变五个引脚的电压,缓冲区内容按 PA1、PA4、PA0、PB0、PB1 的顺序更新; 用示波器观察 PB7 在每个中断里的翻转。 |
| 使用提示 | 开发环境为 KEIL MDK-ARM V5.34.0.0 或 IAR EWARM 8.50.1,硬件基于评估板 N32G033K8Q7-1_STB V1.0; PB3~PB6 需分别接示波器才能观察四路 PWM。 |
核心代码解读与移植
示例把 TIM1 的四路比较输出当作四个触发源,用四段模式依次采完五个通道,再由中断把结果搬出。
数据路径: TIM_Configuration 配四路 PWM → 四路比较事件分别触发相位 1~4 → ADC_ConfigRegularChannel 排定的五个通道依次转换 → 相位 4 完成置 ADC_INT_FLAG_PHS4 → ADC_IRQHandler 用 ADC_GetGroupConvDat 搬五个结果进 ADCConvertedValue
1. 四段模式:每段指定各自的触发源与通道数。 相位 1 触发两个通道,其余三段各一个,触发源分别来自 TIM1 的四个比较通道。
/* Initialize the ExtTrigSelect1 member */
ADC_InitStructure.ExtTrigSelect1 = ADC_EXT_TRIGCONV_T1_CC1;
/* Initialize the ExtTrigSelect2 member */
ADC_InitStructure.ExtTrigSelect2 = ADC_EXT_TRIGCONV_T1_CC2;
/* Initialize the ExtTrigSelect3 member */
ADC_InitStructure.ExtTrigSelect3 = ADC_EXT_TRIGCONV_T1_CC3;
/* Initialize the ExtTrigSelect4 member */
ADC_InitStructure.ExtTrigSelect4 = ADC_EXT_TRIGCONV_T1_CC4;
/* Initialize the DatAlign member */
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
/* Initialize the phase mode member */
ADC_InitStructure.PhsMode = ADC_PHS_TRG_MODE_FOUR ;
/* Initialize the phase 1 channel number member */
ADC_InitStructure.Phs1ChNumber = 2U;
//PH1
ADC_ConfigRegularChannel(ADC_Channel_01_PA1,1,ADC_SAMP_TIME_4CYCLES);
ADC_ConfigRegularChannel(ADC_Channel_04_PA4,2,ADC_SAMP_TIME_4CYCLES);
//PH2
ADC_ConfigRegularChannel(ADC_Channel_00_PA0,3,ADC_SAMP_TIME_4CYCLES);
//PH3
ADC_ConfigRegularChannel(ADC_Channel_08_PB0,4,ADC_SAMP_TIME_4CYCLES);
//PH4
ADC_ConfigRegularChannel(ADC_Channel_09_PB1,5,ADC_SAMP_TIME_4CYCLES);
各段通道数之和对应前面 Phs1ChNumber~Phs4ChNumber,改段数时两处一起改。
2. 五个采样引脚与四路 PWM 引脚分别配置。 采样引脚走模拟模式,PWM 引脚走复用推挽并各自指定复用编号。
/* Configure PB3-CH1 as alternate function push-pull mode ----*/
GPIO_InitStructure.Pin = GPIO_PIN_3;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.GPIO_Alternate =GPIO_AF1;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
/* Configure PB4-CH2 as alternate function push-pull mode ----*/
GPIO_InitStructure.Pin = GPIO_PIN_4;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.GPIO_Alternate =GPIO_AF7;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
复用编号与引脚一一对应,换引脚时要按用户手册的复用映射表改 GPIO_Alternate。
3. TIM1 时基决定触发频率,四路脉冲决定各段触发时刻。 中心对齐模式下计数值先增后减,四路比较值依次触发四个相位。
PrescalerValue = (uint32_t)(SystemCoreClock / 160000) - 1;
/* Time base configuration */
TIM_InitTimBaseStruct(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.Period = 1600;
TIM_TimeBaseStructure.Prescaler = PrescalerValue;
TIM_TimeBaseStructure.ClkDiv = TIM_CLK_DIV1;
TIM_TimeBaseStructure.CounterMode = TIM_CNT_MODE_CENTER_ALIGN3;
TIM_InitTimeBase(TIM1, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: Channel1 */
TIM_InitOcStruct(&TIM_OCInitStructure);
TIM_OCInitStructure.OCMode = TIM_OCMODE_PWM1;
TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE;
TIM_OCInitStructure.Pulse = Pluse1_Val;
TIM_OCInitStructure.OCPolarity = TIM_OC_POLARITY_HIGH;
TIM_InitOc1(TIM1, &TIM_OCInitStructure);
TIM_ConfigOc1Preload(TIM1, TIM_OC_PRE_LOAD_ENABLE);
分组时间由 PrescalerValue 与 Period 共同决定,四路脉冲值的先后顺序决定各段触发次序。
4. 中断里按序搬走五个结果并翻转一个引脚。 中断只在相位 4 标志置位时进入,索引写满 28 个元素后回卷。
void ADC_IRQHandler(void)
{
if(ADC_GetIntStatus(ADC_INT_FLAG_PHS4) != RESET)
{
ADC_ClearIntPendingBit(ADC_INT_FLAG_PHS4);
GPIOB->PBSC = GPIO_PIN_7;
//Get PA1, PA4, PA0, PB0, PB1 conversion value
ADCConvertedValue[index++] = ADC_GetGroupConvDat(0);
ADCConvertedValue[index++] = ADC_GetGroupConvDat(1);
ADCConvertedValue[index++] = ADC_GetGroupConvDat(2);
ADCConvertedValue[index++] = ADC_GetGroupConvDat(3);
ADCConvertedValue[index++] = ADC_GetGroupConvDat(4);
if(index >= 28)
{
index = 0;
}
GPIOB->PBC = GPIO_PIN_7;
}
}
缓冲区大小、回卷阈值与读取的寄存器个数三者要一起改,中断里直接写寄存器是为了缩短耗时。
对应源码: src/main.c、src/n32g033_it.c、firmware/n32g033_std_periph_driver/inc/n32g033_adc.h
5.1.4 注意与排障
| 场景 | 检查与建议 | 来源 |
|---|---|---|
| ADC 工作时钟 | 用户手册 ADC 章写明 ADC_CLK 为 ADC 的工作时钟,最大支持 32 MHz; 调整分频系数时不要超过该频率。 |
用户手册 |
| ADC_1MCLK 频率 | 用户手册 ADC 章写明 ADC_1MCLK 用于内部计时功能且在 RCC 中配置,频率必须配置成 1 MHz。 | 用户手册 |
| 上电后立即启动转换 | 用户手册 ADC 章写明必须等待 PowerUp 过程完成才能进入下一步操作; 可通过查询 ADC_STS 的 RDY 位确认上电是否完成。 |
用户手册 |
| 四段采样通道总数 | 用户手册 ADC 章写明四段采样之和不能超过寄存器数(10 个数据寄存器); 配置超过 10 个通道后只会转换 10 个,多出部分被忽略并产生该段的完成标志。 |
用户手册 |
| 单段采样次数 | 用户手册 ADC 章写明单段采样次数由 ADC_PHCFG 配置,寄存器数值为 0~9 时对应采样次数 1~10,不能超过 10 个。 |
用户手册 |
| 测量 VREFINT | 用户手册 ADC 章写明测量 VREFINT 之前软件必须使能 ADC 内部输入 buffer,并检测 ADC_STS 的 VREFRDY 状态位。 |
用户手册 |
勘误手册 V1.0.0(2025.9.25)针对 A 版芯片,未列出 ADC 相关条目。