打印
[PIC®/AVR®/dsPIC®产品]

PIC多通道AD转换问题

[复制链接]
4705|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
kecaijie|  楼主 | 2014-2-16 21:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
设置一个AD采样子函数,如果连续读取每个通道,则数值正确,但是如果每个循环读取一个通道,第一个通道数值就错误。附上程序,请帮忙看下:
//PIC16F914
#include    <pic.h>
#include    <stdlib.h>
#define uchar       unsigned char
#define uint        unsigned int
uchar chn;
uint  PV,LOWBATT,SYSTEM;//气压,低电压,主板温度
__CONFIG( 0X3724);
void init(void);
uint getad(uchar channel);
void main()
{
        init();
        while(1)
        {
                switch(chn)//每次取一个通道,则chn=0时,数值都不对
                {
                        case 0:{PV=getad(0);break;}
                        case 1:{LOWBATT=getad(1);break;}
                        case 2:{SYSTEM=getad(2);break;}               
                }
                chn++;
                if(chn>=3) {chn=0;}

               
               
                //如果连续去读则正确
                //PV=getad(0);
                //LOWBATT=getad(1);
                //SYSTEM=getad(2);
        delay_ms(50);
       
        }

}

uint getad(uchar channel)
{
    uint adval;
    if(channel==0)//压力
    {
        ADCON0=0B10000001;
        ADON=1;
        __delay_us(121);
        GODONE=1;
        while(GODONE);
        adval=(ADRESH<<8)+ADRESL;
    }
    if(channel==1)//低电压
    {
        ADCON0=0B10000101;
        ADON=1;
        __delay_us(121);
        GODONE=1;
        while(GODONE);
        adval=(ADRESH<<8)+ADRESL;
    }
    if(channel==2)//系统主板温度
    {
        ADCON0=0B10001001;
        ADON=1;
        __delay_us(121);
        GODONE=1;
        while(GODONE);
        adval=(ADRESH<<8)+ADRESL;       
    }
    return (adval);       
}
沙发
yewuyi| | 2014-2-17 10:47 | 只看该作者
你老师看了这段代码会气得拿脑袋撞墙的。


不看了,看这会让心情特别沉重。

使用特权

评论回复
板凳
yklstudent| | 2014-2-17 11:19 | 只看该作者
表面看 没什么问题

使用特权

评论回复
地板
kecaijie|  楼主 | 2014-2-17 12:27 | 只看该作者
yewuyi 发表于 2014-2-17 10:47
你老师看了这段代码会气得拿脑袋撞墙的。

能实现功能就可以了。有些无关的代码和函数删掉了

使用特权

评论回复
5
luofeng2g| | 2014-2-17 12:44 | 只看该作者
程序貌似没问题,你用什么观察数据出错的?

使用特权

评论回复
6
kecaijie|  楼主 | 2014-2-17 12:50 | 只看该作者
luofeng2g 发表于 2014-2-17 12:44
程序貌似没问题,你用什么观察数据出错的?

我先采样固定的电压,然后通过串口传输到电脑上看到的。一次三个通道连续取样就正常,每个循环取样一个通道,就是第一个通道会数值不对(个别的数值正确,很有规律,1个正确2个错误,这样一直循环)

使用特权

评论回复
7
luofeng2g| | 2014-2-17 12:59 | 只看该作者
kecaijie 发表于 2014-2-17 12:50
我先采样固定的电压,然后通过串口传输到电脑上看到的。一次三个通道连续取样就正常,每个循环取样一个通 ...

那会不会是你串口出了问题?

使用特权

评论回复
8
kecaijie|  楼主 | 2014-2-17 14:18 | 只看该作者
luofeng2g 发表于 2014-2-17 12:59
那会不会是你串口出了问题?

串口没问题,这个是实际线路板验证过的,就是顺序取样和每个循环取样一次语句差别,结果就如问题描述的。

使用特权

评论回复
9
ZG11211| | 2014-2-17 20:12 | 只看该作者
本帖最后由 ZG11211 于 2014-2-17 20:21 编辑

大家都是新手成长起来的,给楼主看看我的ADC函数,酌情考虑是否有用,祝PIC粉丝们新年快乐!
/***********10位ADC*****************************************************/
unsigned int get_ad10(unsigned char n) //AD采样函数 n为通道号
{
unsigned int ad_data;
ADCON0 = (n<<2)|0x41;    //Fosc/8,  ADC使能,4M时钟需用F0sc/8, 最佳2us
//ADCON0 = (n<<2)|0x81; //Fosc/32,ADC使能,8M时钟需用F0sc/32,最佳4us
asm("nop");       //空操作延时 根据实际效果选择是否需要
asm("nop");      //空操作延时
GO_DONE = 1; //开始转换
while(GO_DONE);    //等待转换结束
ad_data = ADRESH;//取高8位
ad_data =(ad_data << 2) + (ADRESL >> 6);//取10位时左对齐时使用,8位可//掉此指令
return (ad_data);
}

使用特权

评论回复
10
moheionly| | 2014-2-21 16:18 | 只看该作者

看错了

本帖最后由 moheionly 于 2014-2-21 16:22 编辑

看错了,没搞懂

使用特权

评论回复
11
wupian19910108| | 2014-2-22 12:36 | 只看该作者
楼主  能把你与计算机通信的串口通信程序给我看一下 啊

使用特权

评论回复
12
shenzhenherry| | 2014-3-4 10:16 | 只看该作者
本帖最后由 shenzhenherry 于 2014-3-4 10:28 编辑

adval=(ADRESH<<8)+ADRESL;

LZ的问题解决了吗?我认为是这个语句有问题!

应该是:adval=(ADRESH<<8) | ADRESL;//应该是逻辑或的操作,而不是算术加!

__delay_us(121);//还有就是在AD通道切换后的这个延时明显不够,请看datasheet,是毫秒级的时序,我是这样做的:
#define AD_TIME 20000
delay(AD_TIME);

在春节前,我在做一个项目时,遇到AD转换的问题,也一度苦恼,遇到你这样的问题,即:单独去读书是对的,连续读数就总是会发生数据丢失或是错误,后来仔细实验,才解决,呵呵。

祝你成功!

使用特权

评论回复
13
shenzhenherry| | 2014-3-4 10:17 | 只看该作者
另外,在通道切换后,读取AD转换值的那些重复的语句,建议可以抽象为一个函数,这样理解程序的流程、调试等等都会更加方便

使用特权

评论回复
14
shenzhenherry| | 2014-3-4 10:26 | 只看该作者
本帖最后由 shenzhenherry 于 2014-3-4 10:37 编辑

又仔细对照查看你的代码,和我自己成功的代码,你的语句流程似乎不对,我认为应该是:

1、切换通道
    ADCON0=0B*******;

2、。。。。。

使用特权

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

本版积分规则

1

主题

6

帖子

0

粉丝