[求助] 为什么HalAdcRead()选择不同的通道,转换结果会不一样

spicis   2016-1-7 13:18 楼主
如题:为什么HalAdcRead()选择不同的通道,转换结果会不一样?
我测试了通道7-5,都是只调用了一次HalAdcRead(),
代码是    adc1 = HalAdcRead(HAL_ADC_CHANNEL_5, HAL_ADC_RESOLUTION_8);
测试结果,通道7、6结果是010左右,通道5是122左右。
初始化部分在下面
void SampleApp_Init( uint8 task_id )
{
  SampleApp_TaskID = task_id;
  SampleApp_NwkState = DEV_INIT;
  SampleApp_TransID = 0;

  MT_UartInit();//串口初始化
  MT_UartRegisterTaskID(task_id);//登记任务号
  HalUARTWrite(0,"Hello World\n",12); //(串口0,'字符',字符个数。)

  HalAdcInit();//参考电压是HAL_ADC_REF_VOLT  默认应该是3.3v
  //温度传感器初始化 P1.6
  P1SEL &= 0xbf ;
  //P1口全部为输入
  P1DIR &= 0x00 ;
  //ADC 初始化 P0.7紫外线 P0.6空气质量 P0.5一氧化碳
  APCFG &= 0xff ;
  //P0口全部为输入
  P0DIR &= 0x00 ;
  。。。。

}
不知道为什么,困扰了很久。

回复评论 (16)

问题能描述的再具体点吗?
1、比如你使用什么型号的主控 是CC2530?
2、你的ADC初始化函数好像没有拿出来,不知道问题会不会出现在这里
3、adc1 是什么类型的变量?uint8吗?这段代码最好放出来
4、“通道7、6结果是010左右,通道5是122左右”,通道5、6、7你接的什么地方?你试过把他们都分别接GND和VDD后看测量结果了吗?


虾扯蛋,蛋扯虾,虾扯蛋扯虾
点赞  2016-1-7 13:31
您好,您说的这些问题我一个一个回答:
1、我使用的是CC2530.
2、ADC初始化函数我没有更改
void HalAdcInit (void)
{
#if (HAL_ADC == TRUE)
  adcRef = HAL_ADC_REF_VOLT;
#endif
}
是选择参考电压  :  #define HAL_ADC_REF_AVDD          0x80    /* AVDD_SOC Pin Reference */
3、adc1是这样定义的:    uint16 adc1;
     typedef unsigned short  uint16;
4、我之前没有试过接GND和VDD,我得到的结果是引脚上不接任何东西的结果。这两种测试我应该怎么做呢?

非常感谢您的回复,虽然接触ZigBee一段时间了但我是还个新手,如果我问题有说明不清楚的话我再详细说明,谢谢
点赞  2016-1-7 13:46
引用: littleshrimp 发表于 2016-1-7 13:31
问题能描述的再具体点吗?
1、比如你使用什么型号的主控 是CC2530?
2、你的ADC初始化函数好像没有拿出来 ...

补充一下,刚才我测试了一下,通道7、6、5分别接地都是000,接3.3v或者5v都是127.另外刚才的回复可能写的地方比对,回复在三楼
点赞  2016-1-7 14:07
引用: littleshrimp 发表于 2016-1-7 13:31
问题能描述的再具体点吗?
1、比如你使用什么型号的主控 是CC2530?
2、你的ADC初始化函数好像没有拿出来 ...

我还是引用一下:“
您好,您说的这些问题我一个一个回答:
1、我使用的是CC2530.
2、ADC初始化函数我没有更改
void HalAdcInit (void)
{
#if (HAL_ADC == TRUE)
  adcRef = HAL_ADC_REF_VOLT;
#endif
}
是选择参考电压  :  #define HAL_ADC_REF_AVDD          0x80    /* AVDD_SOC Pin Reference */
3、adc1是这样定义的:    uint16 adc1;
     typedef unsigned short  uint16;
4、我之前没有试过接GND和VDD,我得到的结果是引脚上不接任何东西的结果。这两种测试我应该怎么做呢?

