Страница 1 из 2

ATmega8 2 АЦП

Добавлено: Пн июл 30, 2012 17:53:53
shurikss123
Ребят помогите запустить на 8-ке АЦП 2-х каналов.

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

int main(void)
{
	USART_Init();

	ADCSRA=(1<<ADEN)|(1<<ADPS1)|(1<<ADPS0);

	ADMUX=(1<<REFS1)|(1<<REFS0)|(0<<MUX0)|(0<<MUX1)|(0<<MUX2)|(0<<MUX3);

	sei();
	PORTB = 0xff;

	while (1)
	{
		//tower_left
		USART_Transmit(device);
		USART_Transmit(ch);
		USART_Transmit(0x1);


		ADCSRA |= (1 << ADSC)|(1<<ADFR);    //Начинаем преобразование
		ADMUX = (1<<REFS1)|(1<<REFS0)|(0<<MUX0)|(0<<MUX1);
		while ((ADCSRA&_BV(ADIF))==0x00); //Ждем флага окончания преобразования

		USART_Transmit(ADCH);

		USART_Transmit(ADCL);
		_delay_ms(1000);

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

Re: ATmega8 2 АЦП

Добавлено: Пн июл 30, 2012 18:50:00
U235
Обычно сначала переключают канал, а потом запускают измерение.

Re: ATmega8 2 АЦП

Добавлено: Пн июл 30, 2012 19:09:14
shurikss123
U235 писал(а):Обычно сначала переключают канал, а потом запускают измерение.
я уже по всякому пробывал первый замер делат а потом тупо повторяет

Re: ATmega8 2 АЦП

Добавлено: Пн июл 30, 2012 19:13:37
ILYAUL
И ещё обычно , раз не работают с прерываниями , ручками сбрасывают флаг ADIF Сбрасывается он записью 1

Re: ATmega8 2 АЦП

Добавлено: Пн июл 30, 2012 19:21:14
s_black
shurikss123 писал(а):Ребят помогите запустить на 8-ке АЦП 2-х каналов.
Вот пример и для трёх каналов. СмотрИте исходник.

Re: ATmega8 2 АЦП

Добавлено: Пн июл 30, 2012 19:22:59
shurikss123
ILYAUL писал(а):И ещё обычно , раз не работают с прерываниями , ручками сбрасывают флаг ADIF Сбрасывается он записью 1
не то, в протеусе ругается на заблокированный бит?

Re: ATmega8 2 АЦП

Добавлено: Пн июл 30, 2012 19:29:41
shurikss123
s_black писал(а):
shurikss123 писал(а):Ребят помогите запустить на 8-ке АЦП 2-х каналов.
Вот пример и для трёх каналов. СмотрИте исходник.
в твоем случае 48 мега, в моем 8 мега, есть разница.

Re: ATmega8 2 АЦП

Добавлено: Пн июл 30, 2012 23:19:06
siamds
По Вашей просьбе написал код для двух каналов ADC для ATMega8. Чтобы не возиться с написанием кода программы, программа создана при помощи генератора кодов CV_AVR. Программа промоделирована в Proteus’e. Программа снабжена подробными комментариями. Файлы программы и рисунки генератора кодов во вложении.

Re: ATmega8 2 АЦП

Добавлено: Вт июл 31, 2012 06:11:44
shurikss123
siamds писал(а):По Вашей просьбе написал код для двух каналов ADC для ATMega8. Чтобы не возиться с написанием кода программы, программа создана при помощи генератора кодов CV_AVR. Программа промоделирована в Proteus’e. Программа снабжена подробными комментариями. Файлы программы и рисунки генератора кодов во вложении.
вечерком посмотрю

Re: ATmega8 2 АЦП

Добавлено: Вт июл 31, 2012 19:10:13
shurikss123
ниче не пойму не работает хоть убей

Re: ATmega8 2 АЦП

Добавлено: Вт июл 31, 2012 21:09:45
U235
Попробуйте так

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

int main(void)
{
   USART_Init();

   ADCSRA=(1<<ADPS1)|(1<<ADPS0);
   ADMUX=(1<<REFS1)|(1<<REFS0)|(0<<MUX0)|(0<<MUX1)|(0<<MUX2)|(0<<MUX3);

   sei();
   PORTB = 0xff;

   while (1)
   {
      //tower_left
      USART_Transmit(device);
      USART_Transmit(ch);
      USART_Transmit(0x1);


      ADCSRA |= (1 << ADSC);    //Начинаем преобразование
      while ((ADCSRA&_BV(ADIF))==0x00); //Ждем флага окончания преобразования
      ADMUX = (1<<REFS1)|(1<<REFS0)|(0<<MUX0)|(0<<MUX1);

      ADCSRA |= (1 << ADIF); 

      USART_Transmit(ADCL);
      USART_Transmit(ADCH);

      _delay_ms(1000);

   };
}

Re: ATmega8 2 АЦП

Добавлено: Вт июл 31, 2012 21:15:05
siamds
shurikss123 писал(а):ниче не пойму не работает хоть убей
Давайте разбираться почему не работает. Каким компилятором Вы пользуетесь, и какой симулятор установлен на Вашем компьютере? Программу скачали 11 наших коллег – обратиться к ним работает ли программа у них?

Re: ATmega8 2 АЦП

Добавлено: Вт июл 31, 2012 23:45:21
C@at
siamds пробовал в протеусе ваш проект ADC_Mega8.rar , у меня все работает :beer:

Re: ATmega8 2 АЦП

Добавлено: Ср авг 01, 2012 00:33:21
siamds
Уважаемый C@at!
Спасибо за сообщение. Благодаря Вам будет легче искать “глюки” в программе shurikss123.

Re: ATmega8 2 АЦП

Добавлено: Ср авг 01, 2012 00:40:01
C@at
Вот если найдется тут такой человек, который подскажет ему, что для поиска "глюка" нужно выложить полностью секретный проект, тогда это действительно поможет.....

Re: ATmega8 2 АЦП

Добавлено: Ср авг 01, 2012 11:14:42
Jack_A
C@at писал(а):Вот если найдется тут такой человек, который подскажет ему, что для поиска "глюка" нужно выложить полностью секретный проект, тогда это действительно поможет.....
Да ни в жисть, сопрут ! Копирайт, панимеш :))

