5.31 VREFBUF 使用说明
本章说明 N32H49x 标准外设库中 VREFBUF 驱动的文件组成与 6 个公开函数,以及 ADC_VREFBUF 示例。VREFBUF 是芯片内置的电压参考缓冲器,可为 ADC、12 位 DAC 或外部组件提供 2.048 V、2.5 V、2.9 V 三档基准;输出模式与外部输入模式的区分、高阻配置与使能顺序请配合用户手册的“电压参考缓冲器(VREFBUF)”章节阅读。
5.31.1 相关文件
| 相对路径 | 作用 |
|---|---|
firmware/n32h49x_std_periph_driver/inc/n32h49x_vrefbuf.h |
定义电压档位与寄存器掩码,声明 6 个公开函数 |
firmware/n32h49x_std_periph_driver/src/n32h49x_vrefbuf.c |
实现上述 6 个函数:使能与高阻控制、档位选择与出厂修调取值、修调使能与修调码写入、就绪状态读取 |
projects/n32h49x_EVAL/examples/VREFBUF/ |
VREFBUF 示例根目录,含 ADC_VREFBUF 1 个示例 |
projects/n32h49x_EVAL/examples/VREFBUF/ADC_VREFBUF/ |
该示例的工程目录组成:MDK-ARM/、EWARM/、inc/、src/、readme.txt |
projects/n32h49x_EVAL/bsp/ |
该示例引用的公共板级文件:串口日志函数 |
5.31.2 API 参考
以下 6 个公开函数按 n32h49x_vrefbuf.h 的声明顺序分为 3 组;每个条目给出功能摘要与 n32h49x_vrefbuf.c 中该函数正上方的注释原文。
使能与高阻
VREFBUF_Enable、VREFBUF_EnableHIM
电压档与修调
VREFBUF_SetVoltageScale、VREFBUF_EnableTrim、VREFBUF_SetTrimming
状态
VREFBUF_IsVREFReady
void VREFBUF_Enable(FunctionalState Cmd)使能或关闭内部电压基准。
name VREFBUF_Enable.
fun Enable or disable internal voltage reference.
param Cmd :
- ENABLE
- DISABLE
return none
void VREFBUF_EnableHIM(FunctionalState Cmd)使能或关闭高阻模式(VREF+ 引脚呈高阻)。
name VREFBUF_EnableHIM.
fun Enable or disable high impedance (VREF+ pin is high impedance).
param Cmd :
- ENABLE
- DISABLE
return none
void VREFBUF_SetVoltageScale(uint32_t Scale)设置电压基准档位。
name VREFBUF_SetVoltageScale.
fun Set the Voltage reference scale.
param Scale
- VREFBUF_VOLTAGE_SCALE_2_048V
- VREFBUF_VOLTAGE_SCALE_2_5V
- VREFBUF_VOLTAGE_SCALE_2_9V
return none
使用提示: 实现先按档位从出厂校准区取修调值写入 VREFBUF_TRIM,再修改 RCC->VREFCTRL 中的档位选择位;调用前函数会自行使能 PWR 时钟。
void VREFBUF_EnableTrim(FunctionalState Cmd)使能或关闭 VREFBUF 修调。
name VREFBUF_EnableTrim.
fun Enable or disable VREFBUF triming.
param Cmd :
- ENABLE
- DISABLE
return none
void VREFBUF_SetTrimming(uint32_t Value)设置 VREFBUF 校准的修调码。
name VREFBUF_SetTrimming.
fun Set the trimming code for VREFBUF calibration.
param Value :Value Between 0 and 0x3F
return none
FlagStatus VREFBUF_IsVREFReady(void)检查 VREFBUF 就绪标志是否置位。
name VREFBUF_IsVREFReady.
fun Checks whether VREFBUF ready flag is set or not.
param none
return The new state of VREFBUF_READY (SET or RESET).
5.31.3 Demo 示例说明
本节说明 VREFBUF 的 1 个示例:ADC_VREFBUF 以输出模式配置 VREFBUF 输出 2.5 V 基准,并用 ADC1 的 VREFINT 通道采样 VREF+。
5.31.3.1 ADC_VREFBUF VREFBUF 基准电压采样
工程目录: projects/n32h49x_EVAL/examples/VREFBUF/ADC_VREFBUF/
配置系统与 ADC 时钟→把模拟输入引脚设为模拟模式→初始化 ADC 并执行校准→以输出模式配置 VREFBUF 电压档并等待就绪→主循环反复采样 VREFINT 通道
| 项目 | 源码解读 |
|---|---|
| 功能 | 以输出模式配置 VREFBUF 输出 2.5 V 基准,并等待 VREFBUF_CTRL.RDY 就绪;ADC1 通过内部通道 ADC1_Channel_18_VREFINT 采样 VREF+,转换结果周期性存入 ADC1ConvertedValue[0]。 |
| 源码组成 | src/main.c:main、RCC_Configuration、GPIO_Configuration、ADC_Initial、VREFBUF_CONFIG、ADC_GetData;inc/main.h:包含 n32h49x_adc.h、n32h49x_vrefbuf.h、n32h49x_rcc.h、n32h49x_gpio.h;src/n32h49x_it.c、inc/n32h49x_it.h:中断服务函数(仅异常处理);readme.txt:功能、环境与使用说明;MDK-ARM/、EWARM/:Keil 与 IAR 工程。 |
| 关键配置 | 时钟:ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB, RCC_ADCHCLK_DIV16),RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSI, RCC_ADC1MCLK_DIV8);引脚:PA1、PA2 设为模拟输入; 基准: VREFBUF_MODE_OUTPUT 配 VREFBUF_VOLTAGE_SCALE_2_5V,并调用 VREFBUF_EnableHIM(DISABLE);ADC:独立模式、12 位分辨率、软件触发,采样时间 ADC_SAMP_TIME_CYCLES_239_5。 |
| 程序与数据路径 | main 依次调用 RCC_Configuration、GPIO_Configuration、ADC_Initial(ADC1);ADC_Initial 配置转换参数、使能内部 VREFINT 通道、使能 ADC 并等待 ADC_FLAG_RDY、执行单次校准;VREFBUF_CONFIG 打开输出模式、设置 2.5 V 档、关闭高阻、使能并等待 VREFBUF_IsVREFReady;while(1) 用 ADC_GetData(ADC1, ADC1_Channel_18_VREFINT) 反复采样 VREF+。 |
| 主要 API | VREFBUF_SetVoltageScale、VREFBUF_EnableHIM、VREFBUF_Enable、VREFBUF_IsVREFReady |
| 验证方法 | 编译下载运行后,用调试器观察 ADC1ConvertedValue[0],其码值对应约 2.5 V 的 VREF+ 采样结果;也可用万用表在 VREF+ 引脚测量,读数接近 2.5 V 说明输出正常。 |
| 使用提示 | 硬件开发环境为全功能板 N32H497ZGL7_EVB V1.0; 开发环境为 KEIL MDK-ARM 5.34 或 IAR EWARM 8.50.1; VREF+ 引脚须就近外接 100 nF 去耦电容; 示例通过直接写 VREFBUF_EN_CTRL(地址 0x40010020)的 bit10 切换输出与输入模式。 |
核心代码解读与移植
示例先配置系统与 ADC 时钟、模拟输入引脚并完成 ADC 校准,再以输出模式配置 VREFBUF 的电压档并等待就绪,最后在主循环中反复采样 VREFINT 通道。
数据路径: RCC_Configuration 配置 GPIO 与 ADC 时钟 → GPIO_Configuration 把 PA1、PA2 设为模拟输入 → ADC_Initial 使能 VREFINT 通道并校准 → VREFBUF_CONFIG 写 VREFBUF_TRIM、RCC->VREFCTRL 并等待就绪 → ADC_GetData 采样 VREFINT 存入 ADC1ConvertedValue
1. 配置系统与 ADC 时钟。 RCC_Configuration 使能 GPIOA~GPIOD、ADC1 的时钟,并把 ADC 工作时钟设为 AHB 分频、ADC1M 时钟源设为 HSI。
/* Enable peripheral clocks ------------------------------------------------*/
/* Enable GPIOA, GPIOB, GPIOC ,GPIOD clocks */
RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOA | RCC_AHB_PERIPHEN_GPIOB | RCC_AHB_PERIPHEN_GPIOC | RCC_AHB_PERIPHEN_GPIOD, ENABLE);
/* Enable ADC1 clocks */
RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_ADC1 ,ENABLE);
/* RCC_ADCHCLK_DIV16*/
ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB,RCC_ADCHCLK_DIV16);
RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSI, RCC_ADC1MCLK_DIV8); //selsect HSI as RCC ADC1M CLK Source
移植到其它型号时可裁剪未使用的 GPIO 时钟,但 ADC1 时钟与 ADC_ConfigClk、RCC_ConfigAdc1mClk 的配置要保持一致。
2. 配置模拟输入引脚。 GPIO_Configuration 把 PA1、PA2 配置为模拟模式,供 ADC 采样。
void GPIO_Configuration(void)
{
GPIO_InitType GPIO_InitStructure;
/* Configure PA1 PA2 as analog input -----------------------*/
GPIO_InitStructure.Pin = GPIO_PIN_1 | GPIO_PIN_2;;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_ANALOG;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
}
移植到其它板卡时改 GPIO_InitStructure.Pin 与实际使用的通道引脚即可,采样内部 VREFINT 通道本身不占用外部引脚。
3. 初始化 ADC 并校准。 ADC_Initial 配置独立模式、12 位分辨率与软件触发,使能内部 VREFINT 通道,等待 ADC_FLAG_RDY 后执行单次校准。
void ADC_Initial(ADC_Module* ADCx)
{
/* ADCx configuration ------------------------------------------------------*/
ADC_InitStructure.WorkMode = ADC_WORKMODE_INDEPENDENT;
ADC_InitStructure.MultiChEn = DISABLE;
ADC_InitStructure.ContinueConvEn = DISABLE;
ADC_InitStructure.ExtTrigSelect = ADC_EXT_TRIG_REG_CONV_SOFTWARE;
ADC_InitStructure.DatAlign = ADC_DAT_ALIGN_R;
ADC_InitStructure.ChsNumber = 1;
ADC_InitStructure.Resolution = ADC_DATA_RES_12BIT;
ADC_Init(ADCx, &ADC_InitStructure);
ADC_EnableTempSensorVrefint(ENABLE);
/* Enable ADCx */
ADC_Enable(ADCx, ENABLE);
/*Check ADC Ready*/
while(ADC_GetFlagStatus(ADCx,ADC_FLAG_RDY) == RESET)
;
/* Start ADCx calibration */
ADC_CalibrationOperation(ADCx,ADC_CALIBRATION_SINGLE_MODE);
/* Check the end of ADCx calibration */
while (ADC_GetCalibrationStatus(ADCx,ADC_CALIBRATION_SINGLE_MODE))
;
}
移植时要保留等待就绪与等待校准结束的空循环,缺少这两步会使转换结果不可靠。
4. 配置并启动 VREFBUF。 VREFBUF_CONFIG 在输出模式下先写 VREFBUF_EN_CTRL 的 bit10 选择内部基准,再依次设置电压档、关闭高阻、使能并等待就绪;输入模式则相反。
if(VrefBufferMode == VREFBUF_MODE_OUTPUT)
{
*(uint32_t *)VREFBUF_EN_CTRL |= (1<<10);
VREFBUF_SetVoltageScale(voltage);
VREFBUF_EnableHIM(DISABLE);
VREFBUF_Enable(ENABLE);
while(VREFBUF_IsVREFReady() == RESET);
}
else
{
*(uint32_t *)VREFBUF_EN_CTRL &= (~(1<<10));
VREFBUF_EnableHIM(ENABLE);
VREFBUF_Enable(DISABLE);
}
使用输出模式时必须先关闭高阻(HIM = 0)再使能,否则 VREF+ 不会输出内部基准电压。
5. 主循环采样 VREFINT。 main 完成上述初始化后,在 while(1) 中用 ADC_GetData 反复采样 ADC1_Channel_18_VREFINT。
int main(void)
{
/* System clocks configuration ----------------------------------------------*/
RCC_Configuration();
/* GPIO configuration -------------------------------------------------------*/
GPIO_Configuration();
/* ADC1 configuration -----------------------------------------*/
ADC_Initial(ADC1);
VREFBUF_CONFIG(VREFBUF_MODE_OUTPUT,VREFBUF_VOLTAGE_SCALE_2_5V);
while (1)
{
ADC1ConvertedValue[0]=ADC_GetData(ADC1,ADC1_Channel_18_VREFINT);
}
}
ADC_GetData 每次采样前重新配置规则通道并启动软件转换,适合轮询观测 VREF+ 的变化。
对应源码: src/main.c
5.31.4 注意与排障
| 场景 | 检查与建议 | 来源 |
|---|---|---|
| 输出模式与外部输入模式 | 输出模式与外部输入模式只能二选一,严禁在内部输出时同时开启外部输入。 | 用户手册 |
| VREF+ 与 VDDA 连接 | 若封装中把 VREF+ 引脚与 VDDA 连在一起,电压参考缓冲器不可用,必须保持禁用并把 VREFBUF_CTRL.HIM 置 1。 |
用户手册 |
| 使能顺序与就绪 | 先把 VREFBUF_CTRL.HIM 配置为 0,再置 VREFBUF_CTRL.EN 为 1;必须等待 VREFBUF_CTRL.RDY 置位(输出达到预期值的 90%)后再使用基准电压。 |
用户手册 |
| 电压约束 | VREF+ 的输入电压不能超过 VDDA; VREFBUF 使能后,VREF+ 管脚不能外接电压。 |
用户手册 |
| VREF- 连接 | VREFBUF 工作时 VREF- 默认连接 VSSA。 | 用户手册 |
| 去耦电容 | 100 nF 滤波电容很重要,PCB 设计上需要与 VREF+ 管脚尽量靠近。 | 用户手册 |
| 修调数据 | 每次重启 VREFBUF 或更改档位时,校准数据会自动加载到 VREFBUF_CTRL.TRIMDATA[5:0];直接改写 TRIMDATA[5:0] 后需置位 TRIMEN 使新修调生效,此后档位设置不再影响该寄存器,除非器件复位。 |
用户手册 |