ADC如何利用0.6V参考电压校准

2020-02-09 11:27发布

芯片型号:PIC16F690

我的大体思路是这样,先选取VP6通道,Vp6=ADC/1023*VCC,该算式中Vp6已知为0.6V,ADC的值通过AD转换得到,就能够求出VCC,这个是及时的VCC,因为我的电源只是用了一个5.1V的稳压管,肯定不够稳定,所以才想利用PIC内部0.6V的固定电压
然后改变通道为AN10,进行真正的AD转换,Vsam=ADC'/1023*VCC,该算式中的VCC即我在第一步中算出的VCC,我想这样计算得到的会更可靠一些
大侠们帮忙看看我这个思路有没有问题……

然后就是实现的过程中碰到了问题,1是我转换出来的电压不能被识别出来,而ADC'的值是有的,我想是不是浮点数运算出了问题
还有一个问题我原来使用内置8MHz晶振,现在考虑使用内置31KHz,现在的延时函数很不准确,不知道该如何计算出实现1ms的循环,怎么能够实现1us的延时,AD转换的时候需要,我在MPLAB SIM里面仿真,一个NOP()语句都有几个us
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
3条回答
role_2099
1楼-- · 2020-02-09 16:31
贴上源程序,应该是浮点数运算的问题

#include//包含头文件
#define uchar unsigned char//宏定义
#define uint unsigned int//宏定义
__CONFIG(INTIO & WDTDIS & PWRTEN & BORDIS & UNPROTECT);
//内置振荡器、引脚为IO功能,关闭看门狗,开电压,关,不保护EEPROM
void init();//系统初始化
void init_adc6();//ADC初始化
uint get_ad6();//启动AD转换
void init_adc();//ADC初始化
uint get_ad();//启动AD转换
uint get_v();
void delay_ms(uint);//延时xms
//const uchar table[]={0x7f,0x3f,0x1f,0x0f,0x07};
void main()//主函数
{
uint v_ad,v6_ad;//ADC结果暂存
float vcc;
uint vsam;
const uchar dlxs[]={0x7f,0x3f,0x1f,0x0f,0x07};//依次增多点亮的LED
//20%:0~203,40%:204~408,60%:409~613,80%:614~818,100%:819~1023
init();
/*while(1) //该while语句内将测得的v_ad和v6_ad还原成模拟电压值,
//判断时执行了default后面的语句
{
v_ad = get_ad();//获取AN10 AD转换结果
v6_ad = get_ad6();//获取VP6 AD转换结果
vcc = v_ad*0.6/v6_ad;//通过两个方程求解出vcc
vcc = vcc*100;//保留小数点后2位
float vcc = (uint)vsam;//转换为整型采样电压值

//对采样电压值进行判断,通过LED显示出来
switch(vsam)
{
case 200:PORTC=dlxs[0];break;
case 250:PORTC=dlxs[1];break;
case 300:PORTC=dlxs[2];break;
case 350:PORTC=dlxs[3];break;
case 378:PORTC=dlxs[4];break;
default:PORTC=0xff;break;
}
}*/
while(1)//该while语句测得v_ad和v6_ad结果均正确
{
v_ad = get_ad();//获取AN10 AD转换结果
v6_ad = get_ad6();//获取VP6 AD转换结果
/*if(v_ad>1023)//该if语句测得v_ad结果正确
{
v_ad=1023;
}
else if(8183.9V
{
PORTC = dlxs[4];//PORTC=0b00000111
}
else if(6132.99V
{
PORTC = dlxs[3];//PORTC=0b00001111
}
else if(4081.99V
{
PORTC = dlxs[2];//PORTC=0b00011111
}
else if(2030.99V
{
PORTC = dlxs[1];//PORTC=0b00111111
}
else if(00
{
PORTC = dlxs[0];//PORTC=0b01111111,lednum<204
}
else
{
PORTC = 0xff;
}*/
if(v6_ad>100)//该if语句测得v6_ad结果正确
{
PORTC = dlxs[4];
}
else
{
PORTC = 0xff;
}
}
}
role_2099
2楼-- · 2020-02-09 20:42
//太长了,分2段发
void init_adc6()//初始化ADC vp6
{
VP6EN=1;//使能VP6
delay_ms(1);//延时待VP6稳定
ADCON0 = 0xb5;//结果右对齐,基准为VDD,通道选择VP6进行校准
ADCON1 = 0x30;//ADC时钟选择
ADIE = 0;//禁止ADC中断
delay_ms(1);
}
uint get_ad6()//AD转换 vp6
{
init_adc6();
uint adval;//0x000~0x3ff,1024
GODONE = 1;
while(GODONE);
adval = ADRESH;//00000000 00000011
adval = adval << 8 | ADRESL;//00000011 00000000|11111111=00000011 11111111
return (adval);
}
void init_adc()//初始化ADC
{
ADCON0 = 0xa9;//结果右对齐,基准为VDD,通道选择AN10
ADCON1 = 0x30;//ADC时钟选择
ADIE = 0;//禁止ADC中断
delay_ms(1);
}
uint get_ad()//AD转换
{
init_adc();
uint adval;//0x000~0x3ff,1024
GODONE = 1;
while(GODONE);
adval = ADRESH;//00000000 00000011
adval = adval << 8 | ADRESL;//00000011 00000000|11111111=00000011 11111111
return (adval);
}
void init()//系统初始化
{
OSCCON = 0x01;//振荡器控制寄存器配置为内部31KHz
//OSCCON = 0x31;//振荡器控制寄存器配置为内部500KHz
TRISA = 0x34;//00110100RA2/RA4/RA5为悬空脚
//PORTA = 0xcb;//11001011
TRISB = 0x50;//01010000RB4为模拟输入(采样电压)RB6为悬空脚
//PORTB = 0xaf;//10101111
TRISC = 0x07;//00000111RC2为模拟输入(按键中断),RC1/RC0为悬空脚
//PORTC = 0xf8;//11111000
ANSEL = 0x40;//enable AN6(RC2)
ANSELH = 0x04;//enable AN10(RB4)
}
void delay_ms(uint xms)//延时xms
{
uint i,j;
for(i=xms;i>0;i--)//8MHz晶振下,xms等于几就延时几ms
for(j=152;j>0;j--);
}
yklstudent
3楼-- · 2020-02-09 23:27
楼主的思路不对吧
三个变量  两个方程可以解码

一周热门 更多>