Re: ATmega8 2 АЦП

Добавлено: Ср авг 01, 2012 13:27:53
C@at
Jack_A как вы узнали :shock: что все сопрут?
Уже все стырено в личное пользование :))) ...... и спрятано здесь.
Спасибо siamds за труд, весьма простой наглядный пример + коментарии!

Re: ATmega8 2 АЦП

Добавлено: Ср авг 01, 2012 16:15:01
Angmar
Для ICCAVR есть готовое решение. Несложно портировать в WinAVR, CodeVisionAVR etc.
Привожу сразу с функциями УАРТА, так как применяется отсылка строк из Флеша и РАМа. Проверял на ATMega8 и 32 (никакой разницы).

Главная функция в проекте для чтения АЦП и отправки по УАРТУ -
ADC_transmitValue(). Остаётся в функции main вписать её в нужном вместе. Ну и инициализауию АЦП и УАРТа - ADC_init() и uart0_init()
PS - В функции ADC_transmitValue() надо поставить необх. кол-во каналов.
Спойлер

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


//Controller:  ATmega32 (16MHz Crystal). Compiler:  ICCAVR 

#include <iom32v.h> 
#include <macros.h> 

#define ADC_ENABLE         ADCSRA |= (1<<ADEN) 
#define ADC_DISABLE         ADCSRA &= 0x7F 
#define ADC_START_CONVERSION    ADCSRA |= (1<<ADSC) 
#define TX_NEWLINE  {transmitByte(0x0d); transmitByte(0x0a);} 

void ADC_init(void); 
int ADC_read(void); 
float ADC_calculateTemp(int); 
unsigned char* updateTempDisplay(float); 
unsigned char* temporary(void); 
void ADC_transmitValue(void);

unsigned char receiveByte(void); 
void transmitByte(unsigned char); 
void transmitString_F(const unsigned char*); 
void transmitString(unsigned char*); 
unsigned char valueDisplay[]=":  .   volt"; 

float Vref = 5.00; // Напряжение на Vref АЦП

// Initialize the ADC ****************************************************** 
void ADC_init(void) 
{ 
 ADCSRA = 0x00; //disable adc 
 ADMUX = 0x40; //select adc input 0 
 ADCSRA = 0x86; 
} 
 
// Do a Analog to Digital Conversion ********************************************** 
int ADC_read(void) 
{ 
    char i; 
    int ADC_temp, ADCH_temp; 
    int ADC_var = 0; 
     
    ADC_ENABLE; 
     
    ADC_START_CONVERSION;    //первый раз вычитываем всякий мусор из АЦП
   
    while(!(ADCSRA & 0x10));     //Ждём, флага окончания преобразования. ADIF flag active 
    ADCSRA|=(1<<ADIF); 
         
    for(i=0;i<8;i++)             //Считывание 8 раз для усреднения и повышения точности (потом поделим на 8)
    { 
    ADC_START_CONVERSION; 
        while(!(ADCSRA & 0x10));    // wait for conversion done, ADIF flag active 
        ADCSRA|=(1<<ADIF); 
     
        ADC_temp = ADCL;            // read out ADCL register 
        ADCH_temp = ADCH;         // read out ADCH register         
    ADC_temp +=(ADCH_temp << 8); 
        ADC_var += ADC_temp;      // accumulate result (8 samples) for later averaging 
    } 
 
    ADC_var = ADC_var >> 3;     //усредняем выборку из 8 преобразований
    
    ADC_DISABLE; 
   
    return ADC_var; 
}

