搜索
bottom↓
回复: 3

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

[复制链接]

出0入0汤圆

发表于 2010-8-26 16:05:30 | 显示全部楼层 |阅读模式
芯片型号: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

出0入0汤圆

 楼主| 发表于 2010-8-26 16:23:22 | 显示全部楼层
贴上源程序,应该是浮点数运算的问题

#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;
}
}
}

出0入0汤圆

 楼主| 发表于 2010-8-26 16:25:26 | 显示全部楼层
//太长了,分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--);
}

出0入0汤圆

发表于 2010-8-28 14:29:39 | 显示全部楼层
楼主的思路不对吧
三个变量  两个方程可以解码
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-8 13:50

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表