非常感谢您的回复,虽然接触ZigBee一段时间了但我是还个新手,如果我问题有说明不清楚的话我再详细说明,谢谢。
点赞  2016-1-7 14:08
引用: spicis 发表于 2016-1-7 14:07 补充一下,刚才我测试了一下,通道7、6、5分别接地都是000,接3.3v或者5v都是127.另外刚才的回复可能写的 ...
不知道你用的是哪里的代码 我看了数据手册 你的参考电压设置为80应该是对应的AVDD5 pin QQ图片20160107152802.png CC2530的供电电压不能超过3.9V QQ图片20160107152927.png 而ADC的输入范围不能大于VDD,3.9V 你输入5V可能会损坏ADC QQ图片20160107153003.png 你在测量GND时的读数是0,测量5V时的计数是127 你设置的分辨率是8位,理想的满量程最大值应该是255 从这个看你的ADC读数会随电压的变化而变化 只是满量程是127 7位的分辨率 我看了一下CC2530的ADC,应该不是双极性输入 也没有配置输出数据格式的地方 你可以尝试着把分辨率改大一点看看输出结果有没有变化 本帖最后由 littleshrimp 于 2016-1-8 09:03 编辑
虾扯蛋,蛋扯虾,虾扯蛋扯虾
点赞  2016-1-7 15:37
引用: littleshrimp 发表于 2016-1-7 15:37
不知道你用的是哪里的代码

我看了数据手册
你的参考电压设置为80应该是对应的AVDD5 pin

CC2530的 ...

您好,我是在网蜂官网买的模块和资料,代码是更改了网蜂提供的代码。这里是不是应该使用TI官方的ZStack来更改?

CC2530的供电电压是通过AMS1117转换过得,是5V转成3.3v,我是在开发板上做的测试,所以供电电压应该没问题。

我下午做了一些测试,把ADC的参考电压改成了
#define HAL_ADC_REF_VOLT    HAL_ADC_REF_AIN7    /*selcet AIN7 Reference */
对应的是
#define HAL_ADC_REF_AIN7          0x40    /* AIN7 Reference */
这里我就是把P0.7接3.3v(不知道是不是正确)

我贴一下adc1转换成字符的代码:
V1[0]=adc1/1000+48;
V1[1]=adc1%1000/100+48;
V1[2]=adc1%100/10+48;
V1[3]=adc1%10+48;

之后我根据你的建议,改成了10位分辨率
测试结果:
adc1 = HalAdcRead(HAL_ADC_CHANNEL_0, HAL_ADC_RESOLUTION_10);
P0.0接GND结果是0;
P0.0接3.3v结果是511;
空接是45左右;
接传感器0000-0001左右;

adc1 = HalAdcRead(HAL_ADC_CHANNEL_1, HAL_ADC_RESOLUTION_10);
P0.0接GND结果是0;
P0.0接3.3v结果是511;
空接是45左右;
接传感器0005-0007左右;

adc1 = HalAdcRead(HAL_ADC_CHANNEL_2, HAL_ADC_RESOLUTION_10);
P0.0接GND结果是0;
P0.0接3.3v结果是511;
空接是45左右;
接传感器0001-0002;

adc1 = HalAdcRead(HAL_ADC_CHANNEL_3, HAL_ADC_RESOLUTION_10);
P0.0接GND结果是0;
P0.0接3.3v结果是511;
空接是45左右;
接传感器186左右;

adc1 = HalAdcRead(HAL_ADC_CHANNEL_4, HAL_ADC_RESOLUTION_10);
P0.0接GND结果是0;
P0.0接3.3v结果是511;
空接是490左右;
接传感器256左右;

adc1 = HalAdcRead(HAL_ADC_CHANNEL_5, HAL_ADC_RESOLUTION_10);
P0.0接GND结果是0;
P0.0接3.3v结果是511;
空接是490左右;
接传感器256左右;

adc1 = HalAdcRead(HAL_ADC_CHANNEL_6, HAL_ADC_RESOLUTION_10);
P0.0接GND结果是0;
P0.0接3.3v结果是511;
空接是490左右;
接传感器256左右;

以上都是同一个模块,同一个传感器测试的,开发板除了我自己把P0,P1口焊上了排针,其他应该没有影响电路的部分。最后附上我的测试代码,很多地方写的、注释的非常随意,还望见谅。
点赞  2016-1-7 17:23
.kz的代码不知道是用什么软件写的我没打开
我又看了CC2530的用户手册,发现ADC是支持差分输入的
QQ图片20160108091108.png

你一个输入引脚连接GND时显示0接VDD显示Full–Scale/2
像是工作在差分输入模式下
你可以看一下代码是不是配置了差分输入
了解一下配置的寄存器都代表什么
可以多读读CC2530的用户手册
CC253x User Guide.pdf (2.04 MB)
(下载次数: 8, 2016-1-8 09:21 上传)



ADC引脚处于悬空状态测量结果是没有意义的

看到你ADC在读取同通道时都是连接的P0.0
是不是一个通道对应一个引脚呢?

你的传感器可以先连接到万用表,测量一下传感器的实际输入
再参考万用表的数据判断ADC的问在哪

