打印
[IoT技术交流]

N76E003 Bandgap 校准后仍不准的原因

[复制链接]
944|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Elex|  楼主 | 2020-5-15 16:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
N76E003 bandgap  可以通过读取UID后面两位校准,我最近发现通过bandgap反推VDD有时在校准后误差更大了。网上找资料找了一大轮,根本找不到原因说明,只看到一堆人吐槽N76E003 bandgap不准。用了好多块万用表来测量都可以确定是bandgap校准后测量不准。后来,终于在某个例程里发现UID后面的校准数据根本不是数据手册那么简单。校准数据需要分三种情况,
1,(UID[0x0d] & 0xF0) == 0x00 时,  bandgapValue = (UID[0x0c] )<< 4 +  (UID[0x0d] & 0x0F);
2,(UID[0x0d] & 0xF0) == 0x80 时,  bandgapValue = (UID[0x0c] )<< 4 +  (UID[0x0d] & 0x0F)- 44;
3,(UID[0x0d] & 0xF0) == 0x90 时,  bandgapValue = (UID[0x0e] )<< 4 +  (UID[0x0f] & 0x0F;

按这3种情况校准bandgap,测量数据就基本上很准确了。都是数据手册说的不清楚的坑呀!

使用特权

评论回复
沙发
奔跑的牛| | 2020-5-15 17:38 | 只看该作者
谢谢你的总结

使用特权

评论回复
板凳
奔跑的牛| | 2020-5-15 17:38 | 只看该作者
谢谢你的总结

使用特权

评论回复
地板
鱿鱼丝| | 2020-5-15 17:41 | 只看该作者
不是数据手册那么简单。

使用特权

评论回复
5
tianxj01| | 2020-5-15 18:00 | 只看该作者
很准确?到多少精度?
假定官方内部实测数据完全准确无误差,则实际量化误差按照官方的数据,以典型的中心值1600计算,则精度为1/1600=0.6‰。不知道你这个方法校准后数据是多少?

使用特权

评论回复
6
tianwufeng| | 2020-5-16 08:56 | 只看该作者
官方实例已经写了,手册和实例我感觉还是相信实例吧!实例很准

使用特权

评论回复
7
qjp1988113| | 2020-5-17 16:30 | 只看该作者
谢谢楼主分享,哪天试一下。

使用特权

评论回复
8
pigluffy| | 2020-5-17 16:51 | 只看该作者
感謝分享

使用特权

评论回复
9
heisexingqisi| | 2020-5-17 21:29 | 只看该作者
可以试试实例。

使用特权

评论回复
10
643757107| | 2020-5-17 22:38 | 只看该作者
不校准误差多大?

使用特权

评论回复
11
jasontu| | 2020-5-19 11:27 | 只看该作者
在bsp有例子,
https://github.com/OpenNuvoton/N76E003-BSP/blob/master/Sample_Code/ADC_Bandgap_VDD_noDelay/Code/ADC_BG_VDD_avg_new.c
读出bandgap, 并转成vdd
uid里面应该写的是校正值

使用特权

评论回复
12
antusheng| | 2020-5-19 20:47 | 只看该作者
没操作对?

使用特权

评论回复
13
dongnanxibei| | 2020-5-19 23:49 | 只看该作者
宝贵经验啊,666

使用特权

评论回复
14
dongnanxibei| | 2020-5-19 23:58 | 只看该作者
/*---------------------------------------------------------------------------------------------------------*/
/*                                                                                                         */
/* Copyright(c) 2016 Nuvoton Technology Corp. All rights reserved.                                         */
/*                                                                                                         */
/*---------------------------------------------------------------------------------------------------------*/

//***********************************************************************************************************
//  Nuvoton Technoledge Corp.
//  Website: http://www.nuvoton.com
//  E-Mail : MicroC-8bit@nuvoton.com
//  Date   : Apr/21/2016
//***********************************************************************************************************

//***********************************************************************************************************
//  File Function: N76E885 ADC demo code
//***********************************************************************************************************

#include "N76E003.h"
#include "SFR_Macro.h"
#include "Function_define.h"
#include "Common.h"
#include "Delay.h"

//*****************  The Following is in define in Fucntion_define.h  ***************************
//****** Always include Function_define.h call the define you want, detail see main(void) *******
//***********************************************************************************************
#if 0
//#define Enable_ADC_BandGap        ADCCON0|=SET_BIT3;ADCCON0&=0xF8;                                                                                                                                                                                                                                                        //Band-gap 1.22V
#endif

double  Bandgap_Voltage,VDD_Voltage;                        //please always use "double" mode for this
unsigned  char xdata ADCdataH[5], ADCdataL[5];
int ADCsumH=0, ADCsumL=0;
unsigned char ADCavgH,ADCavgL;

void READ_BANDGAP()
{
                UINT8 BandgapHigh,BandgapLow,BandgapMark;
                double Bandgap_Value,Bandgap_Voltage_Temp;
       
                set_IAPEN;
                IAPCN = READ_UID;
                IAPAL = 0x0d;
    IAPAH = 0x00;
    set_IAPGO;
                BandgapLow = IAPFD;
                BandgapMark = BandgapLow&0xF0;
                       
                if (BandgapMark==0x80)
                {
                                BandgapLow = BandgapLow&0x0F;
                                IAPAL = 0x0C;
                                IAPAH = 0x00;
                                set_IAPGO;
                                BandgapHigh = IAPFD;
                                Bandgap_Value = (BandgapHigh<<4)+BandgapLow;
                                Bandgap_Voltage_Temp = Bandgap_Value*3/4;
                                Bandgap_Voltage = Bandgap_Voltage_Temp - 33;                        //the actually banggap voltage value is similar this value.
                }
                if (BandgapMark==0x00)
                {
                                BandgapLow = BandgapLow&0x0F;
                                IAPAL = 0x0C;
                                IAPAH = 0x00;
                                set_IAPGO;
                                BandgapHigh = IAPFD;
                                Bandgap_Value = (BandgapHigh<<4)+BandgapLow;
                                Bandgap_Voltage= Bandgap_Value*3/4;
                }
                if (BandgapMark==0x90)
                {
                                IAPAL = 0x0E;
                                IAPAH = 0x00;
                                set_IAPGO;
                                BandgapHigh = IAPFD;
                                IAPAL = 0x0F;
                                IAPAH = 0x00;
                                set_IAPGO;
                                BandgapLow = IAPFD;
                                BandgapLow = BandgapLow&0x0F;
                                Bandgap_Value = (BandgapHigh<<4)+BandgapLow;
                                Bandgap_Voltage= Bandgap_Value*3/4;
                }
                clr_IAPEN;
//                        printf ("\n BG High = %bX",BandgapHigh);
//                        printf ("\n BG Low = %bX",BandgapLow);
//                        printf ("\n BG ROMMAP = %e",Bandgap_Voltage);
}
               
               
/******************************************************************************
The main C function.  Program execution starts
here after stack initialization.
******************************************************************************/
void main (void)
{
                double bgvalue;
                unsigned int i;
       
                InitialUART0_Timer1(115200);
                READ_BANDGAP();
                printf ("\n BG ROMMAP = %e",Bandgap_Voltage);
       
                while (1)
                {
                                Enable_ADC_BandGap;                                                                                               
                                CKDIV = 0x02;                                                                                                                        // IMPORTANT!! Modify system clock to 4MHz ,then add the ADC sampling clock base to add the sampling timing.
                                for(i=0;i<5;i++)                                                                                                        // All following ADC detect timing is 200uS run under 4MHz.
                                {
                                                clr_ADCF;
                                                set_ADCS;                                                                                                                               
                                                while(ADCF == 0);
                                                ADCdataH[i] = ADCRH;
                                                ADCdataL[i] = ADCRL;
                                }               
                                CKDIV = 0x00;                                                                                                                        // After ADC sampling, modify system clock back to 16MHz to run next code.
                                Disable_ADC;
                                for(i=2;i<5;i++)                                                                                                        // use the last 3 times data to make average
                                {
                                        ADCsumH = ADCsumH + ADCdataH[i];
                                        ADCsumL = ADCsumL + ADCdataL[i];
                                }                               
                                ADCavgH = ADCsumH/3;
                                ADCavgL = ADCsumL/3;
                                bgvalue = (ADCavgH<<4) + ADCavgL;
                                VDD_Voltage = (0x1000/bgvalue)*Bandgap_Voltage;
                                printf ("\n VDD voltage = %e", VDD_Voltage);
                                Timer0_Delay1ms(500);
                                ADCsumH = 0;
                                ADCsumL = 0;
                }
}


使用特权

评论回复
15
dongnanxibei| | 2020-5-19 23:58 | 只看该作者
是这个例子吧

使用特权

评论回复
16
Jenghiz| | 2020-5-29 10:27 | 只看该作者
之前用的时候我是直接读bandgap的AD值,发现波动很大,所以一直就没用bandgap值。也不知道是软件问题还是硬件问题

使用特权

评论回复
17
幸福小强| | 2020-5-29 21:05 | 只看该作者
官方例子讲的有,不过没这么总结。

使用特权

评论回复
18
WENAO| | 2023-2-10 09:43 | 只看该作者
Bandgap_Voltage= Bandgap_Value*3/4;这个乘3除4是怎么来的?为何是这个数?请问大家知道吗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

5

主题

16

帖子

1

粉丝