реклама на сайте
подробности

 
 
> Программирование АЦП на atmega16L-16AI, Помогите разобраться с считыванием данных с АЦП
abitwise
сообщение Apr 7 2011, 06:26
Сообщение #1





Группа: Участник
Сообщений: 14
Регистрация: 1-04-11
Пользователь №: 64 056



Доброго времени суток.
Поскольку я не профессиональный программист и до этого момента с микроконтроллерами общался постольку поскольку, то обращаюсь к знающим и опытным людям с просьбой помочь разобраться с поставленной передо мной задачей.

Исходные данные:

Есть - мк Atmega16L-16AI (TQFP)
- два вентилятора Jamicon (JF0825B1H), Evercool (EC6010H12B)
- два дачитка температуры типа NTC

Задача: необходимо считывать информацию с датчиков и выдавать на вентиляторы напряжения, соответствующие температурным диапазонам.
Так как я в этом деле новичок, то разбил задачу на три.
1) Научиться выдавать ШИМ на вентиляторы. С этим я худо бедно разобрался!

Вот код
Код
  Chip type           : ATmega16L
Program type        : Application
Clock frequency     : 8,00000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 256
*****************************************************/


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

// Timer 1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
OCR1A=0x00;
OCR1B=0x00;
TCNT1L=0x00;  
PORTD=0b00110000;
}

//Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
   PORTD=0b00110000;

}

// Timer 1 output compare B interrupt service routine
interrupt [TIM1_COMPB] void timer1_compb_isr(void)

{
  PORTD=0b00110000;
    
}

void main(void)
{


// Input/Output Ports initialization
// Port A initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTA=0x00;
DDRA=0x00;

// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=Out Func4=Out Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=0 State4=0 State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x30;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x00;
TCNT0=0x00;
OCR0=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 8192,000 kHz
// Mode: Fast PWM top=00FFh
// OC1A output: Non-Inv.
// OC1B output: Non-Inv.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: On
TCCR1A=0xA1;
TCCR1B=0x09;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// INT2: Off
MCUCR=0x00;
MCUCSR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x1C;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// ADC initialization
// ADC Clock frequency: 64,000 kHz
// ADC Voltage Reference: AREF pin
// ADC Auto Trigger Source: Timer1 Overflow
// Only the 8 most significant bits of
// the AD conversion result are used
//ADMUX=0b00000000;
//ADCSRA=0xF7;
//SFIOR&=0x1F;
//SFIOR|=0xC0;
SPCR=0x40;
SPSR=0x01;

#asm("sei")

while (1)
{
   OCR1B=100;
   OCR1A=100;
};
}


По части теории вопросов у меня пока что нет. Перед решением этой задачи были проведены расчёты и получены соответствующие значения регистров сравнения таймера/счётчика1, соответствующих температурным диапазонам. Также согласно формуле из даташита на атмегу получено число ADC.
Вот эти значения (приведу только один диапазон в целях экономии времени):

температура, С измерительное напряжение, В ADC OCR1A OCR1B
25 1.196 299 0 0
26 1.159 290 0 0
27 1.123 281 0 0
28 1.087 272 0 0
29 1.053 263 0 0
30 1.020 255 0 0

и т. д.
Со второй задачей справиться не получается. Заключается она в том, чтобы научиться работать с АЦП.
А именно как правильно считывать информацию из АЦП, где и какие прерывание нужны в данной задаче? То есть я хочу понять структуру кода на Си, которая позволяет это делать и как такую структуру писать.
Дело в том, что я пользуюсь CodeVisionAvr, который генерит код, если использовать Wizard. Это на мой взгляд удобно, но только в том, случае если есть полное понимание сгенеренного кода. У меня такого понимания нету.
Я пытался самостоятельно решить эту проблему и протестировать полученный результат в Протеус, как в решении первой задачи, но ничего не вышло
Вот код (всё тоже самое только с добавлением сгенеренного кода для АЦП):
Код


1-   #define ADC_VREF_TYPE 0x04                                
2-   // Read the 8 low significant bits
3-   // of the AD conversion result
4-   unsigned char read_adc(unsigned char adc_input)
5-   {
6-    ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);  
7-    Delay needed for the stabilization of the ADC input voltage
8-    delay_us(10);
9-    // Start the AD conversion
10-  ADCSRA=0b11100110;
11-  // Wait for the AD conversion to complete
12-  while ((ADCSRA & 0x40)==0);
13-  ADCSRA|=0x10;
14-  return ADCL;
15-  }





