搜索

[8/16位单片机] PIC12F1822 的ADC采样问题求助

[复制链接]
4463|29
 楼主 | 2020-7-21 10:01 | 显示全部楼层 |阅读模式
#include "mcc_generated_files/mcc.h"

uint32_t u32AdcCount = 0;

static uint16_t u16AD_GetData(void)
{
    uint32_t u32Count = 0;
    uint16_t i;

    for(i=0;i<10;i++)
    {
        u32Count += ADC_GetConversion(channel_AN0);
    }

    return u32Count/10;
}

void main(void)
{
    uint16_t i,u16AD,u16Temp;

/*引脚配置*/
    LATA = 0x00;
    TRISA = 0x19;
    ANSELA = 0x17;
    WPUA = 0x00;
    OPTION_REGbits.nWPUEN = 1;
    APFCON = 0x00;

/*ADC配置*/
    ADCON0 = 0x01;
    ADCON1 = 0x10;
    ADRESL = 0x00;
    ADRESH = 0x00;

/*时钟配置*/
    OSCCON = 0x68;
    OSCTUNE = 0x00;
    BORCON = 0x00;


    while (1)
    {
        for(i=0;i<1000;i++)
        {
            u32AdcCount += u16Proximity_GetData();//对AN0通道一千次采样
        }
        u16AdcValue = u32AdcCount/1000;//取平均值
        u16AD = u16AD_GetData();//对AN3通道采样
        if(u16AD > 0xB332)
            u16AD = 0xB332;
        else
            if(u16AD < 0x5000)
            u16AD = 0x5000;
        u16Temp = (float)u16AD*1.72 - 13591;//模拟函数转换数值
        u32AdcCount = 0;
    }
}

遇到了很头疼的问题。
u16AD = u16AD_GetData();
这个函数只进行一次采样,而且采样的数据不准确,按道理进行10次采样后取平均值。
在我将这个函数内部  u32Count += ADC_GetConversion(channel_AN0);前面加了一句    ADCON0bits.ADON = 0;
也就是
static uint16_t u16AD_GetData(void)
{
    uint32_t u32Count = 0;
    uint16_t i;

    for(i=0;i<10;i++)
    {
        ADCON0bits.ADON = 0;/*加了一句这个*/
        u32Count += ADC_GetConversion(channel_AN0);
    }

    return u32Count/10;
}
,才能继续出数据。为什么要关一下再开才能出数据。。。而且数据也是不准确的。。。
0.0人类迷惑行为。

使用特权

评论回复
| 2020-7-21 14:17 | 显示全部楼层
本帖最后由 lcczg 于 2020-7-21 14:24 编辑

还有你的配置字DEBUG有没有使能,使能的话RA0就是ICSPDAT了。
The DEBUG bit in Configuration Word is managed automatically by device development tools including debuggers and
programmers. For normal device operation, this bit should be maintained as a '1'.

io.PNG

使用特权

评论回复
| 2020-7-22 10:44 | 显示全部楼层
1822的AN0和ICSP接口是复用的, 就好比两个贼把手伸进了同一个兜里,当然会冲突了...
其实, 你可以给AN0一个已经知道的电平, 例如Vdd/2, 然后代码里面判断一下ADC的值是否在512附近, 通过空闲的IO口翻转来指示,
把代码烧进去,别进debug模式..
这样间接来判断好了..

使用特权

评论回复
| 2020-7-21 10:47 | 显示全部楼层
本帖最后由 lcczg 于 2020-7-21 11:24 编辑

你ADC_GetConversion函数的代码贴一下,一般来说先启动一次转换,检测转换结束标志位,最后读取转换结果。你是不是漏了哪一步

使用特权

评论回复
 楼主 | 2020-7-21 11:29 | 显示全部楼层
lcczg 发表于 2020-7-21 10:47
你ADC_GetConversion函数的代码贴一下,一般来说先启动一次转换,检测转换结束标志位,最会读取转换结果。 ...

好的!麻烦了!

typedef uint16_t adc_result_t;

/*端口地址*/
typedef enum
{
    channel_AN0 =  0x0,
    channel_AN3 =  0x3,
    channel_Temp =  0x1D,
    channel_DAC =  0x1E,
    channel_FVR =  0x1F
} adc_channel_t;

adc_result_t ADC_GetConversion(adc_channel_t channel)
{
    // select the A/D channel
    ADCON0bits.CHS = channel;   
   
    // Turn on the ADC module
    ADCON0bits.ADON = 1;

    // Acquisition time delay
    __delay_us(ACQ_US_DELAY);

    // Start the conversion
    ADCON0bits.GO_nDONE = 1;

    // Wait for the conversion to finish
    while (ADCON0bits.GO_nDONE)
    {
    }

    // Conversion finished, return the result
    return ((adc_result_t)((ADRESH << 8) + ADRESL));
}

这个函数应该是没问题的,因为我用AN3通道转换没问题,但是AN0转换却发现了这个问题。

使用特权

评论回复
| 2020-7-21 11:44 | 显示全部楼层
本帖最后由 lcczg 于 2020-7-21 11:45 编辑
a511484095 发表于 2020-7-21 11:29
好的!麻烦了!

typedef uint16_t adc_result_t;

函数是没问题。RA0除了配为AN0外,有没有配为别的功能。另外RA0要置为模拟输入的。

