Не могу насторить АЦП в ATmega

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
stas00n
Вымогатель припоя
Сообщения: 557
Зарегистрирован: Пн мар 23, 2009 04:03:45

Re: Не могу насторить АЦП в ATmega

Сообщение stas00n »

Проверьте в своем компиляторе, будет ли работать конструкция типа
ADCSRA.ADIF = 0;
У меня CVAVR ругается, т.к. регистры не описаны структурами.
В инициализации надо делать просто присваивание (оператор "="); составное присваивание (|=, &= ) - это когда нужно дрыгнуть одним/несколькими битами, не трогая при этом остальных. А при инициализации просто присваиваем регистру значение безо всяких И/ИЛИ:

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

// Инициализация АЦП
void ADCinit()
{

    ADMUX = (1 << 6);  //АЦП работает от Vcc, прием данных по A0
    ADCSRA = (1 << 7) | (1 << 6) | (1 << 3) |  (1 << 2) | (1 << 1);

}
Кот-тоК
Открыл глаза
Сообщения: 42
Зарегистрирован: Чт окт 28, 2010 19:33:35

Re: Не могу насторить АЦП в ATmega

Сообщение Кот-тоК »

stas00n писал(а):

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

ADCSRA &= ~(1<<ADIE);  
ADCSRA      &= ~(1<<ADIF);


}


Поставил, перестало работать. Он отображает одно и тоже значение, которое вычислил в первый раз в прерывании.
Кот-тоК
Открыл глаза
Сообщения: 42
Зарегистрирован: Чт окт 28, 2010 19:33:35

Re: Не могу насторить АЦП в ATmega

Сообщение Кот-тоК »

stas00n писал(а):Проверьте в своем компиляторе, будет ли работать конструкция типа
ADCSRA.ADIF = 0;
У меня CVAVR ругается, т.к. регистры не описаны структурами.


Неа, у меня тоже ругается.
stas00n
Вымогатель припоя
Сообщения: 557
Зарегистрирован: Пн мар 23, 2009 04:03:45

Re: Не могу насторить АЦП в ATmega

Сообщение stas00n »

Proteus все-равно пишет, что в реальном времени не может симулировать т.к. проц перегружен.

Вероятно, код генерится неоптимальный, надо как-то "договариваться" с компилятором, чтоб он фигню бесполезную не делал. Возможно дело в этих сдвиговых операциях - CVAVR их делает по-настоящему, не знаю как WinAVR. Компиляторы, которыми раньше доводилось пользоваться влет понимали что от них требуется и просто "отсекали лишнее" :)) Может, пригодится ассемблерная вставка...

Поставил, перестало работать. Он отображает одно и тоже значение, которое вычислил в первый раз в прерывании.

А регистр ADCH точно читается в прерывании? Пока его не прочитаешь, новое преобразование не начнется!
Кот-тоК
Открыл глаза
Сообщения: 42
Зарегистрирован: Чт окт 28, 2010 19:33:35

Re: Не могу насторить АЦП в ATmega

Сообщение Кот-тоК »

Сделаю так: скачаю CVAVR, там откомпилирую и посмотрю какой результат. Но не сейчас, надо отдохнуть, а то голова уже не варит. :)
Еще всё хорошенько обдумаю. Сегодня днем напишу, что получилось.
Кот-тоК
Открыл глаза
Сообщения: 42
Зарегистрирован: Чт окт 28, 2010 19:33:35

Re: Не могу насторить АЦП в ATmega

Сообщение Кот-тоК »

Забыл поблагодарить, что уже часа 4 мне помогаете. :))
Спасибо огромное! :beer: :beer: :beer:
stas00n
Вымогатель припоя
Сообщения: 557
Зарегистрирован: Пн мар 23, 2009 04:03:45

Re: Не могу насторить АЦП в ATmega

Сообщение stas00n »

Кот-тоК писал(а):
stas00n писал(а):

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

ADCSRA &= ~(1<<ADIE);  
ADCSRA      &= ~(1<<ADIF);


}


Поставил, перестало работать. Он отображает одно и тоже значение, которое вычислил в первый раз в прерывании.

