АЦП у Мега8

Обсуждаем контроллеры компании Atmel.
Ответить
Грызет канифоль
Сообщения: 261
Зарегистрирован: Ср авг 01, 2012 10:45:42

Сообщение kk042fjv »

Добрый день!
Занимаюсь самоизучение микроконтроллеров.
Как в данный код параллельно порту РС0 прописать второй код РС1 или РС2

ACSR=0x80;
SFIOR=0x00;

ADMUX=0;
ADCSRA=0x85;

ADCSRA |= 0x40;
data = ADCW;
L = (float) data*0.01953125;
Реклама
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

что такое "параллельно"? может работать только один вход АЦП.
ADMUX = (1<<MUX0); - вход ADC1 (PC1)
или ADMUX = (1<<MUX1); - вход ADC2 (PC2)
или ADMUX = (1<<MUX1) | (1<<MUX0); - вход ADC3 (PC3)
и т.д.
Реклама
Грызет канифоль
Сообщения: 261
Зарегистрирован: Ср авг 01, 2012 10:45:42

Сообщение kk042fjv »

А как тогда к моему вольтметру подключить второй вольтметр?
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

не понятен вопрос.
если нужно измерять напряжение с нескольких входов одного контроллера, то по очереди. выбрали вход, дождались преобразования, считали данные, переключили на другой вход, дождались преобразования, и т.д.
Реклама
Эиком - электронные компоненты и радиодетали
Грызет канифоль
Сообщения: 261
Зарегистрирован: Ср авг 01, 2012 10:45:42

Сообщение kk042fjv »

Работу понял, подскажите тогда где это вводится? Вот мы считали с одного порта, преобразовали, вывели. А как теперь на другой порт переключится?

ADMUX=0; //подключили порт
ADCSRA=0x85; //настроили АЦП

// LCD module initialization
lcd_init(16); //подключили ЖК
lcd_clear(); //стерли

