Управление реле на Atmega8

Обсуждаем контроллеры компании Atmel.
Ответить
Родился
Сообщения: 6
Зарегистрирован: Сб июн 08, 2013 10:26:13

Сообщение yakidiman »

Доброго времени суток. Делаю устройство для управления релюшками на atmege8. Смысл в том, что исходными сигналами для включения и отключения реле являются два сигнала с АЦП. Так в целом программу написал, в протеусе промоделировал, все отлично. Но когда собрал на макетке и подаю питание, то на нужных мне пинах сразу появляется "1". И это независимо, что на входе АЦП, даже подтягивал эти входы к земле. Вот сама программа, ну а схема я думаю тут и не нужна, т.к. проще некуда.
Помогите пожалуйста, разобраться где собака порылась.
Спойлер#define F_CPU 1000000
#include <avr/io.h>
#include <avr/iom8.h>
# include <util/delay.h>
#include <AVR/interrupt.h>
#define sei()
// Опорное напряжение - ножка AREF
#define ADC_VREF_TYPE 0b00000000

unsigned int ADCdata;
unsigned int ADCdata1;
void ADC1(ADCdata);

unsigned int ADCRead(unsigned char adc_input) // Подпрограмма считывания данных с АЦП
{
ADMUX = adc_input | ADC_VREF_TYPE;
//Задержка для стабилизации АЦП
_delay_us(50);
// Запускаем АЦП
ADCSRA |= 0x40;
while ((ADCSRA & 0x10) == 0); // Ждем флага окончания преобразования
ADCSRA |= 0x10;
return ADCW;
}

int main(void)
{
DDRD=0xFF;
PORTD=0x00;

/*** Настройка АЦП ***/
ADCSRA |= (1 << ADEN)|(1 << ADPS2)|(1 << ADPS1)|(0 << ADPS0);

while(1)
{
// вход ADC0
//включение, настройка АЦП
ADCSRA |= (1 << ADEN)|(1 << ADPS2)|(0 << ADPS1)|(1 << ADPS0);
ADMUX |= (0 << REFS1)|(0 << REFS0)|(0 << MUX0)|(0 << MUX1)|(0 << MUX2)|(0 << MUX3);
_delay_us(50);
ADCSRA |= (1 << ADSC); //начало преобразования
while((ADCSRA&(1 << ADIF))== 0); //ждем прерывания
ADCSRA |= (1 << ADIF);
ADCdata = ADCRead(0);// Запись результата с первого порта АЦП

// вход ADC1
ADMUX |= (0 << REFS1)|(0 << REFS0)|(1 << MUX0)|(0 << MUX1)|(0 << MUX2)|(0 << MUX3);
_delay_us(50);
ADCSRA |= (1 << ADSC); //начало преобразования
while((ADCSRA&(1 << ADIF))== 0); //ждем прерывания
ADCSRA |= (1 << ADIF);
ADCdata1 = ADCRead(1); //запись результата
ADCSRA |= (0 << ADEN); //выключение АЦП

if ((ADCdata >= 341)&&(ADCdata1 >= 10)) // 0.625V
{
PORTD = 0b00000100;

}
else
{
PORTD=0b00000000;
}

//_delay_ms(30);
}


}
Реклама
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Не вникал особо, но в глаза бросилось что вы не правильно сбрасываетет биты.....

например у вас в цикле крутится: включение канала 1
ADMUX |= (0 << REFS1)|(0 << REFS0)|(1 << MUX0)|(0 << MUX1)|(0 << MUX2)|(0 << MUX3);
потом включение канала 0
ADMUX |= (0 << REFS1)|(0 << REFS0)|(0 << MUX0)|(0 << MUX1)|(0 << MUX2)|(0 << MUX3);
но так вы не включите канал 0, т.к. этой командой бит MUX0 не сбросится (и вообще эта команда абсолютно ничего не делает с содержимым ADMUX, что бы там не находилось).....

то же самое и тут:
ADCSRA |= (0 << ADEN); //выключение АЦП
так бит не сбросиш.....

не знаю как это влияет на работоспособность программы, но на заметку возьмите.....



А это еще зачем?
#define sei()
Реклама
Опытный кот
Сообщения: 804
Зарегистрирован: Чт мар 12, 2009 16:31:05

Сообщение Vov123 »

это какой-то бред,а не программа. :shock:
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

Как то так надо:

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