虾扯蛋,蛋扯虾,虾扯蛋扯虾
点赞  2016-1-8 09:21
引用: littleshrimp 发表于 2016-1-8 09:21
.kz的代码不知道是用什么软件写的我没打开
我又看了CC2530的用户手册,发现ADC是支持差分输入的


你一 ...

您好,
我重新添加了一个.zip的文件,使用IAR开发的,工程在
enddiv_use_adc\enddiv\Projects\zstack\Samples\SampleApp\CC2530DB
路径下

关于昨天的回复我纠正一些东西,我测试的时候根据不同的通道,连接的是相对应的引脚,回复的时候错写成了都连P0.0了,不好意思。

uint16 HalAdcRead (uint8 channel, uint8 resolution)
{
  int16  reading = 0;

#if (HAL_ADC == TRUE)
  uint8   i, resbits;
  uint8  adcChannel = 1;

  /*
   * If Analog input channel is AIN0..AIN7, make sure corresponing P0 I/O pin is enabled.  The code
   * does NOT disable the pin at the end of this function.  I think it is better to leave the pin
   * enabled because the results will be more accurate.  Because of the inherent capacitance on the
   * pin, it takes time for the voltage on the pin to charge up to its steady-state level.  If
   * HalAdcRead() has to turn on the pin for every conversion, the results may show a lower voltage
   * than actuality because the pin did not have time to fully charge.
   */
  if (channel < 8)
  {
    for (i=0; i < channel; i++)
    {
      adcChannel <<= 1;
    }
  }

  /* Enable channel */
  ADCCFG |= adcChannel;

  /* Convert resolution to decimation rate */
  switch (resolution)
  {
    case HAL_ADC_RESOLUTION_8:
      resbits = HAL_ADC_DEC_064;
      break;
    case HAL_ADC_RESOLUTION_10:
      resbits = HAL_ADC_DEC_128;
      break;
    case HAL_ADC_RESOLUTION_12:
      resbits = HAL_ADC_DEC_256;
      break;
    case HAL_ADC_RESOLUTION_14:
    default:
      resbits = HAL_ADC_DEC_512;
      break;
  }

  /* writing to this register starts the extra conversion */
  ADCCON3 = channel | resbits | adcRef;

  /* Wait for the conversion to be done */
  while (!(ADCCON1 & HAL_ADC_EOC));

  /* Disable channel after done conversion */
  ADCCFG &= (adcChannel ^ 0xFF);

  /* Read the result */
  reading = (int16) (ADCL);
  reading |= (int16) (ADCH << 8);

  /* Treat small negative as 0 */
  if (reading < 0)
    reading = 0;

  switch (resolution)
  {
    case HAL_ADC_RESOLUTION_8:
      reading >>= 8;
      break;
    case HAL_ADC_RESOLUTION_10:
      reading >>= 6;
      break;
    case HAL_ADC_RESOLUTION_12:
      reading >>= 4;
      break;
    case HAL_ADC_RESOLUTION_14:
    default:
      reading >>= 2;
    break;
  }
#else
  // unused arguments
  (void) channel;
  (void) resolution;
#endif

  return ((uint16)reading);
}


这是API的代码,我分析了一下,在
adc1 = HalAdcRead(HAL_ADC_CHANNEL_0, HAL_ADC_RESOLUTION_10);
的调用中
adcRef=0x40;
adcChannel=0x01;
resbits=0x10;
channel=0x00;

所以代码中对应寄存器设置的结果应该是
ADCCFG =0xFF;
ADCCON3=01                        01                        0000
               AIN7参考电压      9bitENOB 分辨率     P0.0口

我上午做了一些测试,传感器的电压输出一直是稳定在800mV左右,对应不同的的通道,输出结果依旧是不一样的,
我上传的附件大于15m,上传到我的资源里头,我觉得应该是我代码出了问题,谢谢
点赞  2016-1-8 12:01
引用: littleshrimp 发表于 2016-1-8 09:21
.kz的代码不知道是用什么软件写的我没打开
我又看了CC2530的用户手册,发现ADC是支持差分输入的


你一 ...

我发现我18B20.c文件里有对寄存器的操作,我以为是这个地方影响了,删除这部分代码之后问题依然存在。
点赞  2016-1-8 14:36
引用: spicis 发表于 2016-1-8 12:01
您好,
我重新添加了一个.zip的文件,使用IAR开发的,工程在
enddiv_use_adc\enddiv\Projects\zstack\S ...

这样看的话你的ADC设置为8位分辨率(实际为7位)最大值为127
10位分辨率(实际为9位)最大值为511
是正确的
说明ADC没有问题,比如你用两个几K电阻分压或者使用电位器输出用ADC测一下看看是否正常

