利用带隙电压获取新塘单片机N76E003芯片电压VDD
1、【1】打开集成开发环境Keil并建立好相应C51工程。
【2】在创建工程时Device选择Nuvoton 8051 Devices-->E76E003。前提要安装好Keil插件,否则找不到芯片型号,插件必须安装在Keil的根目录下。
【3】我是将Keil C51和Keil ARM安装在同一个根目录下,所以他们两个的图标相似,最主要是代码的放大缩小很方便。
【4】设置Output生成.hex文件的位置和Listing文件的位置,必须将Create HEX Files前打勾。




2、【1】编写串口驱动驱动程序,设置波特率为9600pbs,8位数据位,1位停止位,无奇偶校验。串口驱动驱动程序可以直接用官方给的Demo。
void InitialUART1_Timer3(u32 u32Baudrate)//Initial UART1 Timer3
【2】编写简单的延时函数,也可以使用官方提供的延时函数,官方给的延时函数使用定时器,提前是你不使用这个定时器,否则这个延时函数不准或出错。
void Timer0_Delay1ms(u32 u32CNT)//Timer0 Delay 1ms
【3】编写获取带隙电压(Band-gap)函数,这个函数在数据数据手册上有, ADC那一章有讲解。获取带隙电压需要用到IAP功能读取固化到Flash中的内容。
void vGet_BandGap_VoltageValue(void)//xGet Band Gap Voltage Value
【4】编写获取当前芯片的电压值。
double xGet_PowerSource_Voltage(void)//xGet Power Source Voltage
【5】编写printf函数的重定向
char putchar (char c)//UART1 printf
3、【1】串口驱动驱动程序
void InitialUART1_Timer3(u32 u32Baudrate)//Initial UART1 Timer3
{
P02_Quasi_Mode; //Setting UART pin as Quasi mode for transmit
P16_Quasi_Mode; //Setting UART pin as Quasi mode for transmit
SCON_1 = 0x50; //UART1 Mode1,REN_1=1,TI_1=1
T3CON = 0x08; //T3PS2=0,T3PS1=0,T3PS0=0(Prescale=1), UART1 in MODE 1
clr_BRCK;
#ifdef FOSC_160000
RH3 = HIBYTE(65536 - (1000000/u32Baudrate)-1); //16 MHz
RL3 = LOBYTE(65536 - (1000000/u32Baudrate)-1);
#endif
#ifdef FOSC_166000
RH3 = HIBYTE(65536 - (1037500/u32Baudrate)); //16.6 MHz
RL3 = LOBYTE(65536 - (1037500/u32Baudrate));
#endif
set_TR3; //Trigger Timer3
TI_1 = 1; //For printf function must setting TI = 1
}
【2】延时函数
void Timer0_Delay1ms(u32 u32CNT)//Timer0 Delay 1ms
{
clr_T0M; //T0M=0, Timer0 Clock = Fsys/12
TMOD |= 0x01; //Timer0 is 16-bit mode
set_TR0; //Start Timer0
while (u32CNT != 0)
{
TL0 = LOBYTE(TIMER_DIV12_VALUE_1ms); //Find define in "Function_define.h" "TIMER VALUE"
TH0 = HIBYTE(TIMER_DIV12_VALUE_1ms);
while (TF0 != 1); //Check Timer0 Time-Out Flag
clr_TF0;
u32CNT --;
}
clr_TR0; //Stop Timer0
}
【3】获取带隙电压(Band-gap)函数
BandGapStruct BanGapStruct;
void vGet_BandGap_VoltageValue(void)//xGet Band Gap Voltage Value
{
double bandGapVoltage = 0;
u16 bandGapValue = 0;
u8 bandGapHigh=0, bandGapLow=0, BandgapMark=0;
IAP_ENABLE;
IAPCN = READ_UID;
IAPAL = 0X0D;
IAPAH = 0X00;
IAP_START_PROGRAMEE;
bandGapLow = IAPFD;
BandgapMark = bandGapLow&0XF0;
switch(BandgapMark)
{
case 0X00 :
{
bandGapLow = bandGapLow&0X0F;
IAPAL = 0X0C;
IAPAH = 0X00;
IAP_START_PROGRAMEE;
bandGapHigh = IAPFD;
bandGapValue = (((u16)bandGapHigh)<<4) + bandGapLow;
bandGapVoltage = (bandGapValue*3)/4;
}
break;
case 0X80 :
{
bandGapLow = bandGapLow&0X0F;
IAPAL = 0X0C;
IAPAH = 0X00;
IAP_START_PROGRAMEE;
bandGapHigh = IAPFD;
bandGapValue = (((u16)bandGapHigh)<<4) + bandGapLow;
bandGapVoltage = ((bandGapValue*3)/4) - 33;
}
break;
case 0X90 :
{
IAPAL = 0X0E;
IAPAH = 0X00;
IAP_START_PROGRAMEE;
bandGapHigh = IAPFD;
IAPAL = 0X0F;
IAPAH = 0X00;
IAP_START_PROGRAMEE;
bandGapLow = IAPFD;
bandGapLow = bandGapLow&0X0F;
bandGapValue = (((u16)bandGapHigh)<<4) + bandGapLow;
bandGapVoltage = (bandGapValue*3)/4;
}
break;
default : break;
}
IAP_DISABLE;
BanGapStruct.Voltage = bandGapVoltage;
}
【4】获取当前芯片的电压值
double xGet_PowerSource_Voltage(void)//xGet Power Source Voltage
{
double powerVolatge = 0;
double powerADC = 0;
u16 powerADCH=0, powerADCL=0;
u8 adcDataH[5]={0}, adcDataL[5]={0};
u8 i = 0;
Enable_ADC_BandGap;
CKDIV = 0X02;
for(i=0; i<5; i++)
{
ADC_CLR_FALG;
ADC_START_CONVERT;
while(!ADCF);
adcDataH[i] = ADCRH;
adcDataL[i] = ADCRL;
}
CKDIV = 0X00;
for(i=2; i<5; i++)
{
powerADCH += adcDataH[i];
powerADCL += adcDataL[i];
}
adcDataH[0] = ((u8)(powerADCH/3));
adcDataL[0] = ((u8)(powerADCL/3));
powerADC = (((u16)adcDataH[0])<<4) + adcDataL[0];
powerVolatge = (0X1000/powerADC)*BanGapStruct.Voltage;
return powerVolatge;
}
【5】printf函数的重定向
char putchar (char c)//UART1 printf
{
while (!TI_1);//wait until transmitter ready
TI_1 = 0;
SBUF_1 = c;//output character
return (c);
}







4、编写主函数。先要获取获取带隙电压,才能获取当前芯片电压
void main(void)
{
Set_All_GPIO_Quasi_Mode;
InitialUART1_Timer3(9600);
vGet_BandGap_VoltageValue();
while(1)
{
printf("Current Voltage : %f mV", xGet_PowerSource_Voltage());
Timer0_Delay1ms(3000);
}
}

5、【1】编译并检查错误,直到程序正确为此。
【2】N76E003的时钟默认为16MHZ,宏定义系统时钟,否则串口配置无效,串口配置中有一个条件编译,所以需要宏定义,我这里直接定义在编译器中。


6、【1】将程序下载到芯片中,也就是下载.hex到芯片中。
【2】通过串口调试助手参看当前电压值,调节当前电压值再次查看串口调试助手打印的信息,已验证程序的正确性,也可以用万用表直接测量此时芯片的电压,看是否相正确。


