|
samxon 发表于 2026-1-6 09:13
|
samxon 发表于 2026-1-5 11:12 假设 0x04D7 (十进制:1239) 是间隙基准源的电压值 (1239mV),则读取这个电压值的代码可以改成:
“adc_val 值是 0x02” :这个数据应该是双字节,所以这个数据是有问题的。假设完整的数据是 adc_val = 0x0102 (十进制:258),则电源电压的值为:1.239V * 1023 / 258 = 4.9128 V 。 即 adc_val = 0x0102 是在 Vcc = 4.9128V 时,测量间隙基准源电压所得到到 ADC 读数。 参考 11# 的说明。 |
samxon 发表于 2025-12-29 19:24 如果read_bandgap_voltage()读到的0x4d7是Vbg的mV数,那么这句: (long)(read_bandgap_voltage()*1024)/adc_val); 就是对的,现在的问题是adc_val应该在255左右,检查下为什么这个值错的离谱吧! |
samxon 发表于 2026-1-5 11:12 STC15W408AS 读取0xef 的值为0x04D7,你凭什么说 明显是 1239mv。你根据什么理由或资料证明地址0xef 里的数据是内部参考电压值?STC15W用户手册哪里有此说明?官方示例程序也没有类似应用。不可能凭空找一个数据就能得到正确结果。 |
WL0123 发表于 2026-1-4 16:37 STC15W408AS 读取0xef 的值为0x04D7, 明显是 1239mv,这个应该怎样处理。谢谢。 #define ID_ADDR_RAM 0xef //BandGap地址 unsigned int read_bandgap_voltage(){ return (*(unsigned char idata *)ID_ADDR_RAM <<8) |*(unsigned char idata *)(ID_ADDR_RAM + 1); } |
samxon 发表于 2026-1-4 09:43 10-位 ADC 的值范围为 0x0000 ~ 0x03FF。0x04D7 不是一个有效的 ADC 数据。 说明: ① 数据本身错误,或者 ② read_bandgap_voltage() 中的代码有问题。 |
发表于 2026-1-4 12:59 STC15W408AS的EEPROM共有10个扇区,各扇区首地址分别为0x0000、0x0200、0x0400......。BGV就2个字节的数据,只要没搞错你爱存哪里都可以。BGV不是凭空来的,必须是此芯片在某特定电源电压下测得的。这与STC8系列有所不同。STC8系列出厂时已将内部1.19V参考信号源电压值保存在指定地址:BGV = (int idata *)0xef;,前者保存的是ADC转换值,后者保存的是电压值,易混淆。后期处理不当会出错。 |
|
这个读取BGV 的地址为什么不是0xef ,而是0x0000呢 我定义的地址是#define ID_ADDR_RAM 0xef //BandGap地址 #define IAP_ADDRESS 0x0000 //测试地址 |
Jack315 发表于 2026-1-3 11:04 串口打印出来, adc_val值是0x02, read_bandgap_voltage()值是0x04D7, 反正最后得到的就不是VCC的真实电压。谢谢。 |
samxon 发表于 2026-1-2 17:37
测量ADC的第9通道推算VCC电压计算INV.rar
(19.65 KB, 下载次数: 0)
|
|
中断函数 adc_isr() 中: adc_val 值是多少? read_bandgap_voltage() 函数的返回值是多少? 最后得到的 vcc_voltage 是多少? 能不能上传一个 STC15W408AS 的数据手册,或给个链接。 想具体看看 BandGap 和 ADC 相关部分的硬件结构和编程信息。 |
Jack315 发表于 2026-1-2 01:14 VCC供电是5V, 以下代码还是无法获取到真实电压值。请大家帮忙看看是什么问题导致的。 void AdInit() { P1ASF = 0x00; ADC_RES = 0; ADC_RESL = 0; CLK_DIV = 0x20; ADC_CONTR = 0x88; _nop_();_nop_(); ADC_CONTR |= 0x08; delay_ms(20); EADC = 1; } unsigned int read_bandgap_voltage(){ return (*(unsigned char idata *)ID_ADDR_RAM <<8) |*(unsigned char idata *)(ID_ADDR_RAM + 1); } void adc_isr() interrupt 5{ uint adc_val=(ADC_RES*256+ADC_RESL); uint vcc_voltage=5.0*((float)read_bandgap_voltage()/(float)adc_val); P1ASF=0x00; ADC_CONTR = 0x88|0x00; _nop_();_nop_();_nop_();_nop_(); //等待四个机器周期 while(!(ADC_CONTR&ADC_FLAG)); ADC_CONTR &=~ADC_FLAG; } |
|
测量 VCC 的步骤: ① 给定一个比较精确的电源电压 VCCA ,得到 BandGap (间隙基准源)的 ADC 读数 BGVA。据此可计算出 BandGap 的基准电压 VBG 。 ② 当电源电压为 VCCX 时,得到另一个 BandGap 的 ADC 读数为 BGVX。则 VCCX = BGVX * VBG / BGVA 。 10 位 ADC 的值范围为:0x000 ~ 0x3FF (十进制:0~1023)。 假设 VCCA = 5.00V,间隙基准源的基准电压为 VBG = 1.25V,则 BGVA 的值为:1.25V / 5.00V * 1023 = 255.75。 四舍五入得到 256。即此时的 ADC 读数应为 BGVA = 0x100 (十进制:256)。 假设在待测电源电压下 BandGap 的 ADC 读数为 BGVX = 0x266 (十进制:614), 则 VCCX = BGVX * VBG / BGVA = 614 * 1.25 / 256 = 2.998V 【说明】 ① 注意到测量 VBG 时,ADC 的量化作用导致了测量误差:5.00V * 256 / 1023 = 1.251222V 。为提高测量精度,可用不同的 VCCA 进行测量,然后对计算出的 VBG 值求平均作为 VBG 的 “精确” 值。 ② 注意到 10位 ADC 的读数需要三个 Nibble(半字节),比较方便的类型为双字节的无符号整数(可以定义为 UInt16)。 以上述假设的数据为例: UInt16 BGVA = 0x0100、UInt16 BGVX = 0x0266、float VBG = 1.25; float VCCX = (float) BGVX * VBG / (float) BGVA 。 假设要用 UInt16 来表示 VCCX ,可以先将 VCCX 乘以一个适当的常数 (float) C,以保留足够的输出精度: UInt16 Result = (UInt16) (VCCX * C) 。 若最大 VCCA = 5.5V 时,输出为 0xFFFF,则 C 可取为 65535 / 5.5 = 11915.4545454545 。 |
samxon 发表于 2025-12-29 19:24 // 当前VCC_mV = 标准电压mV * 标准电压BandGap转换值 / 当前电压BandGap转换值 VCC = 5000 * (long)BGV5 / BGVx; |
shuiquan3 发表于 2025-12-29 21:55 A/D 转换模块的参考电压源 STC15 系列单片机的参考电压源是输入工作电压 Vcc,所以一般不用外接参考电压源。如 7805 的输 出电压是 5V,但实际电压可能是 4.88V 到 4.96V,用户需要精度比较高的话,可在出厂时将实际测出的 工作电压值记录在单片机内部的 EEPROM 里面,以供计算。 如果有些用户的 Vcc 不固定,如电池供电,电池电压在 5.3V--4.2V 之间漂移,则 Vcc 不固定,就需 要在 8 路 A/D 转换的一个通道外接一个稳定的参考电压源,来计算出此时的工作电压 Vcc,再计算出其 他几路 A/D 转换通道的电压。如下图所示,可在 ADC 转换通道的第二通道外接一个 2.5V( 或 1V,或...) 的基准参考电压源,由此求出此时的工作电压 Vcc,再计算出其它几路 A/D 转换通道的电压( 理论依据 是短时间之内, Vcc 不变)。
|
| 这里提出另外一个问题:计算读取的电压时,1024应该为1023,STC手册中给出的是1024,也是错误的。请大家讨论。 |
| 请教:stc15w408as如何使用外部基准电压? |
| 请教:STC15W408AS如何使用外部基准电压,接哪个引脚,还是P1口随便接? |
| 保存在 RAM 的 基准点压参考值,开机后有可能被改写,建议从 CODE中读取。 或者,开机后,优先读取 RAM中的参考值,再执行其他代码。 |
|
经过反复排查 void adc_isr() interrupt 5{ ADC_CONTR &= ~0x10; uint vcc_voltage=(float)(5.0*bandgap/adc_val); 串口打印出来 bandgap是D7, adc_val是02, vcc_voltage结果是十进制24, 为什么vcc_voltate不是十进制537呢。 |
| 添加一个基准电压再采样计算 |
| 添加一个基准电压比较再采集计算 |