Тьфу, блин, пора уже спать! Голова похоже не варит ни у меня, ни у тебя! Ты куда эту строчку
ADCSRA &= ~(1<<ADIE);
поставил? Это запрет прерываний от АЦП! после нее надо их обратно разрешить:
ADCSRA |= (1<<ADIE);
Запрет делается временно для того, чтобы при вычислении температуры ВНЕЗАПНОЕ :))) завершение преобразования (читай - прерывание) не исказило результат вычислений (т.к. изменится adcResult; считать-то начали еще со старым значением, а по вылету из прерывания может быть уже новое).
Кот-тоК
Открыл глаза
Сообщения: 42
Зарегистрирован: Чт окт 28, 2010 19:33:35

Re: Не могу насторить АЦП в ATmega

Сообщение Кот-тоК »

Не, там всё нормально, я и запретил и разрешил. Я в сообщении этого не отобразил. :)
stas00n
Вымогатель припоя
Сообщения: 557
Зарегистрирован: Пн мар 23, 2009 04:03:45

Re: Не могу насторить АЦП в ATmega

Сообщение stas00n »

Кстати, в CVAVR работает 16-битный доступ к результату АЦП, поэтому обработчик прерывания лучше такой, безо всяких сдвигов, компилируется в нормальный компактный код:

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

interrupt [ADC_INT] void Adc_Interrupt_Handler(void){
adcResult = ADCW;
ADCSRA &= ~(1<<ADIF)
}
Кот-тоК
Открыл глаза
Сообщения: 42
Зарегистрирован: Чт окт 28, 2010 19:33:35

Re: Не могу насторить АЦП в ATmega

Сообщение Кот-тоК »

Всем, опять большой привет!!!

Проверил я работоспособность программы в CVAVR - тоже самое :( Proteus пишет всё тоже - в реальном времени симулировать не возможно.

Вот рабочий код от Vov123

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

#include <mega8535.h>
#include <stdio.h>      //для sprintf
#include <delay.h>

// Alphanumeric LCD Module functions
#asm
   .equ __lcd_port=0x15 ;PORTC
#endasm
#include <lcd.h>



void main(void)
{
unsigned int a;//отображаемая переменная

char ss[30];  //буфер для LCD(размер зависит от длины отображаемой строки)
ADCSRA=0b10000111;  //настройкаа АЦП.Включен АЦП,прескалер максимальный
ADMUX=0b01000011;   //опорное напряжение от питания,выравнивание в право(10бит),ручное преобразование,вход на ADC3


// LCD module initialization
lcd_init(20);

while (1)
      {
       ADCSRA.6=1;             //запускаем преобазование
        while(ADCSRA.6==1){};   //ждём пока идёт преобразование(пустой цикл)
        a=ADCW;          //результат преобразования сохраняется в регистре ADCW
       sprintf(ss,"%u",a);
        lcd_gotoxy(0,0);   //положение в строке/номер строки(0-3)
        lcd_puts(ss);
        delay_ms(500);
        lcd_clear();

      };
}


Писал тоже самое для ATmega16 работает :) . Но странно, всё работает не смотря даже на то, что бит ADIE всегда 0
Proteus не ругается, всё работает зашибись.

Пишу код вида (уже выкладывал его)

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

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "LCM.h"
#include "ADC.h"

#define k 202
#define b -580

unsigned char ADCresult1 = 0, ADCresult2 = 0, ADCresult = 0;
unsigned char temperatura;

void main()
{

  unsigned long t;

  DDRB = 0xFF;
  DDRC = 0xFF;
  DDRD = 0xFF;
  PORTC = 0;
  PORTD = 0;
  PORTB = 1;

  LCMinit();

  ADCinit();

  SetLCMPosition(2,5);
  ShowChar('V');

  SREG |= (1 << 7);                        // прерывания разрешены

  while(1)
  {
      t = ((((ADCresult2 << 8) + ADCresult1) * k) >> 8) + b;
 
      temperatura = (unsigned char) t;

      SetLCMPosition(1,0);
      ShowChar(temperatura);
  }


}


// Инициализация АЦП
void ADCinit()
{

    ADMUX = (1 << 6);  //АЦП работает от Vcc, прием данных по A0

    ADCSRA = (1 << 7) | (1 << 6) | (1 << 3) | (1 << 2) | (1 << 1);


}


ISR (SIG_ADC)
{

    ADCresult1 = ADCL;
    ADCresult2 = ADCH;

    ADCSRA &= ~(1 << ADIF);
    ADCSRA |= (1 << 6);
}


Работает, но Proteus ругается. Это с WinAVR.