如果ADC没问题你就要看看问题是不是出在传感器了
看看你的传感器输入是不是有缓冲

不过我觉得更像是传感器连接的问题
因为不同的ADC测量电源时都是满量程最大值
测量传感器时的读数却千差万别



QQ图片20160108144037.png

QQ图片20160108144535.png
虾扯蛋,蛋扯虾,虾扯蛋扯虾
点赞  2016-1-8 14:51
引用: littleshrimp 发表于 2016-1-8 14:51
这样看的话你的ADC设置为8位分辨率(实际为7位)最大值为127
10位分辨率(实际为9位)最大值为511
是正 ...

您好,

我下午又做了一些测试,用公式
AD转换结果   =  分辨率   *   传感器输入电压   /   参考电压
计算但我不确定这个公式是否正确

我改了分辨率,代码是
adc1 = HalAdcRead(HAL_ADC_CHANNEL_6, HAL_ADC_RESOLUTION_12);

HAL_ADC_RESOLUTION_12  查看手册是10bit ENOB
有这么几种情况

(AIN7就是P0.7口吧?我用这个口输入作为参考电压)
adc1 =    分辨率   *    输入电压   /   3.3V(P0.7口接3.3v)输入电压接3.3V的时候 , 输出结果是2047
得出分辨率是2047  应该是  1 1111 1111 是9bit  和手册上好像不一样(我是不是哪里理解错了)


所以公式就变成
adc1 =    2047   *    输入电压   /   3.3V(P0.7口接3.3v)
我在测试的时候  万用板红笔接传感器ADout模拟输出引脚,黑笔接GND,测出传感器输出电压(公式中的输入电压),同时串口接收adc1的值

然后我发现选择不同的通道,即传感器模拟输出引脚接不同口(P0.0-P0.6)测得的这个引脚输出电压是不一样的,
引脚接0-6分别的电压是
0        1         2       3       4         5         6
0.15   0.28   0.15   2.8    0.54    0.53    0.53                  

不过除了通道3和通道6,其他几个通道的测试结果在公式中都大致正确 。(通道1,2,6的测试过程我没记录,但其他是确定的,弄了几天有点累了)  


非常感谢你给我的回复, 帮里我不是忙                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
点赞  2016-1-8 19:35
引用: littleshrimp 发表于 2016-1-8 14:51
这样看的话你的ADC设置为8位分辨率(实际为7位)最大值为127
10位分辨率(实际为9位)最大值为511
是正 ...

我测了一下P0.0-P0.7的电压,发现
P0.0很小接近0V,
P0.2在3.4v左右,
其他口在3.3V左右

然后我接传感器的模拟输入,电压相应的也就不一样了

这可能就是不同通道转换结果不一样的原因,
可是这是为什么呀,,
点赞  2016-1-9 11:23
引用: spicis 发表于 2016-1-9 11:23
我测了一下P0.0-P0.7的电压,发现
P0.0很小接近0V,
P0.2在3.4v左右,
其他口在3.3V左右

然后我接 ...

CC2530的引脚是数字和模拟复用的
你看看配置ADC的同时
是不是需要把对应的引脚寄存器也切换成AIN模式

你也可以先用一个白光(蓝光)LED或者红光串相应的电阻
分别连接ADC输入引脚对电和ADC输入引脚对地(注意正负极)
看LED会不会亮
如果亮了
说明你的引脚是输出模式
或者由内部或外部电路将其与电源或地连接了
这时候你先检查一下外部电路
如果外部电路没有问题
再看一下内部寄存器的配置
虾扯蛋,蛋扯虾,虾扯蛋扯虾
点赞  2016-1-11 11:54
引用: littleshrimp 发表于 2016-1-11 11:54
CC2530的引脚是数字和模拟复用的
你看看配置ADC的同时
是不是需要把对应的引脚寄存器也切换成AIN模式
...

您好,因为这个是我在学校里头的项目,不过之后我就在外面工作了,所以应该要过些时候才会再去解决这个问题,非常感谢您的帮助,谢谢。帖子就先到这里吧,然后专心公司的工作
点赞  2016-1-11 17:06
引用: spicis 发表于 2016-1-11 17:06
您好,因为这个是我在学校里头的项目,不过之后我就在外面工作了,所以应该要过些时候才会再去解决这个问 ...


祝你好运
虾扯蛋,蛋扯虾,虾扯蛋扯虾
点赞  2016-1-11 17:15
您好,请问这个问题是怎么回事
点赞  2017-10-18 18:00
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复