16-   // ADC interrupt service routine
17-   interrupt [ADC_INT] void adc_isr(void)
18-   {
19-   unsigned char adc_data_l;
20-   // Read the 8 low significant bits
21-   // of the AD conversion result
22-   adc_data_l = ADCL;

23-   if(adc_data_l==0xFF)
24-     {
25-       OCR1A = 255 - adc_data_l;
26-       OCR1B = 255 - adc_data_l;
27-     }
28-   else
29-     {
30-      OCR1A = adc_data_l;
31-      OCR1B = adc_data_l;
32-      };
33-   }


Хотелось бы узнать от опытных людей, для чего необходимо и что означают 1 и 6 строчки кода, а также 12 и 13.
Далее хотелось бы понять правильно ли я сделал, что в процедуре прерывания АЦП написал последовательность действий по присвоению значений регистрам сравнения ?

3) Третья задача пока вообще не рассматриволась. Заключается она в передаче данных из АЦП в процедуру сравнения полученного из АЦП числа.
У меня процедура сравнения выглядит следующим образом:
Код
int range[9]={299, 255, 217, 184, 132, 112, 95, 81};

if (range[0] <= adc_data_l)
  {
   OCR1AL=0;
   OCR1BL=0;
  };
if (range[1] <= adc_data_l)
  {
   OCR1AL=0;
   OCR1BL=0;
  };
if (range[2] <= adc_data_l < range[1])  
  {
   OCR1AL=128;
   OCR1BL=85;
  };
if (range[3] <= adc_data_l< range[2])  
  {
   OCR1AL=149;
   OCR1BL=96;
  };    
if (range[4] <= adc_data_l < range[3])  
  {
   OCR1AL=170;
   OCR1BL=106;
  };    
if (range[5] <= adc_data_l < range[4])  
  {
   OCR1AL=191;
   OCR1BL=138;
  };
if (range[6] <= adc_data_l < range[5])  
  {
   OCR1AL=213;
   OCR1BL=149;
  };  
if (range[7] <= adc_data_l < range[6])  
  {
   OCR1AL=234;
   OCR1BL=170;
  };
if (range[8] <= adc_data_l < range[7])  
  {
   OCR1AL=255;
   OCR1BL=255;
  };

Массив из значений регистров сравнения ввёл для удобства. Хотя может быть оно и сомнительное.
В какой части кода необходимо писать эту процедуру ? В бесконечном цикле while(1){}? Или в прерываниях? Поскольку переменная adc_data_l объявлена внутри функции, то использовать её как глобальную переменную нельзя. Как решается эта проблема?. То есть, допустим я прочитал АЦП и записал число в эту переменную, что нужно сделать чтобы можно было пользоваться этой переменной в процедуре сравнения?

Заранее благодарю за помощь! Если на форуме или в интернете уже есть идентичные темы, в которых предложены решения данных проблем, то прошу поделиться ссылкой. Я обыскался в инете на эту тему, но не нашёл ничего, чтобы мне объяснило или подсказало как решать и что делать.
Надеюсь на вашу помощь!
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
abitwise
сообщение Apr 11 2011, 12:09
Сообщение #2





Группа: Участник
Сообщений: 14
Регистрация: 1-04-11
Пользователь №: 64 056



Спасибо за уточнения. Эту часть материала я усвоил.
С учётом перечисленных замечаний, код получился такой

Код
/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.5 Professional
Automatic Program Generator
© Copyright 1998-2007 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date    : 03.04.2011
Author  : F4CG                            
Company : F4CG                            
Comments:


Chip type           : ATmega16L
Program type        : Application
Clock frequency     : 8,00000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 256
*****************************************************/


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


interrupt [TIM1_OVF] void timer1_ovf_isr(void) // Прерывание по переполнению Т/C1
{
    OCR1A=0x00;
    OCR1B=0x00;
// TCNT1L=0x00;  
// PORTD=0b00110000;
}


interrupt [TIM1_COMPA] void timer1_compa_isr(void) // Прерывание по совпадению события А
{
   PORTD=0b00100000;
}

interrupt [TIM1_COMPB] void timer1_compb_isr(void) // Прерывания по совпадению события Б
{
   PORTD=0b00010000;
}



#define ADC_VREF_TYPE 0x20                      // Aref pin, выравнивание влево