//To calculate Voltage ************************************************* 
 float ADC_calculateValue(int inputValue) 
 { 
    float actualValue; 
    actualValue=(inputValue * Vref/1024.0);   //calculates the voltage present 
    return actualValue; 
 } 
   
//To update the valueDisplay string based on the latest voltage read ************************ 
  unsigned char* updateDisplay(float actualValue) 
 {    
     
  int temp; 
  unsigned char c; 
  temp=(int)(actualValue*100.0);   //to include decimal point for display 
   
  if((actualValue*100.0 - temp) >= 0.5) temp=temp+1; 
   
  valueDisplay[5] = ((unsigned char)(temp%10)) | 0x30; 
  temp=temp/10; 
     valueDisplay[4] = ((unsigned char)(temp%10)) | 0x30; 
  temp=temp/10; 
  valueDisplay[2] = ((unsigned char)(temp%10)) | 0x30; 
  temp=temp/10; 
   
  return valueDisplay; 
        
} 
 
//to transmit the voltage values at 8 ADC channels ******************************* 
void ADC_transmitValue(void) 
{ 
  int value; 
  float value1; 
  unsigned char i; 
   
  
  for(i=0; i<8; i++) // вместо 8 устанавливаем необходимое кол-во или выбранные номера каналов АЦП !!!
  { 
    ADMUX &= 0xe0; 
    ADMUX |= i;   //ВЫБИРАЕМ КАНАЛ
    value = ADC_read();
    value1 = ADC_calculateValue(value); 
     
//following three functions are part of the UART routines, sending the 
//voltage values to serial port. UART must be initialized before 
//calling them 
 
    transmitString_F("   Channel ");    
    transmitByte(i | 0x30); 
    transmitString(updateDisplay(value1)); 
    TX_NEWLINE; 
  } 
} 
   

//******** FUNCTIONS FOR SERIAL COMMUNICATION USING UART ******* 
//Function to initialize UART ************************** 
//UART0 initialize  
// desired baud rate: 19200 
// actual: baud rate:19231 (0.2%)(at 16MHz crystal) 
// char size: 8 bit 
// parity: Disabled 
 
void uart0_init(void) 
{ 
 UCSRB = 0x00; //disable while setting baud rate 
 UCSRA = 0x00; 
 UCSRC = BIT(URSEL) | 0x06; 
 UBRRL = 0x33; //set baud rate lo 
 UBRRH = 0x00; //set baud rate hi 
 UCSRB = 0x98; 
} 
 
//Function to receive a single byte ********************** 
unsigned char receiveByte( void ) 
{ 
  unsigned char data, status; 
   
  while(!(UCSRA & (1<<RXC)));   // Wait for incomming data 
   
  status = UCSRA; 
  data = UDR; 
 
  return(data); 
}

//Function to transmit a single byte ************************* 
void transmitByte( unsigned char data ) 
{ 
  while ( !(UCSRA & (1<<UDRE)) ) 
    ;           //Wait for empty transmit buffer 
  UDR = data;         //Start transmition 
} 
 
//Function to transmit a string stored in Flash ***************** 
void transmitString_F(const unsigned char* string) 
{ 
    while (*string) 
  transmitByte(*string++); 
} 
 
//Function to transmit a string from RAM 
//*************************************************** 
void transmitString(unsigned char* string) 
{ 
    while (*string) 
  transmitByte(*string++); 
}



Re: ATmega8 2 АЦП

Добавлено: Ср авг 01, 2012 19:10:50
shurikss123
siamds писал(а):
shurikss123 писал(а):ниче не пойму не работает хоть убей
Давайте разбираться почему не работает. Каким компилятором Вы пользуетесь, и какой симулятор установлен на Вашем компьютере? Программу скачали 11 наших коллег – обратиться к ним работает ли программа у них?
gcc-avr 1:4.5.3-3
avr-libs 1:1.7.1-2
proteus не важно, я в железе пробывал, на двух atmega8, кстате на atmega168 завелось без проблем по даташиту.
вот исходник
https://code.google.com/p/sfag/source/b ... po=tank-tx

Re: ATmega8 2 АЦП

Добавлено: Ср авг 01, 2012 20:06:00
ILYAUL

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

ADCSRA |= 0x40;
- Ошибка