#define F_CPU 1000000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

unsigned int ADCdata;
unsigned int ADCdata1;
unsigned int ADCRead(unsigned char adc_input);


int main(void)
{
    DDRD = 0xFF;

    //настройка ADC
    ADMUX = 0;                                    //внешний опорный источник
    ADCSR = (1<<ADEN)|(1<<ADPS2)|(0<<ADPS1)|(1<<ADPS0);

    while(1)
    {    
        ADCdata  = ADCRead (0<<MUX0);            //вход ADC0
        ADCdata1 = ADCRead (1<<MUX0);            //вход ADC1
        
        if ((ADCdata >= 341)&&(ADCdata1 >= 10)) // 0.625V  //анализ результата
            PORTD = 0b00000100; 
        else
            PORTD = 0b00000000;
    } 
}


unsigned int ADCRead(unsigned char adc_input)     // Подпрограмма считывания данных с АЦП
{
    ADMUX = adc_input;    
    _delay_us(50);                                //Задержка для стабилизации АЦП    
    ADCSR |= (1<<ADSC);                            //запустить преобразование 
    while (ADCSR & (1<<ADSC)){}                     //крутимся в цикле до конца замера
    return (ADCL + (ADCH<<8));
} 
Реклама
Эиком - электронные компоненты и радиодетали
Опытный кот
Сообщения: 804
Зарегистрирован: Чт мар 12, 2009 16:31:05

Сообщение Vov123 »

Свой вариант предложу,только настройки АЦП немного другие.ТС может легко их исправить.

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

#define F_CPU 1000000
#include <avr/io.h>
#include <util/delay.h>

unsigned int ADCdata;

int main(void)
{
DDRD=0xFF;
PORTD=0x00;

//опорное напряжение от питания,выравнивание в право(10бит)
//ручное преобразование,вход на ADC3 
ADCSRA=0b10000111;
ADMUX=0b01000011;  

while(1)
{

ADCSRA |= (1 << 6); //начало преобразования
loop_until_bit_is_clear(ADCSRA,6);
ADCdata = ADCW;
if ((ADCdata >= 10)&&(ADCdata <= 341))PORTD = 0b00000100; // 0.625V
else
PORTD=0b00000000;

_delay_ms(500);
}


}
Реклама
Родился
Сообщения: 6
Зарегистрирован: Сб июн 08, 2013 10:26:13

Сообщение yakidiman »

shads писал(а):Как то так надо:

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

#define F_CPU 1000000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

unsigned int ADCdata;
unsigned int ADCdata1;
unsigned int ADCRead(unsigned char adc_input);


int main(void)
{
    DDRD = 0xFF;

    //настройка ADC
    ADMUX = 0;                                    //внешний опорный источник
    ADCSR = (1<<ADEN)|(1<<ADPS2)|(0<<ADPS1)|(1<<ADPS0);

    while(1)
    {    
        ADCdata  = ADCRead (0<<MUX0);            //вход ADC0
        ADCdata1 = ADCRead (1<<MUX0);            //вход ADC1
        
        if ((ADCdata >= 341)&&(ADCdata1 >= 10)) // 0.625V  //анализ результата
            PORTD = 0b00000100; 
        else
            PORTD = 0b00000000;
    } 
}


unsigned int ADCRead(unsigned char adc_input)     // Подпрограмма считывания данных с АЦП
{
    ADMUX = adc_input;    
    _delay_us(50);                                //Задержка для стабилизации АЦП    
    ADCSR |= (1<<ADSC);                            //запустить преобразование 
    while (ADCSR & (1<<ADSC)){}                     //крутимся в цикле до конца замера
    return (ADCL + (ADCH<<8));
} 
Все также, на третьем пине D "1" появляется сразу же, а в протеусе все четко.
Реклама
Вымогатель припоя
Сообщения: 599
Зарегистрирован: Ср янв 06, 2010 10:01:46

Сообщение metan »

yakidiman писал(а):Все также, на третьем пине D "1" появляется сразу же
А где вы сказали процессору, что там ноль обязан быть?
Вот Vov123 в своей программе сказал.
Родился
Сообщения: 6
Зарегистрирован: Сб июн 08, 2013 10:26:13

Сообщение yakidiman »