unsigned int read_adc(unsigned char adc_input) // Считывание 8 СЗР
                                                // преобразования АЦП
{                                              
  ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);    
  delay_us(10);                                 // Задержка для стабилизации входного напряжения АЦП
  ADCSRA|=0b11010111;                           // Начало АЦП, сброс флага прерывания
  while ((ADCSRA & 0x10)==0);                   // Ожидание завершения преобразования
  return ADCH;                                  // Возвращение 8 СЗР
}


                    
void main(void)
{
int temp_range[9] = {299, 255, 217, 184, 156, 132, 112, 95, 81};
  
PORTA=0x30; // Инициализация порта А  
DDRA=0x00;  // РА4, РА5 - входы с подключенным резистором

PORTB=0x00; // Инициализация порта Б
DDRB=0x00;

PORTC=0x00; // Инициализация порта С
DDRC=0x00;

PORTD=0x00; // Инициализация порта Д  
DDRD=0x30;  // PD4, PD5 выходы с низким логическим уровнем

TCCR0=0x00; // Инициализация Т/C0
TCNT0=0x00;
OCR0=0x00;


TCCR1A=0xA1; // Инициализация T/C1
TCCR1B=0x0B; //
ICR1H=0x00;  // Тактирование системное
ICR1L=0x00;  // Частота: 8000,000 kHz
             // Режим: Fast PWM top=00FFh
             // OC1A : не инвертирующий
             // OC1B : не инвертирующий
            
ASSR=0x00;   // Инициализация  Т/C2
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
              
MCUCR=0x00;
MCUCSR=0x00;

TIMSK=0x1C;  // Инициализация прерываний таймера счётчика

ACSR=0x80;   // Аналоговый компаратор выключен
SFIOR=0x00;  


ADMUX=0b00000000;    
ADCSRA=0b00000000;    
                    

SPCR=0x40;   // Инициализация SPI
SPSR=0x01;
#asm("sei")  // Разрешение прерываний

for (;;)    
{
   unsigned int adc_data_l;
  
   TCNT1H=0x00; //  Обнуление Т/С1
   TCNT1L=0x00;
  
   OCR1AH=0x00; // Обнуление регистров сравнения
   OCR1AL=0x00;
   OCR1BH=0x00;
   OCR1BL=0x00;

   adc_data_l=0; // Обнуление переменной                    
  
   adc_data_l=read_adc(5); // Запись данных из АЦП с PA5
  
   if(temp_range[0] <= adc_data_l)  // Процедура сравнения значения АЦП с
     {                              // температурными диапазонами и
      OCR1A=0;                      // выдача ШИМ на вентилятор
     }
   else if(temp_range[1] <= adc_data_l)
     {
      OCR1A=0;
     }
   else if((temp_range[2] <= adc_data_l) && (adc_data_l < temp_range[1]))
     {
      OCR1A=128;
     }
   else if((temp_range[3] <= adc_data_l) && (adc_data_l < temp_range[2]))
     {
      OCR1A=149;
     }        
   else if((temp_range[4] <= adc_data_l) && (adc_data_l < temp_range[3]))
     {
      OCR1A=170;
     }
   else if((temp_range[5] <= adc_data_l) && (adc_data_l < temp_range[4]))
     {
      OCR1A=191;
     }
   else if((temp_range[6] <= adc_data_l) && (adc_data_l < temp_range[5]))  
     {
      OCR1A=213;
     }
   else if((temp_range[7] <= adc_data_l) && (adc_data_l < temp_range[6]))  
     {
      OCR1A=234;
     }
   else if((temp_range[8] <= adc_data_l) && (adc_data_l < temp_range[7]))  
     {
      OCR1A=255;
     }
   else if(adc_data_l < temp_range[8])
     {
      OCR1A=255;
     }  
  
   adc_data_l=read_adc(4); // Запись данных АЦП с PA4

   if(temp_range[0] <= adc_data_l)  // Процедура сравнения значения АЦП с
     {                              // температурными диапазонами и
      OCR1B=0;                      // выдача ШИМ на вентилятор
     }
   else if(temp_range[1] <= adc_data_l)
     {
      OCR1B=0;
     }
   else if((temp_range[2] <= adc_data_l) && (adc_data_l < temp_range[1]))
     {
      OCR1B=128;
     }
   else if((temp_range[3] <= adc_data_l) && (adc_data_l < temp_range[2]))
     {
      OCR1B=149;
     }        
   else if((temp_range[4] <= adc_data_l) && (adc_data_l< temp_range[3]))
     {
      OCR1B=170;
     }
   else if((temp_range[5] <= adc_data_l) && (adc_data_l < temp_range[4]))
     {
      OCR1B=191;
     }
   else if((temp_range[6] <= adc_data_l) && (adc_data_l < temp_range[5]))  
     {
      OCR1B=213;
     }
   else if((temp_range[7] <= adc_data_l) && (adc_data_l < temp_range[6]))  
     {
      OCR1B=234;
     }
   else if((temp_range[8] <= adc_data_l) && (adc_data_l < temp_range[7]))  
     {
      OCR1B=255;
     }                
   else if(adc_data_l < temp_range[8])
     {
      OCR1B=255;
     }  
};
}


