АЦП в atmega8

Обсуждаем контроллеры компании Atmel.
Ответить
Нашел транзистор. Понюхал.
Сообщения: 194
Зарегистрирован: Сб ноя 07, 2009 15:27:59

Сообщение kushman »

Подключил к atmega8 датчик температуры, схема подлючения - делитель напряжения (опорный резистор и датчик температуры - каждый по 1 кОм), соответственно со средней точки снимается показание АЦП. Проблема в следующем - измеряю тестером напряжение на средней точке - 0.1 В, вытаскиваю атмегу8 из кроватки - все становится нормально, примерно 2.5 вольтра. Видимо какая-то проблема со входным сопротивлением АЦП, может его надо как-то настраивать?
Реклама
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

Сообщение ChipKiller »

Видимо какая-то проблема со входным сопротивлением АЦП, может его надо как-то настраивать?
как пример или так
Реклама
Нашел транзистор. Понюхал.
Сообщения: 194
Зарегистрирован: Сб ноя 07, 2009 15:27:59

Сообщение kushman »

ChipKiller писал(а):
Видимо какая-то проблема со входным сопротивлением АЦП, может его надо как-то настраивать?
как пример или так
М, пардон, так и не понял, в чем хитрость?
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

"Ножка" контроллера, которая может работать входом АЦП, ещё может быть как цифровым входом, так и цифровым выходом (похоже оно у вас так и настроено и на выходе логический "0", близкий к 0 вольт). Вот её и надо в программе настроить как вход АЦП, а потом командовать АЦП "измерить" и т.д.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Реклама
Эиком - электронные компоненты и радиодетали
Прорезались зубы
Аватара пользователя
Сообщения: 222
Зарегистрирован: Чт июл 08, 2010 01:03:40
Откуда: Украина, Киев

Сообщение Antifritz »

Короче, соответствующий бит регистра DDRC в 0 сбросить.
Реклама
Нашел транзистор. Понюхал.
Сообщения: 194
Зарегистрирован: Сб ноя 07, 2009 15:27:59

Сообщение kushman »

Да, действительно, настроил порт как вход, теперь все хорошо. Большое спасибо.
И еще такой вопрос, чтотбы темы не плодить. Пытаюсь вывести на дисплей измеряемое напряжение, код приведен ниже. А в ответ выводится лишь пустота. Что не так?

Код: Выделить всё

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);   
   
}
Символ I использую как индикатор сработавшего прерывания.
Реклама
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

А почему вы только ADCH читаете?
У вас прерывание вызывается? Может, вы их забыли включить ( 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
Контактная информация:
Нашел транзистор. Понюхал.
Сообщения: 194
Зарегистрирован: Сб ноя 07, 2009 15:27:59

Сообщение kushman »

Все равно на дисплее пусто. Может с выводом что не так?
Прерывание да, срабатывает. А один байт обрабатываю, поскольку АЦП 10 разрядов, а 2 из них как правило прыгают.
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

Тогда действительно, дисплей не выводит. Попробуйте отдельно на него что-нибудь вывести.
И день и ночь в пути...
Мои программки: 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

Сообщение kushman »

Хм..А что же тут не так. Этот дисплей с этим кодом прекрасно работал с 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++;
    }
} 
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

Так вы на дисплей уже что-нибудь выводили этой вашей функцией?
И день и ночь в пути...
Мои программки: 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

Сообщение kushman »

Да, с помощью sprinf выводил строчку. А вот с переменной она что-то отказывается работать.
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

В обе строки дисплея выводили? А из прерывания выводили? Я не встречал, чтобы sprintf глючила...
И день и ночь в пути...
Мои программки: 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

Сообщение kushman »

Да, в обе строки все выводится.
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

Тогда вы покажите, как у вас lcd_buffer объявлен.
И день и ночь в пути...
Мои программки: 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

Сообщение kushman »

da-nie писал(а):Тогда вы покажите, как у вас lcd_buffer объявлен.
LCD_Buffer объявлен таким образом:
unsigned char lcd_buffer[LCD_BUFFER_SIZE];
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

Тогда чудеса... :?
А вы всю программу приведите, если не трудно. Это очень странно...
И день и ночь в пути...
Мои программки: 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

Сообщение kushman »

Вот код программы:

Код: Выделить всё

#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) {}          
}
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

А где вы включаете прерывания с помощью sei()? :?

Я, правда, не знаю, как в вашем IDE и компиляторе это сделано. Я использую WinAVR.
И день и ночь в пути...
Мои программки: 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

Сообщение kushman »

В функции main разрешаются все прерывания и прерывания от АЦП. В регистрах SREG и ADCSRA. Вот код:

Код: Выделить всё

 
SREG.7=1; //разрешение всех прерываний 
ADCSRA.6=1; //разрешение прерываний от АЦП
Ответить

Вернуться в «AVR»