【发布时间】:2018-01-23 12:06:29
【问题描述】:
我正在将 LM35 与 Atmega8 连接。为了显示数字,我使用 7 段 LED 阳极显示器,我将其连接到 AVR 的两端(它在没有晶体管的情况下处理它,所以为什么不呢)。奇怪的事情发生了: 从 adc 分配后的 res 值为 237(23.7 度)。我想在我的显示器上打印第一个数字 (2)。 如果我在注释掉的时候留下最后一行,显示器首先正确显示数字 2,但在第一次延迟后显示 1 而不是 2。否则我得到正确的数字 2。为什么会发生这种情况?
#ifndef F_CPU
#define F_CPU 1000000UL
#endif // F_CPU
#include <avr/io.h>
#include <util/delay.h>
#define DELAY_IN_MS 500 /* 0.5 sec */
int numbers[] = {
0b01000000,
0b01110011,
0b00100100,
0b00100001,
0b00010011,
0b00001001,
0b00001000,
0b01100011,
0b00000000,
0b00000001,
0b11111111 // off
};
uint8_t digits[3];
void initADC()
{
ADMUX=(1<<REFS1)|(1<<REFS0);
ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
}
uint16_t ReadADC(uint8_t ch)
{
//Select ADC Channel ch must be 0-7
ch=ch&0b00000111;
ADMUX|=ch;
//Start Single conversion
ADCSRA|=(1<<ADSC);
//Wait for conversion to complete
while(!(ADCSRA & (1<<ADIF)));
//Clear ADIF by writing one to it
ADCSRA|=(1<<ADIF);
return(ADC);
}
int main()
{
DDRD = 0xFF;
PORTD = 0xFF;
DDRB = 0b00000001;
PORTB = 1;
initADC();
uint16_t adc_value;
uint16_t res;
while(1)
{
adc_value = 0;
for (int i = 0; i < 250; i++)
{
adc_value += ReadADC(0);
}
adc_value=(adc_value/25)/4;
res = adc_value;
for(int j = 2; j >= 0; j--) {
digits[j] = res%10;
res /= 10;
}
uint8_t dig = digits[0];
PORTD = numbers[dig];
_delay_ms(DELAY_IN_MS);
// if following is uncommented there blinks digit two correctly
// if commented there is unblinking digit 1
PORTD = numbers[10]; // display off
}
return 0;
}
【问题讨论】:
-
hmmm 可能是错误的数组索引或 MSB 或 LSB 第一种情况?
-
不确定是什么问题,但我会将数字数组更改为
uint8_t而不是int。你有任何可能调试你的代码吗? -
@Maku 好的。可悲的是我无法调试它(或不知道如何)。我唯一可以“调试”的是LM35输出,我可以用电压表读取。我想知道,是否可能是显示器耗电过多导致 ADC 计算不正确?
-
给定 ADC 的分辨率在这里很重要。除非它是 8 位,否则此代码将崩溃并烧毁,因为您无法将 250 次 ADC 读取的总和存储在 16 位变量中。微控制器的行业最低标准是 10 位 ADC。 12 位越来越普遍。你真的在使用 8 位 ADC 吗?
-
@Lundin 为什么要“崩溃和燃烧”?确实 250*16bit 不适合 16bit 变量,但它不会崩溃 - 如果我没记错的话它只会翻转。