С типами данных у функции read_adc, массива temp_range и переменной adc_data_l ничего не напутал ? Всё верно ?
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- abitwise   Программирование АЦП на atmega16L-16AI   Apr 7 2011, 06:26
- - Палыч   Цитата(abitwise @ Apr 7 2011, 10:26) Хоте...   Apr 7 2011, 07:06
- - abitwise   Спасибо за ответ. Если я вас правильно понял, то ...   Apr 7 2011, 09:19
|- - Палыч   Цитата(abitwise @ Apr 7 2011, 13:19) Если...   Apr 7 2011, 09:50
- - abitwise   С каждым вашим ответом, ситуация в голове проясняе...   Apr 7 2011, 10:51
|- - Палыч   Цитата(abitwise @ Apr 7 2011, 14:51) биты...   Apr 7 2011, 14:42
- - abitwise   Ясно! Уже учёл. Спасибо! Вот код, которы...   Apr 7 2011, 17:37
|- - Палыч   Проверку на попадание в диапазон Вы записали в вид...   Apr 8 2011, 04:04
|- - Xenia   Цитата(abitwise @ Apr 7 2011, 21:37) По п...   Apr 9 2011, 20:29
- - XVR   Цепочка из if'ов - это жесть. Для кого в С ц...   Apr 8 2011, 08:56
- - abitwise   Можете предложить другой вариант решения ? Цепочка...   Apr 8 2011, 09:01
|- - Палыч   Цитата(abitwise @ Apr 8 2011, 13:01) Цепо...   Apr 8 2011, 09:34
|- - Палыч   Ещё обратите внимание, что Ваша программа "за...   Apr 8 2011, 11:21
- - abitwise   Спасибо. Уже обратил) Буду пробовать прошивать......   Apr 8 2011, 11:42
- - abitwise   Прошил атмегу. Но программа по заданному алгоритму...   Apr 9 2011, 18:36
- - нечитатель   "Высокая точность не нужна" = "инте...   Apr 9 2011, 21:36
- - abitwise   Именно так. Достаточно битов регистра ADCL. Xenia...   Apr 10 2011, 12:00
|- - Палыч   Цитата(abitwise @ Apr 10 2011, 16:00) Мне...   Apr 11 2011, 08:06
|- - Xenia   Цитата(abitwise @ Apr 10 2011, 16:00) Мне...   Apr 11 2011, 09:17
- - нечитатель   "Участники форума обязаны: ... 2.1в высказыва...   Apr 11 2011, 06:09
- - abitwise   Нашёл решение данной проблемы. В даташите написан...   Apr 11 2011, 09:19
|- - Палыч   Цитата(abitwise @ Apr 11 2011, 13:19) Буд...   Apr 11 2011, 09:55
|- - Xenia   Цитата(abitwise @ Apr 11 2011, 13:19) Наш...   Apr 11 2011, 10:28
- - SysRq   Цитата(abitwise @ Apr 11 2011, 13:19) Код...   Apr 11 2011, 09:37
- - abitwise   Интересно. Я думал, что этот бит, совместно с ком...   Apr 11 2011, 09:56
|- - Палыч   Цитата(abitwise @ Apr 11 2011, 13:56) Инт...   Apr 11 2011, 10:02
- - abitwise   Не забыл. Код#define ADC_VREF_TYPE 0x20 и ADMUX=ad...   Apr 11 2011, 10:36
|- - Палыч   Цитата(abitwise @ Apr 11 2011, 14:36) Над...   Apr 11 2011, 11:36
- - SysRq   Цитата(abitwise @ Apr 11 2011, 13:56) У м...   Apr 11 2011, 11:45
|- - Палыч   Цитата(abitwise @ Apr 11 2011, 16:09) С т...   Apr 11 2011, 12:24
- - abitwise   1. Мне нужно 8 разрядов. Насколько я понял, выйгр...   Apr 11 2011, 12:37
|- - Палыч   Цитата(abitwise @ Apr 11 2011, 16:37) 1. ...   Apr 11 2011, 12:59
- - abitwise   Ясно. То есть, чтобы не было этого конфликта нужно...   Apr 11 2011, 13:07
- - Палыч   Цитата(abitwise @ Apr 11 2011, 17:07) нуж...   Apr 11 2011, 13:15


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 10:22
Рейтинг@Mail.ru


Страница сгенерированна за 0.01449 секунд с 7
ELECTRONIX ©2004-2016