Вставляю включение/выключение прерывания

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

ADCSRA &= ~(1 << ADIE);
ADCSRA |= (1 << ADIE);


Перестаёт работать. :shock: :shock: :shock:

Если пытаюсь просто выводить символ на экран + делая инициализируя АЦП так:

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

// Инициализация АЦП
void ADCinit()
{

    ADMUX = (1 << 6);  //АЦП работает от Vcc, прием данных по A0

    ADCSRA = (1 << 7) | (1 << 2) | (1 << 1);


}


Proteus перестаёт ругаться. Только дописываю

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

ADCSRA = (1 << 7) | (1 << 6) | (1 << 3) | (1 << 2) | (1 << 1);


Опять проблемы.

Как я понимаю какие-то проблемы в прерывании.

Надеюсь кто-нибудь меня понял, я тут такого нагородил. :) :) :)

Есть ли в WinAVR аналог функции sprintf? А если я библиотеку <stdio.h> перенесу в из CVAVR в WinAVR заработает? :)

В общем я запутался, всё конец........
Кот-тоК
Открыл глаза
Сообщения: 42
Зарегистрирован: Чт окт 28, 2010 19:33:35

Re: Не могу насторить АЦП в ATmega

Сообщение Кот-тоК »

Так, вот конечный код в CVAVR.

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


#include <mega16.h>
#include <io.h>
#include <delay.h>
#include <stdio.h>



#define k 202
#define b -580

unsigned char temperatura;
char ss[15];

void ADCinit()
{


    ADMUX = (1 << 6);  //АЦП работает от Vcc, прием данных по A0
    ADCSRA = (1 << 7) | (1 << 2) | (1 << 1);


}


void main()
{

  unsigned long t;

  DDRC = 0xFF;
  DDRD = 0xFF;
  PORTC = 0;
  PORTD = 0;

  LCMinit(); // инициализация экрана, моя собственная функция

  ADCinit();  // инициализация АЦП

  SREG |= (1 << 7);    // прерывания разрешены

  while(1)
  {       
       ADCSRA |= (1 << 6);
       while(ADCSRA.6 == 1){};

       t = ADCW;
       t = ((ADCW * k) >> 8) + b;   

       temperatura = (unsigned char) t;

       sprintf(ss, "%u", temperatura);
   
       SetLCMPosition(1,0);
       ShowStr(ss);
  }
}


Заметьте, что всё работает с битом ADIE = 0. Это магия CVAVR :))
Данные разнятся с реальной температурой на 1 градус. Пока не знаю почему. Точность приборов :)) .
Странно, но Proteus продолжает симулировать не в реальном режиме.

Изображение

С WinAVR пока глухо :( :( :(
Очень жаль...........
stas00n
Вымогатель припоя
Сообщения: 557
Зарегистрирован: Пн мар 23, 2009 04:03:45

Re: Не могу насторить АЦП в ATmega

Сообщение stas00n »

Кот-тоК писал(а): Но странно, всё работает не смотря даже на то, что бит ADIE всегда 0
Proteus не ругается, всё работает зашибись.

Ничего странного, прерывание ведь не используется, преобразование запускается установкой бита ADSC, по окончании преобразования этот бит сбрасывается аппаратно, что приводит к выходу из цикла while (ADCSRA.6 == 1). Все нормально.
Кот-тоК писал(а):Заметьте, что всё работает с битом ADSC = 0. Это магия CVAVR :))

Опять никакой "магии" :)) ADSC ведь устанавливается перед циклом ожидания окончания преобразования, так?

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

       ADCSRA |= (1 << 6);
       while(ADCSRA.6 == 1){};

А то что в симуляторе его видно как 0, так это потому что он довольно быстро сбрасывается.
Кот-тоК писал(а): Proteus пишет всё тоже - в реальном времени симулировать не возможно.

А оно вообще надо? Может быть симуляция прерываний отнимает много ресурсов, не знаю, не пользуюсь протеусом.
Кот-тоК
Открыл глаза
Сообщения: 42
Зарегистрирован: Чт окт 28, 2010 19:33:35

Re: Не могу насторить АЦП в ATmega

Сообщение Кот-тоК »

Ну что же, ОГРОМНОЕ СПАСИБО всем, кто помогал!!!!!!

:beer: :beer: :beer: :beer: :beer: :beer:
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»