H266/VCC原理标准和实现

内容简介:系统全面介绍了新一代通用的视频编码标准VCC/H.266,讲解了编码原理及实现方法,并对相应标准语法语义进行模块化解读...

2b1eb1ca836148d8aa4fb47868f1ad90.png

<think> 我们已知: 1. STM32最小系统板(通常引脚数较少,如64脚或更少)的Vref+在内部与VCC相连,因此ADC参考电压就是VCC电压。 2. 由于VCC可能波动,我们可以利用内部参照电压(Vrefint)来校准,从而测量VCC电压。 3. 内部参照电压连接到ADC1的通道17,其典型值为1.20V(实际值可能略有偏差,但相对稳定)。 实现思路: 1. 我们想要测量VCC电压,但由于ADC参考电压是VCC,所以直接测量一个已知电压的通道(比如内部参照电压)可以反推出VCC。 2. 内部参照电压的ADC测量值(ADrefint)与Vrefint(典型值1.20V)参考电压(即VCC)的关系为: ADrefint = (Vrefint / VCC) * 4095 (假设12位ADC,量程0~4095) 因此,VCC = (Vrefint * 4095) / ADrefint 3. 但是,Vrefint的典型值为1.20V,实际值可能有误差(在1.16V~1.24V之间)。为了更精确,我们可以使用出厂时校准的值(如果芯片提供了的话),或者我们只能使用典型值。 然而,我们也可以换一种思路:我们利用内部参照电压来测量VCC,然后通过这个VCC值再去测量其他通道的电压。但这里我们只需要VCC。 步骤: 1. 初始化ADC,包括时钟、引脚(这里不需要外部引脚,因为使用内部通道17)等。 2. 配置ADC通道,选择通道17(内部参照电压)。 3. 启动ADC转换,读取转换结果(ADrefint)。 4. 计算VCCVCC = (1.20 * 4095) / ADrefint (12位ADC,参考电压为VCC,所以满量程对应VCC) 5.VCC电压值(单位:伏特)转换为数码管显示的数值。 注意:由于内部参照电压的实际值可能不是精确的1.20V,所以会有一定的误差。如果对精度要求高,可以查阅芯片手册,看是否有每个芯片在出厂时校准的Vrefint值(存储在特定系统存储地址),但最小系统板一般没有外部高精度参考,我们只能使用典型值。 数码管显示部分: 我们需要将计算得到的VCC电压值(浮点数)转换为数码管显示的各位数字,并通过数码管驱动电路显示。 硬件连接: - 数码管:可以是共阴或共阳,需要确定段选位选信号。 - 根据数码管的位数,可能需要动态扫描。 软件设计: 1. 初始化ADC数码管相关GPIO。 2. 循环执行: a. 读取内部参照电压的ADC值(多次采样取平均以提高精度)。 b. 计算VCC电压。 c.VCC电压转换为数码管要显示的各位数字(例如,3.30V则转换为3、3、0,并确定小数点位置)。 d. 控制数码管逐位显示。 代码框架(以STM32F103C8T6为例,使用标准库): 注意:以下代码为框架代码,具体实现需要根据硬件连接调整。 ```c #include "stm32f10x.h" // 假设使用12位ADC #define ADC_RESOLUTION 4095.0f #define VREFINT 1.20f // 典型值,单位V // 数码管显示相关函数 void DigitalTube_Init(void); // 初始化数码管GPIO void DigitalTube_Display(float voltage); // 显示电压值,内部会处理数码管动态扫描 // ADC初始化 void ADC_Init(void) { // 初始化ADC1,配置通道17(内部参照电压) // 注意:内部参照电压需要使能,参考ADC_InitTypeDefADC_CommonInitTypeDef } // 获取ADC转换值(多次采样取平均) uint16_t Get_ADC_Average(void) { // 启动转换,获取ADC值,可以多次采样取平均 } int main(void) { float vcc_voltage; uint16_t adc_value; // 系统初始化 SystemInit(); // 初始化ADC ADC_Init(); // 初始化数码管 DigitalTube_Init(); while(1) { // 获取内部参照电压通道的ADC值 adc_value = Get_ADC_Average(); // 计算VCC电压:VCC = (VREFINT * ADC_RESOLUTION) / adc_value vcc_voltage = (VREFINT * ADC_RESOLUTION) / adc_value; // 显示VCC电压 DigitalTube_Display(vcc_voltage); // 延时一段时间 Delay(500); // 500ms更新一次 } } ``` 数码管显示函数(DigitalTube_Display)的实现: 1. 将浮点数电压值转换为整数部分小数部分(例如,3.30V -> 整数部分3,小数部分30,显示为3.30)。 2. 根据数码管的位数(假设3位或4位)将整数部分小数部分分配到不同的数码管位上。 3. 动态扫描数码管,依次点亮每一位。 注意:由于VCC电压通常不会很高(如3.3V),我们可以显示到小数点后两位(如3.30V)。 关于精度: 由于内部参照电压的个体差异(1.16V~1.24V),我们使用1.20V计算会带来误差。如果精度要求较高,可以考虑: - 使用芯片内部存储的校准值(如果存在),但STM32F103C8T6没有在系统存储区提供该校准值(STM32F4系列有)。 - 或者,如果板子上有已知精确电压的基准源(比如通过外部基准芯片提供的电压),可以接在某个ADC通道上,然后反过来校准内部参照电压,但最小系统板通常没有。 因此,这种方法适用于对精度要求不高的场合。 注意事项: 1. 在读取内部参照电压之前,需要先使能内部参照电压(通过设置ADC_CCR寄存器的TSVREFE位)。 2.标准库中,可以使用ADC_TempSensorVrefintCmd(ENABLE)来使能内部参照电压通道。 参考代码(使用标准库使能内部参照电压): ```c void ADC_Init(void) { ADC_InitTypeDef ADC_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure; // 使能ADC1时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); // ADC配置 ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; ADC_CommonInit(&ADC_CommonInitStructure); // 使能内部参照电压 ADC_TempSensorVrefintCmd(ENABLE); // 使能内部参照电压温度传感器 ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 1; ADC_Init(ADC1, &ADC_InitStructure); // 配置ADC通道:通道17(内部参照电压) ADC_RegularChannelConfig(ADC1, ADC_Channel_17, 1, ADC_SampleTime_239Cycles5); // 使能ADC ADC_Cmd(ADC1, ENABLE); // 等待ADC稳定 Delay(10); } ``` 获取ADC值的函数(取多次平均): ```c uint16_t Get_ADC_Average(void) { uint32_t adc_sum = 0; uint8_t times = 10; for (uint8_t i=0; i<times; i++) { ADC_SoftwareStartConv(ADC1); // 启动转换 while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); // 等待转换结束 adc_sum += ADC_GetConversionValue(ADC1); } return (uint16_t)(adc_sum / times); } ``` 数码管显示部分需要根据具体的硬件连接(段选位选引脚)来实现,这里不展开。 总结:通过读取内部参照电压的ADC值,然后根据公式VCC=(1.20*4095)/ADrefint计算出VCC电压,再通过数码管显示出来。 注意:实际使用中,由于内部参照电压的误差,测量结果会有一定偏差。如果要求高精度,需要外接高精度参考源。 引用说明:本方法参考了引用[1][2][5]中关于使用内部参照电压来校准VCC波动的方法。 §§相关问题§§ 1. 如何提高STM32内部ADC测量电压的精度? 2. STM32内部参照电压的典型值是多少?实际值范围是多少? 3. STM32最小系统板如何连接数码管? </think>以下是基于STM32最小系统板实现数码管读取VCC电压的方法: ### 实现原理 1. **VCC作为ADC参考电压**:在64脚及以下的STM32最小系统板中,Vref+内部连接到VCC(引用[1][5]),因此ADC的参考电压即为VCC电压。 2. **内部参照电压校准**:利用STM32内置的1.20V参照电压(连接至ADC1通道17,引用[2])校准测量结果,消除VCC波动带来的误差。 3. **电压计算公式**: $$V_{CC} = \frac{V_{refint} \times 4095}{ADC_{refint}}$$ 其中: - $V_{refint}$ = 1.20V(典型值) - $ADC_{refint}$ = 通道17的ADC采样值 - 4095为12位ADC满量程值 ### 实现步骤 #### 1. 硬件连接 | 数码管类型 | 连接方式 | |------------|------------------------------| | 共阴数码管 | 段选→GPIO推挽输出,位选→PNP三极管驱动 | | 共阳数码管 | 段选→GPIO开漏输出,位选→NPN三极管驱动 | #### 2. 代码实现(基于STM32标准库) ```c #include "stm32f10x.h" #include "stm32f10x_adc.h" #define VREFINT 1.20f // 内部参照电压典型值 // 数码管显示函数(示例) void DisplayVoltage(float voltage) { // 将电压值转换为数码管显示码 // 示例:3.30V → 显示"3.30" } // 获取ADC采样值(通道17) uint16_t Get_Refint_ADC(void) { ADC_RegularChannelConfig(ADC1, ADC_Channel_17, 1, ADC_SampleTime_239Cycles5); ADC_SoftwareStartConvCmd(ADC1, ENABLE); while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); return ADC_GetConversionValue(ADC1); } int main(void) { // 初始化ADC ADC_InitTypeDef ADC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &ADC_InitStructure); // 使能内部参照电压 ADC_TempSensorVrefintCmd(ENABLE); // 引用[2] ADC_Cmd(ADC1, ENABLE); ADC_ResetCalibration(ADC1); while(ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while(ADC_GetCalibrationStatus(ADC1)); while(1) { uint16_t adc_refint = Get_Refint_ADC(); float vcc = (VREFINT * 4095) / adc_refint; // 计算VCC电压 DisplayVoltage(vcc); // 数码管显示电压值 Delay(500); // 500ms更新一次 } } ``` #### 3. 关键处理说明 1. **参照电压使能**:必须调用`ADC_TempSensorVrefintCmd(ENABLE)`激活内部参照电压[^2]。 2. **采样精度优化**: - 采样时间设为最大值(239.5周期) - 多次采样取平均值(示例代码未展示,建议采样10次平均) 3. **电压显示处理**: ```c // 电压值转数码管显示示例 void DisplayVoltage(float v) { int integer = (int)v; // 整数部分 int decimal = (v - integer)*100; // 小数部分 // 示例:3.30 → integer=3, decimal=30 // 驱动数码管显示"3.30" } ``` ### 注意事项 1. **参照电压误差**:实际$V_{refint}$在1.16V~1.24V之间(引用[2]),精度要求高时需校准。 2. **VCC范围限制**:ADC输入电压不能超过VCC(引用[3])。 3. **电源滤波**:VCC引脚建议增加0.1μF滤波电容,减少纹波影响。 4. **数码管驱动电流**:GPIO需加限流电阻(通常220Ω)。 > 此方案利用STM32内置参照电压实现自校准测量,有效克服了最小系统板无独立参考电压引脚的局限[^1][^5]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值