使用特权

评论回复
| 2020-7-21 12:57 | 显示全部楼层
在MCC里面配置的吗

使用特权

评论回复
| 2020-7-21 14:09 | 显示全部楼层

是的

AIN.PNG

使用特权

评论回复
 楼主 | 2020-7-21 14:16 | 显示全部楼层

是的0.0

使用特权

评论回复
 楼主 | 2020-7-21 14:17 | 显示全部楼层
lcczg 发表于 2020-7-21 11:44
函数是没问题。RA0除了配为AN0外,有没有配为别的功能。另外RA0要置为模拟输入的。 ...

   LATA = 0x00;
    TRISA = 0x19;
    ANSELA = 0x17;
    WPUA = 0x00;
    OPTION_REGbits.nWPUEN = 1;
    APFCON = 0x00;

这是引脚配置的代码 应该是满足要求的

使用特权

评论回复
 楼主 | 2020-7-21 14:26 | 显示全部楼层
lcczg 发表于 2020-7-21 14:17
还有你的配置字DEBUG有没有使能,使能的话RA0就是ICSPDAT了。
The DEBUG bit in Configuration Word is ma ...

我觉得只能是这个问题了  谢谢!!!!

使用特权

评论回复
 楼主 | 2020-7-21 14:30 | 显示全部楼层
可是我找不到配置字2中debug的配置方法  我真是个酸菜鱼

使用特权

评论回复
 楼主 | 2020-7-21 15:52 | 显示全部楼层
lcczg 发表于 2020-7-21 14:17
还有你的配置字DEBUG有没有使能,使能的话RA0就是ICSPDAT了。
The DEBUG bit in Configuration Word is ma ...

我尝试去改了配置字,换成PICC编译器才想到办法进行debug位的更改。
XC8编译器没有debug位的配置字选项。。。MCC也没有。。。
但是我发现了

配置字2中的DEBUG 位由包括调试器和编
程器在内的器件开发工具自动管理。对于
正常的器件操作,该位应保持置 1。
101925f169e97e63ec.png
找了很久还是没有找到debug自动管理的设置。
只能尝试在PICC编译器下进行debug位的配置字设置。但是好像还是没有什么用。

__CONFIG(0x0984);
__CONFIG(0x1CFF);


使用特权

评论回复
| 2020-7-21 16:47 | 显示全部楼层
你观测到ADC的结果不对是在调试(DEBUG)的时候还是芯片正常运行的时候?

使用特权

评论回复
 楼主 | 2020-7-21 17:18 | 显示全部楼层
lcczg 发表于 2020-7-21 16:47
你观测到ADC的结果不对是在调试(DEBUG)的时候还是芯片正常运行的时候? ...

调试和正常运行的时候都不对0.0

使用特权

评论回复
 楼主 | 2020-7-21 17:23 | 显示全部楼层
本帖最后由 a511484095 于 2020-7-21 17:25 编辑
lcczg 发表于 2020-7-21 16:47
你观测到ADC的结果不对是在调试(DEBUG)的时候还是芯片正常运行的时候? ...

但是我发现我将芯片拆下来,直接调试,给AN0通道通上3V直流电压的时候 943005f16b4467698b.png
更让我相信了是debugger模式的问题。。。。。。



使用特权

评论回复
 楼主 | 2020-7-21 17:53 | 显示全部楼层
lcczg 发表于 2020-7-21 16:47
你观测到ADC的结果不对是在调试(DEBUG)的时候还是芯片正常运行的时候? ...

谢谢你!确实是调试模式debug的问题。我刚才用了AN2,也是OK的,唯独这个AN0有问题而且报这样的错。但是我不太明白为什么正常烧录还是会出现这个问题。难瘦。如果您知道怎么设置debug的方法能教给我,那就更好了!谢谢你!!

使用特权

评论回复
 楼主 | 2020-7-22 11:38 | 显示全部楼层
CoolSilicon 发表于 2020-7-22 10:44
1822的AN0和ICSP接口是复用的, 就好比两个贼把手伸进了同一个兜里,当然会冲突了...
其实, 你可以给AN0一个 ...

我用万用表测了AN0点电位,差不多也算是给了一个确定的电压吧。。
但是ADC转换AN0通道出来的值并不随AN0电位改变而改变。也就是按您的方法,给了Vdd/2,甚至Vdd3/4,但是ADC的值一直都在300左右晃悠。
我不太确定自己是否进入debug模式了,我一般烧录就是直接点 123015f17b45ee9f50.png ,应该没错
您觉得我需要换一个调试器,换成正版PICKit3吗

使用特权

评论回复
| 2020-7-22 14:06 | 显示全部楼层
a511484095 发表于 2020-7-22 11:38
我用万用表测了AN0点电位,差不多也算是给了一个确定的电压吧。。
但是ADC转换AN0通道出来的值并不随AN0 ...

烧录完了之后,你拔掉 pickit了没?

使用特权

评论回复
 楼主 | 2020-7-22 15:28 | 显示全部楼层
CoolSilicon 发表于 2020-7-22 14:06
烧录完了之后,你拔掉 pickit了没?

没拔。。。难道他不应该自己学会断开debug模式吗

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

在线客服 快速回复 返回顶部 返回列表