while (1)
{
delay_ms(20);
ADCSRA |= 0x40;
data = ADCW;
L = (float) data*0.01953125;
sprintf(string, "Rashod %1.1f ",L);
lcd_gotoxy(0,0);
lcd_puts(string)
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

kk042fjv писал(а):А как теперь на другой порт переключится?
ADMUX=1 (нужное число см. в таблице в даташите)
Реклама
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

как-то так

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

ADCSRA=0x85; //настроили АЦП
// LCD module initialization
lcd_init(16); //подключили ЖК
lcd_clear(); //стерли
while (1)
{ 
static unsigned char port=0; // переменная для мультиплексора порта
ADMUX=port; //подключили порт
if(++port > 7) port=0; // подготовили переменную для следующего порта (в данном случае все от 0 до 7)
delay_ms(20);
ADCSRA |= 0x40; // запустили преобразование
while((ADCSRA&(1<<ADIF)) == 0); // ждем окончания преобразования
ADCSRA |= (1<<ADIF); // сбросили флаг готовности
data = ADCW; 
L = (float) data*0.01953125;
sprintf(string, "Rashod %1.1f ",L);
lcd_gotoxy(0,0);
lcd_puts(string)
YS
Друг Кота
Аватара пользователя
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05

Сообщение YS »

Помимо всего прочего, float в контроллерах без FPU - ОЧЕНЬ плохо. Это дико раздувает код и ужасно замедляет его, ибо в AVR используется программная эмуляция. Причем в стандартном варианте еще и написанная на C.

Используйте фиксированную точку. А лучше обойдитесь целочисленными вычислениями.

sprintf - тоже не айс, ибо жутко ресурсоемка.

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

float L;

...

L = (float) data*0.01953125;
- плохо. К тому же, используется ADCW, т.е., 10 бит, потому здесь еще и коэффициент неправильный. Правильный - 5/1024=0.00488.

Надо так:

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

uint16_t L;

...

L=(5*ADCW)/1024;
Получится результат с точностью до вольт. Если надо до десятых, умножаем на 10:

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

uint16_t L;

...

L=(50*ADCW)/1024;
Как-то так. Учитываем множитель и следим за переполнениями. А float в AVR без совсем суровой на то необходимости (которой может быть, например, решение СЛАУ) - это ардуино-стайл.
Разница между теорией и практикой на практике гораздо больше, чем в теории.
Контактная информация:
Грызет канифоль
Сообщения: 261
Зарегистрирован: Ср авг 01, 2012 10:45:42

Сообщение kk042fjv »

Спасибо за ответ.
Буду теперь знать про float и sprintf, а что коэффициент неправильный это я экспериментировал как он считает.
Подскажите, у меня программа ругается на ADIF ведать я может вначале что то не ввел и не понимает надпись while((ADCSRA&(1<<ADIF) == 0);

пишу CodeVisionAVR
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

а что именно пишет? какая версия?
#include <mega8.h> - есть?
в крайнем случае можно написать
while((ADCSRA&0x10) == 0);

ps. у Вас скобки не хватает: while((ADCSRA&(1<<ADIF)) == 0);
Грызет канифоль
Сообщения: 261
Зарегистрирован: Ср авг 01, 2012 10:45:42

Сообщение kk042fjv »

CodeVisionAVR 1.25.9
Что то я в этом коду запутался, лучше сначала начать
Может есть у кого нибудь какой-нибудь полный код для примера АЦП с использованием нескольких входов
Грызет канифоль
Сообщения: 261
Зарегистрирован: Ср авг 01, 2012 10:45:42

Сообщение kk042fjv »

Скобку видать когда копировал потерял, я после Вашего сообщения еще раз перепроверял, так же

пишет (invalid expression)

А вот на Ваш второй вариант while((ADCSRA&0x10) == 0); работает, но тогда на ADCSRA |= (1<<ADIF); ругается
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

Project -> Configure -> C Compiler ->Code Generation поставить галочку Include I/O Registers Bits Definitions
или заменить на аналогичное
ADCSRA |= 0x10;
Грызет канифоль
Сообщения: 261
Зарегистрирован: Ср авг 01, 2012 10:45:42

Сообщение kk042fjv »

Добрый день!
Вроде разобрался я как работать с АЦП.
Теперь возник вопрос как вынести показание на разные строчки?
т.е. у меня цифры просто меняются.

ADCSRA=0x85;

// LCD module initialization
lcd_init(20);
lcd_clear();


while (1)
{
static unsigned char port=0;
ADMUX=port;
if(++port > 1) port=0;
delay_ms(1000);
ADCSRA |= 0x40;
while((ADCSRA&0x10) == 0);
ADCSRA |= 0x10;
data = ADCW;
V = (float) data*0.004887585;
sprintf(string, " %1.2f ",V);
lcd_gotoxy(5,0);
lcd_puts(string);
ADCSRA |= 0x10;

};
}

прикреплен файл в протеусе.
Вложения
АЦП.rar
(18.44 КБ) 173 скачивания
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

Вроде как в lcd_gotoxy второй параметр это строка, так вот в зависимости от номера порта и поставить или (5,0) или (5,1), может даже прямо написать (5,port), если тип данных позволяет.
Грызет канифоль
Сообщения: 261
Зарегистрирован: Ср авг 01, 2012 10:45:42

Сообщение kk042fjv »

Я ставил тогда две строчки одновременно меняются.
Мне надо что бы одна строчка показывала с одного порта, другая с другого
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

Не могут две строчки одновременно меняться, если только эти входа АЦП между собой не закорочены или если одно и тоже значение просто выводится по очереди то в одну строку, то в другую (lcd_gotoxy(5,0);lcd_puts(string);lcd_gotoxy(5,1);lcd_puts(string); )
Грызет канифоль
Сообщения: 261
Зарегистрирован: Ср авг 01, 2012 10:45:42

Сообщение kk042fjv »

вот как Вы второй вариант показали у меня так же получается
Вымогатель припоя
Сообщения: 630
Зарегистрирован: Пн июн 14, 2010 13:07:29
Откуда: Жуковский

Сообщение a_skr »

не знаю, что там у Вас не получается...
у меня, правда sprintf не форматирует float. вот на целых числах:

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

#include <mega8.h>
#include <stdio.h>
#include <alcd.h>

void main(void)
{
  unsigned short data;
  char string[17];

  lcd_init(16);
  lcd_clear(); 
  ADCSRA=0x85;

  while (1)
  { 
    static unsigned char port=0;
    ADMUX=port;
    ADCSRA |= 0x40;
    while((ADCSRA&0x10) == 0);
    ADCSRA |= 0x10;
    data = ADCW*50/1023; 
    sprintf(string, "%d.%d", data/10, data%10);
    lcd_gotoxy(5,port);
    lcd_puts(string); 
    if(++port > 1) port=0;
  }

}
Изображение
Вложения
1.JPG
(87.36 КБ) 1105 скачиваний
Друг Кота
Аватара пользователя
Сообщения: 3872
Зарегистрирован: Пт янв 29, 2010 10:27:40
Откуда: Москва

Сообщение Engineer_Keen »

kk042fjv, ну так я ж написал, что если так сделать, то это не правильно
я писал(а): одно и тоже значение просто выводится по очереди то в одну строку, то в другую
:facepalm: Вы сами то пройдитесь по своему коду строчка за строчкой и сделайте как бы контроллер это сделал (пишите на бумажке промежуточные результаты). И что при этом получится?
a_skr вон подставил port прямо в функцию позиционирования на экране, как я и сказал, и все работает.
Ответить

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