metan писал(а):
yakidiman писал(а):Все также, на третьем пине D "1" появляется сразу же
А где вы сказали процессору, что там ноль обязан быть?
Вот Vov123 в своей программе сказал.
Когда я сказал процессору в начальном состоянии должно быть ноль, он переходит в неопределенное состояние, нужный мне порт тоже так же
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

ребят, харош курить, разговоры с процессорами до хорошего не доведут :)))
пиши PORTD = 0; там где ты DDRD определяешь.
Ставим плюсы: )
Родился
Сообщения: 6
Зарегистрирован: Сб июн 08, 2013 10:26:13

Сообщение yakidiman »

проблема с 0 и 1 решилась, появилась другая проблема. Теперь когда входы АЦП подтянуты на землю, все нормально, но стоит поставить на ацп просто провода от датчиков не подключая сами датчики, то на том же пине D3 появляется 2,5В. Также при подключенных датчиках.
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

Посмотрите осциллографомскопом форму импульсов на выходе 3. Висящий в воздухе вход АЦП может давать все что угодно.
Ставим плюсы: )
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

metan писал(а):А где вы сказали процессору, что там ноль обязан быть?
Вот Vov123 в своей программе сказал.
ibiza11 писал(а):пиши PORTD = 0; там где ты DDRD определяешь.
Программа крутится в этом цикле, и будет там 0 или 1 зависит от результатов измерения АЦП, а не от того что пропишеш при старте.....

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

   while(1)
    {    
        ADCdata  = ADCRead (0<<MUX0);            //вход ADC0
        ADCdata1 = ADCRead (1<<MUX0);            //вход ADC1
        
        if ((ADCdata >= 341)&&(ADCdata1 >= 10)) // 0.625V  //анализ результата
            PORTD = 0b00000100; 
        else
            PORTD = 0b00000000; 
yakidiman писал(а):проблема с 0 и 1 решилась
Ну так хоть намекни уж в чем проблема была.... небось с опорным напряжением накосячил.....
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

shads писал(а):Программа крутится в этом цикле, и будет там 0 или 1 зависит от результатов измерения АЦП, а не от того что пропишеш при старте.....
А Вы не видите, что перед выводом в порт ожидается два преобразования АЦП? За это время светодиод может моргнуть (продолжительность зависит от времени преобразования АЦП), поскольку начальное значение явно не задано. До окончания преобразования в порту будет именно то, что вывели при инициализации. Все переменные должны быть заданы явно. Пишите правильно, раз советы даете.
Ставим плюсы: )
Родился
Сообщения: 6
Зарегистрирован: Сб июн 08, 2013 10:26:13

Сообщение yakidiman »

shads писал(а):
metan писал(а):А где вы сказали процессору, что там ноль обязан быть?
Вот Vov123 в своей программе сказал.
ibiza11 писал(а):пиши PORTD = 0; там где ты DDRD определяешь.
Программа крутится в этом цикле, и будет там 0 или 1 зависит от результатов измерения АЦП, а не от того что пропишеш при старте.....

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

   while(1)
    {    
        ADCdata  = ADCRead (0<<MUX0);            //вход ADC0
        ADCdata1 = ADCRead (1<<MUX0);            //вход ADC1
        
        if ((ADCdata >= 341)&&(ADCdata1 >= 10)) // 0.625V  //анализ результата
            PORTD = 0b00000100; 
        else
            PORTD = 0b00000000; 
yakidiman писал(а):проблема с 0 и 1 решилась
Ну так хоть намекни уж в чем проблема была.... небось с опорным напряжением накосячил.....
Да, проблема была именно в этом, я неправильное опорное напряжение подавал))) Кстати, и моя и ваша программа отлично работают. Все нужные мне биты АЦП сбрасываются. Так что спасибо!
Родился
Сообщения: 6
Зарегистрирован: Сб июн 08, 2013 10:26:13

Сообщение yakidiman »

ibiza11 писал(а):
shads писал(а):Программа крутится в этом цикле, и будет там 0 или 1 зависит от результатов измерения АЦП, а не от того что пропишеш при старте.....
А Вы не видите, что перед выводом в порт ожидается два преобразования АЦП? За это время светодиод может моргнуть (продолжительность зависит от времени преобразования АЦП), поскольку начальное значение явно не задано. До окончания преобразования в порту будет именно то, что вывели при инициализации. Все переменные должны быть заданы явно. Пишите правильно, раз советы даете.

Сейчас все работает. Работает и начальным заданием порта D и без него.
Ответить

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