АЦП в atmega8
- Сообщения: 194
- Зарегистрирован: Сб ноя 07, 2009 15:27:59
Подключил к atmega8 датчик температуры, схема подлючения - делитель напряжения (опорный резистор и датчик температуры - каждый по 1 кОм), соответственно со средней точки снимается показание АЦП. Проблема в следующем - измеряю тестером напряжение на средней точке - 0.1 В, вытаскиваю атмегу8 из кроватки - все становится нормально, примерно 2.5 вольтра. Видимо какая-то проблема со входным сопротивлением АЦП, может его надо как-то настраивать?
- Реклама
- Сообщения: 194
- Зарегистрирован: Сб ноя 07, 2009 15:27:59
М, пардон, так и не понял, в чем хитрость?
"Ножка" контроллера, которая может работать входом АЦП, ещё может быть как цифровым входом, так и цифровым выходом (похоже оно у вас так и настроено и на выходе логический "0", близкий к 0 вольт). Вот её и надо в программе настроить как вход АЦП, а потом командовать АЦП "измерить" и т.д.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
- Реклама
- Сообщения: 194
- Зарегистрирован: Сб ноя 07, 2009 15:27:59
Да, действительно, настроил порт как вход, теперь все хорошо. Большое спасибо.
И еще такой вопрос, чтотбы темы не плодить. Пытаюсь вывести на дисплей измеряемое напряжение, код приведен ниже. А в ответ выводится лишь пустота. Что не так?
Символ I использую как индикатор сработавшего прерывания.
И еще такой вопрос, чтотбы темы не плодить. Пытаюсь вывести на дисплей измеряемое напряжение, код приведен ниже. А в ответ выводится лишь пустота. Что не так?
Код: Выделить всё
interrupt [ADC_INT] void ADC_ISR(void) {
float voltage;
voltage = (ADCH*2.56)/255;
send_lcd_symbol(set_second_line, 'I');
sprintf(lcd_buffer, "%f", voltage);
send_lcd(set_first_line, lcd_buffer);
}А почему вы только ADCH читаете?
У вас прерывание вызывается? Может, вы их забыли включить ( sei() ) или не указали АЦП работать с прерыванием.
Я когда-то делал без прерывания так:
У вас прерывание вызывается? Может, вы их забыли включить ( sei() ) или не указали АЦП работать с прерыванием.
Я когда-то делал без прерывания так:
Код: Выделить всё
...
//включаем АЦП на канале PC5 в режиме одиночного преобразования
ADMUX=(0<<MUX3)|(1<<MUX2)|(0<<MUX1)|(1<<MUX0)|(0<<ADLAR)|(0<<REFS0)|(0<<REFS1);
//MUX0-MUX3 - выбор входа (0101=PC5)
//ADLAR -выравнивание преобразования (0=не нужно)
//REFS0,REFS1-выбор опорного напряжения (0,0=внешний вход aref)
ADCSR=(1<<ADEN)|(0<<ADSC)|(0<<ADFR)|(0<<ADIF)|(0<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
//ADEN-включение преобразования АЦП (1=включено)
//ADSC-запуск преобразования (0=выключено)
//ADFR-режим работы АЦП (0=одиночное преобразование)
//ADIF-флаг прерывания от компаратора (0=выключено)
//ADIE-разрешение прерываний от компаратора (0=выключено)
//ADPS0-ADPS2-выбор частоты преобразования (111=делитель 128)
SFIOR=0;
...
//----------------------------------------------------------------------------------------------------
//получить показания АЦП
//----------------------------------------------------------------------------------------------------
unsigned short GetADC(void)
{
if (ADCSR&(1<<ADIF)) ADCSR^=(1<<ADIF);
ADCSR|=(1<<ADSC);//запускаем преобразование
while((ADCSR&(1<<ADSC)));//ждём завершения преобразования
//читаем полученное значение
unsigned char l=ADCL;
unsigned char h=ADCH;
unsigned short value=((unsigned short)(h)<<8)|((unsigned short)(l));
return(value);
}
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
- Сообщения: 194
- Зарегистрирован: Сб ноя 07, 2009 15:27:59
Все равно на дисплее пусто. Может с выводом что не так?
Прерывание да, срабатывает. А один байт обрабатываю, поскольку АЦП 10 разрядов, а 2 из них как правило прыгают.
Прерывание да, срабатывает. А один байт обрабатываю, поскольку АЦП 10 разрядов, а 2 из них как правило прыгают.
Тогда действительно, дисплей не выводит. Попробуйте отдельно на него что-нибудь вывести.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
- Сообщения: 194
- Зарегистрирован: Сб ноя 07, 2009 15:27:59
Хм..А что же тут не так. Этот дисплей с этим кодом прекрасно работал с ADuC845.
Может что не так с этой строчкой?
Вот функция вывода на дисплей, немного кривая, но хорошо работающая)
Может что не так с этой строчкой?
Код: Выделить всё
sprintf(lcd_buffer, "%f", value);Вот функция вывода на дисплей, немного кривая, но хорошо работающая)
Код: Выделить всё
void send_lcd(unsigned char line,unsigned char *txt) {
unsigned int i=0;
while(txt[i]!=NULL) {
send_lcd_symbol(line+i, txt[i]);
i++;
}
}
Так вы на дисплей уже что-нибудь выводили этой вашей функцией?
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
- Сообщения: 194
- Зарегистрирован: Сб ноя 07, 2009 15:27:59
Да, с помощью sprinf выводил строчку. А вот с переменной она что-то отказывается работать.
В обе строки дисплея выводили? А из прерывания выводили? Я не встречал, чтобы sprintf глючила...
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
- Сообщения: 194
- Зарегистрирован: Сб ноя 07, 2009 15:27:59
Тогда вы покажите, как у вас lcd_buffer объявлен.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
- Сообщения: 194
- Зарегистрирован: Сб ноя 07, 2009 15:27:59
LCD_Buffer объявлен таким образом:da-nie писал(а):Тогда вы покажите, как у вас lcd_buffer объявлен.
unsigned char lcd_buffer[LCD_BUFFER_SIZE];
Тогда чудеса...
А вы всю программу приведите, если не трудно. Это очень странно...
А вы всю программу приведите, если не трудно. Это очень странно...
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
- Сообщения: 194
- Зарегистрирован: Сб ноя 07, 2009 15:27:59
Вот код программы:
Код: Выделить всё
#include <mega8.h>
#include <delay.h>
#include <stdio.h>
#define set_first_line 0x80
#define set_second_line 0xC0
#define LCD_BUFFER_SIZE 16
unsigned char lcd_buffer[LCD_BUFFER_SIZE]; //Buffer for LCD
#define RS PORTB.2
#define RW PORTB.1
#define En PORTB.0
void send_lcd_4bit(unsigned char send_data) {
PORTD=send_data;
En=1;
delay_ms(30);
En=0;
}
void send_lcd_cmd(unsigned char send_data) {
RS=0;
send_lcd_4bit(send_data);
send_data=(send_data << 4);
send_lcd_4bit(send_data);
}
void send_lcd_data(unsigned char send_data) {
RS=1;
send_lcd_4bit(send_data);
send_data=(send_data << 4);
send_lcd_4bit(send_data);
}
void LCD_Init(void) {
send_lcd_4bit(0x30);
delay_ms(30);
send_lcd_4bit(0x30);
delay_ms(30);
send_lcd_4bit(0x30);
delay_ms(30);
send_lcd_4bit(0x20);
delay_ms(30);
send_lcd_cmd(0x28);
delay_ms(30);
send_lcd_cmd(0x0C);
delay_ms(30);
send_lcd_cmd(0x06);
delay_ms(30);
send_lcd_cmd(0x01);
}
void send_lcd_symbol(unsigned char adress, unsigned char send_data) {
send_lcd_cmd(adress);
send_lcd_data(send_data);
}
void send_lcd(unsigned char line,unsigned char *txt) {
unsigned int i=0;
while(txt[i]!=NULL) {
send_lcd_symbol(line+i, txt[i]);
i++;
}
}
void ADC_Init(void) {
ADMUX=0x0E;
ADCSRA=0x9F;
}
interrupt [ADC_INT] void ADC_ISR(void) {
unsigned char l,h, value;
send_lcd_symbol(set_second_line, 'I');
l=ADCL;
h=ADCH;
value=((unsigned short)(h)<<8)|((unsigned short)(l));
sprintf(lcd_buffer, "%f", value);
send_lcd(set_first_line, lcd_buffer);
}
void main(void) {
DDRB=0xFF;
DDRD=0xFF;
DDRC=0x00;
LCD_Init();
ADC_Init();
SREG.7=1;
ADCSRA.6=1;
while(1) {}
}
А где вы включаете прерывания с помощью sei()?
Я, правда, не знаю, как в вашем IDE и компиляторе это сделано. Я использую WinAVR.
Я, правда, не знаю, как в вашем IDE и компиляторе это сделано. Я использую WinAVR.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
- Сообщения: 194
- Зарегистрирован: Сб ноя 07, 2009 15:27:59
В функции main разрешаются все прерывания и прерывания от АЦП. В регистрах SREG и ADCSRA. Вот код:
Код: Выделить всё
SREG.7=1; //разрешение всех прерываний
ADCSRA.6=1; //разрешение прерываний от АЦП


