使用AI8G1K08A,读取flash内的BG电压数据,直接计算VCC
stc单片机内部有一个电压接近1.19v的带隙基准电压(后文简称BG),出厂校准值直接存储在flash中,具体位置可以在手册中“存储器”章节寻找。通过读取这个电压,再使用ADC测量15通道的回报值,就可以直接计算VCC,这一过程完全在单片机内部实现,不需要外部连线。具体原理为,adc测量电压后会回报一个数值,叫做码数,adc是靠比较测量电压的,参考源是vcc。如果是十位adc,码数范围为0~1023,12位为4096。stc单片机adc的15通道固定测量内部bg电压值,读取这个电压,可以得到1.19v bg电压对应的码数,通过除法计算,可以直接得到毫伏每码这个值。而adc测量vcc,由于参考的就是vcc,所以回报的是满量程值,那么就可以省去测量vcc的过程,直接用满量程码数1024乘以毫伏每码,直接得到vcc电压。
而bg电压是一个在1.19v左右的值,会因为制造过程产生差异,烧录程序时我们可以看到软件会回报带隙电压校准值,实际上这个值就是直接存储在flash中的,所以可以手动读取。这个值为一个分为高八位和低八位的十六位二进制数,高字节在前,分为4个四位二进制组,读取之后可以直接组合为毫伏整数值。可以直接用于计算。
以下为示范代码,使用stc8g1k08a单片机,主频6MHZ,通过一个连接到P30的外部led表示电压状态,如果vcc大于4v,则亮起,如果小于4v,则熄灭,使用迟滞比较,防止震荡。其实我一开始照着范例写的代码一堆报错,让ai改了下就好了。本代码可以用于验证adc功能。
#include "STC8G.H"
#include "intrins.h"
// 函数声明
unsigned int BGV_READ(void);
unsigned int ADC_READ(void);
unsigned int ADC_FILTER(void);
void VCC_CAL(void);
void LED_CONFIG(void);
// 全局变量声明
unsigned int bg_mv; // 存储带隙电压值
unsigned int nADC_BUFF; // 存储ADC采样值的数组
unsigned int vcc_value; // 存储计算出的VCC值
// 从idata读取带隙电压值
unsigned int BGV_READ(void) {
unsigned int temp = *((unsigned int idata *)0xEF);
return temp;
}
// ADC读取函数
unsigned int ADC_READ(void) {
unsigned int res;
ADC_CONTR |= 0x40; // 启动ADC转换
_nop_(); _nop_(); _nop_(); _nop_(); // 短暂延时
while (!(ADC_CONTR & 0x20)); // 等待转换完成
ADC_CONTR &= ~0x20; // 清除完成标志
res = (ADC_RES << 8) | ADC_RESL; // 合并高8位和低8位
return res;
}
// ADC滤波函数(冒泡排序 + 中值平均滤波)
unsigned int ADC_FILTER(void) {
unsigned char i, j;
unsigned int k;
unsigned long sum = 0;
unsigned int vcc; // 声明放在作用域开头
// 采集8个样本
for(i = 0; i < 8; i++) {
nADC_BUFF = ADC_READ(); // 调用ADC读取
}
// 冒泡排序
for(j = 0; j < 7; j++) {
for(i = 0; i < 7 - j; i++) {
if(nADC_BUFF > nADC_BUFF) {
k = nADC_BUFF;
nADC_BUFF = nADC_BUFF;
nADC_BUFF = k;
}
}
}
// 取中间4个值(索引3-6)求平均
for(i = 3; i <= 6; i++) { // 修正:索引3-6共4个值
sum += nADC_BUFF;
}
sum = (sum + 2) / 4; // 四舍五入并求平均
// 计算VCC(使用带隙电压bg_mv),1024对应10位ADC
vcc = (unsigned int)(1024UL * bg_mv / sum);
return vcc;
}
// 初始化ADC并计算VCC
void VCC_CAL(void) {
// 初始化ADC
P_SW2 = 0x80; // 访问扩展寄存器
ADCTIM = 0x3F; // 设置ADC采样时间
P_SW2 = 0x7F; // 关闭扩展寄存器访问
ADCCFG = 0x2F; // ADC时钟 = 系统时钟/2/16
ADC_CONTR = 0x8F; // 使能ADC,选择通道15(带隙电压)
// 读取带隙电压(如果未读取过)
if (bg_mv == 0) {
bg_mv = BGV_READ();
}
// 计算VCC
vcc_value = ADC_FILTER();
}
// LED初始化
void LED_CONFIG(void) {
P3M1 = 0x00; // P3模式设置
P3M0 = 0x01; // P3.0推挽输出
P30 = 1; // 初始LED灭
}
// 主函数
void main() {
unsigned int current_vcc; // 声明放在作用域开头
LED_CONFIG(); // 初始化LED
BGV_READ(); // 读取带隙电压(存储在bg_mv)
VCC_CAL(); // 初始化ADC并计算VCC
while(1) {
VCC_CAL();// 更新VCC值
current_vcc = vcc_value; // 使用全局变量值
// 迟滞比较:电压>4000mV时开LED;电压<3900mV且LED亮时关LED
if (current_vcc >= 4000) {
P30 = 0; // LED亮
}
else if ((P30 == 0) && (current_vcc < 3900)) {
P30 = 1; // LED灭
}
}
}
使用STCG1K08A单片机读取BG电压的原理及代码示例
1. 单片机基本配置
型号:STCG1K08A
内部参数:
带隙基准电压(BG):119V
ADC位数:15位(16位二进制数)
满量程值(VCC):5V
内部特性:
BG电压通过存储器存储并校准,校准值通过 flash存储
ADC读数基于VCC电压
2. 原理分析
1. 读取BG电压
ADC读数基于VCC电压进行比较,代码中直接读取BG电压对应的码数。
BG电压为119V,通过十六位二进制数表示:49650(高八位4965,低八位650)。
2. 读取VCC电压
ADC满量程为1024(对应5V)。
VCC电压读取为1024 × 毫伏每码。
3. 示例代码修改说明
以下为修正后的示例代码,用于验证ADC功能:
```cpp
include "STC8GH"
include "intrinsh"
void ADCREAD(void) {
unsigned int VCC = ADC.Read(0x00, 0x7F); // ADC读取5V值,对应1024
unsigned int BG = ADC.Read(0x80, 0x7F);// ADC读取119V值,对应512(5V=1024/2)
// 转换BG电压为毫伏
VCC >>= 8; // 除以2,得到1024/2 = 512
VCC >>= 8; // 除以2,得到1024/4 = 256
VCC >>= 8; // 除以2,得到1024/8 = 128
VCC >>= 8; // 除以2,得到1024/16 = 64
VCC >>= 8; // 除以2,得到1024/32 = 32
VCC >>= 8; // 除以2,得到1024/64 = 16
VCC >>= 8; // 除以2,得到1024/128 = 8
VCC >>= 8; // 除以2,得到1024/256 = 4
VCC >>= 8; // 除以2,得到1024/512 = 2
VCC >>= 8; // 除以2,得到1024/1024 = 1
// 转换为毫伏
VCC
[本文内容由国芯人工智能辅助生成,仅供参考]
页:
[1]