我正在尝试使用ATmega328P制作接近传感器。我使用板载ADC转换电压值,如果它高于环境温度,LED会亮起。
在电路中,VOUT将进入ADC通道3并应被感知(想想右侧的LED作为IR传感器)。
当程序启动时,它会检测到30个读数并将其平均值用作环境设置。如果任何后续测量值高于此值,LED应点亮。
但即使我将手放在传感器上方,LED也不亮。
我只用LED测试,看看红外传感器是否正常。顺便说一下,这是好的。
微控制器的代码如下:
/*
* Proximity Sensor IR.c
*
* Created: 6/3/2017 2:35:33 PM
* Author : Rishav
*/
#include <avr/io.h>
#include <stdio.h>
#define F_CPU 16000000UL
#include <util/delay.h>
int calibration()
{
unsigned int sum = 0;
for (int i=0; i<30; i++)
{
ADCSRA |= (1<<ADSC);
while(!(ADCSRA & (1<<ADIF)));
ADCSRA |= (1<<ADIF);
sum += (ADCH<<8)|ADCL;
}
return (sum/30);
}
int main(void)
{
unsigned int val = 0;
ADMUX |= (0<<REFS1)|(1<<REFS0)|(0<<MUX3)|(0<<MUX2)|(1<<MUX1)|(1<<MUX0); //setting the multiplexer to ADC3
ADCSRA |= (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
DDRB = 0b00000010;
DDRD |= (1<<PCINT22);
PORTD |= (1<<PCINT22);
int calib_value = calibration();
while (1)
{
ADCSRA |= (1<<ADSC);
while(!(ADCSRA & (1<<ADIF)));
val = (ADCH<<8)|ADCL;
ADCSRA |= (1<<ADIF);
if (val > calib_value)
PORTB = 0b00000010;
}
}
我认为代码中存在一些问题。请帮忙。
答案 0 :(得分:1)
查看代码时会想到一些事情:
ADMUX
和ADCSRA
个注册表 - 您在其中放置的所有内容都只是&#39; ORed&#39; -in。 (ADLAR
中的ADMUX
未处于已定义的状态,例如,ADCSRA
具有更多未定义的位。)calibration
中的第一次测量将会消失。解决这个问题的最简单方法是先进行一次测量,然后忽略其结果。 (或者在设置ADC后等待几毫秒)。ADCL
之前读取ADCH
(AVR锁定ADC,以便在读取ADCL时将更多结果写入结果寄存器,直到读取ADCH为止好)。您当前的代码具有这两个寄存器的未定义读取顺序。答案 1 :(得分:0)
您必须首先启用ADC,然后选择通道和参考电压。在数据表中很容易跳过这个事实。
通过将ADCSRA中的ADC使能位ADEN置1来使能ADC。 电压参考和输入通道选择不会生效 直到ADEN设定。 Datasheet page 238.
我没有检查您的所有设置,但我很确定这一定是您的问题。
示例顺序:
void init_adc()
{
ADCSRA |= (1<<ADEN); // enable ADC
ADMUX |= (1<<MUX1) | (1<<MUX0); // channel selection ADC3 - PB3
ADMUX &= ~(1<<REFS0); // VCC as reference
ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // setting prescaler to 128
}
如上所述,您应首先阅读ADCL:
必须先读取ADCL,然后再读取ADCH,以确保其内容 数据寄存器属于同一转换
我建议将此部分移动到一个单独的函数中:
uint16_t read_adc()
{
ADCSRA |= (1<<ADSC);
while(!(ADCSRA & (1<<ADIF)));
uint8_t adcl = ADCL;
uint8_t adch = ADCH;
ADCSRA |= (1<<ADIF);
return (adch<<8) | adcl;
}