[其他产品] 关于mega48 多通道AD转换的问题,转换结果相同

[复制链接]
 楼主| powerantone 发表于 2025-3-9 23:00 | 显示全部楼层 |阅读模式
/******************************************************************************/
/*                     多通道AD实验程序                                       */
/******************************************************************************/

#include <iom48v.h>
#include <macros.h>
#define uint unsigned int
#define uchar unsigned char
uint temp1=0,temp4=0;

uint ADC_Convert(uchar channel)
{
  ADMUX |= channel; //选择ADC通道为PA0
  ADCSRA|=(1<<ADSC);// 开始转换
  while (!(ADCSRA&(1<<ADIF))); // 等待转换结束
  ADCSRA |=(1<<ADIF); // 清除转换结束标记
  return(ADCH);
}

void main(void)
{
  DDRD|=0x80;
  PORTD&=0x7F;

  DDRC&=0xEB;//ad通道输入设置
  ADCSRA=0x00;
  ADMUX |=0x60; //采用内部5参考电压,左对齐  
  ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);

  while(1)
  {
    temp1=ADC_Convert(2);
if(temp1>40)
PORTD|=0x80;

temp4=ADC_Convert(4);
if(temp4<40)
PORTD&=0x7F;
  }

}
捉虫天师 发表于 2025-3-21 16:26 | 显示全部楼层
可能是由于以下原因导致的:

1. ADMUX通道选择问题
你在ADC_Convert函数中使用ADMUX |= channel;来选择通道,这种方式会保留ADMUX寄存器中的其他位(如参考电压选择、对齐方式等),可能导致通道选择不准确。

应该先清除通道选择位(MUX3:0),再设置新的通道。可以使用ADMUX = (ADMUX & 0xF0) | channel;来确保只修改通道选择位。

2. ADC结果读取问题
你只读取了ADCH(高8位),而没有读取ADCL(低8位)。对于10位精度的ADC,需要同时读取ADCL和ADCH,否则结果可能不准确。

读取顺序应该是先读ADCL,再读ADCH。

3. ADC初始化问题
你在ADMUX中设置了左对齐(0x60),这意味着结果的高8位在ADCH中,低2位在ADCL的高2位。如果你只读取ADCH,会丢失精度。

如果需要完整的10位结果,建议使用右对齐(清除ADLAR位)。

4. 通道输入配置问题
你设置了DDRC &= 0xEB;,但PORTC的配置没有明确说明。如果PORTC的上拉电阻未启用,可能会导致输入信号不稳定。

建议将PORTC的对应引脚设置为输入模式,并启用上拉电阻(如果需要)。
捉虫天师 发表于 2025-3-21 16:26 | 显示全部楼层
试试下面的代码
  1. #include <iom48v.h>
  2. #include <macros.h>

  3. #define uint unsigned int
  4. #define uchar unsigned char

  5. uint temp1 = 0, temp4 = 0;

  6. uint ADC_Convert(uchar channel)
  7. {
  8.     ADMUX = (ADMUX & 0xF0) | channel; // 清除通道选择位并设置新通道
  9.     ADCSRA |= (1 << ADSC);            // 开始转换
  10.     while (!(ADCSRA & (1 << ADIF)));  // 等待转换结束
  11.     ADCSRA |= (1 << ADIF);            // 清除转换结束标记
  12.     return ADC;                       // 读取完整的10位结果(先读ADCL,再读ADCH)
  13. }

  14. void main(void)
  15. {
  16.     DDRD |= 0x80;    // 设置PD7为输出
  17.     PORTD &= 0x7F;   // PD7初始化为低电平

  18.     DDRC &= 0xEB;    // 设置PC2和PC4为输入
  19.     PORTC |= 0x14;   // 启用PC2和PC4的上拉电阻

  20.     ADCSRA = 0x00;   // 关闭ADC
  21.     ADMUX = 0x40;    // 使用AVCC作为参考电压,右对齐
  22.     ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // 使能ADC,设置预分频为128

  23.     while (1)
  24.     {
  25.         temp1 = ADC_Convert(2); // 读取PC2的ADC值
  26.         if (temp1 > 40)
  27.             PORTD |= 0x80;     // 如果结果大于40,PD7置高

  28.         temp4 = ADC_Convert(4); // 读取PC4的ADC值
  29.         if (temp4 < 40)
  30.             PORTD &= 0x7F;      // 如果结果小于40,PD7置低
  31.     }
  32. }
捉虫天师 发表于 2025-3-21 16:26 | 显示全部楼层
说明:
通道选择:使用ADMUX = (ADMUX & 0xF0) | channel;确保只修改通道选择位。

ADC结果读取:使用return ADC;读取完整的10位结果。

右对齐:将ADMUX设置为0x40,使用右对齐模式。

上拉电阻:启用PC2和PC4的上拉电阻,确保输入信号稳定。
捉虫天师 发表于 2025-3-21 16:26 | 显示全部楼层
建议:
使用示波器或逻辑分析仪检查PC2和PC4的输入信号,确保信号正常。

在调试时,可以打印temp1和temp4的值,观察ADC结果是否正确。
g36xcv 发表于 2025-3-27 15:26 | 显示全部楼层
在设置通道前,应该先清空 ADMUX 的通道位,然后再 OR (|) 赋值。
而服务器人 发表于 2025-3-31 15:59 | 显示全部楼层
你可以修改 ADC_Convert() 函数,使其在每次选择通道前 清除 ADMUX 中的通道选择部分,然后再设置新通道。
kepe 发表于 2025-4-24 14:55 | 显示全部楼层
应该先清除通道选择位,再设置新的通道。
kepe 发表于 2025-4-24 15:36 | 显示全部楼层
你在ADC_Convert函数中使用ADMUX |= channel;来选择通道
kepe 发表于 2025-4-24 15:52 | 显示全部楼层
清除转换结束标记
您需要登录后才可以回帖 登录 | 注册

本版积分规则

676

主题

3894

帖子

4

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