Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Подключения АЦП
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
AnKing
Задача: Собрать устройство которое будет выключать светодиод порта В при изменении освещения ниже допустимого уровня

Средства:
-Atmega8
-Фотодиод ФД265А
-LCD Для вывода резцльтата ацп на экран

Реализация:
Подключаю AVCC, AREF, длинную ногу фотодиода к +5V
AGND к GND;

PC0(ADC0) подключаю к короткой ноге фотодиода и через резистор 5КОм в GND

Код программы на С:
Код
#include <mega8.h>
#include <delay.h>
#include <stdlib.h>

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

// Declare your global variables here

char sstr[10];

interrupt [ADC_INT]  void  adc_isr(void)
{
PORTB = (1<<0);
lcd_gotoxy(0,1);
lcd_putsf("RABOTAET");
lcd_gotoxy(0,0);
lcd_putchar(ADCH);
//delay_ms(127);
//ADCSRA|=0x40;
#asm ("cli")
}

void __init_mk(void) {
DDRB=0xFF;
PORTB=0xFF;

ADCSRA=0x8F;

ADMUX=0;

#asm("sei")
}


void main(void)
{
lcd_init(16);

lcd_clear();

__init_mk();

ADCSRA|=0x40;

while (1)
      {
      PORTB = (1<<0);
      lcd_gotoxy(7,1);
      //lcd_putchar(rand());
      itoa(rand(),sstr);
      lcd_puts(sstr);
      lcd_gotoxy(13,1);
      lcd_putchar(sstr[2]);
      delay_ms(25);
      
ADCSRA|=0x40;
      PORTB = (0<<0);
      delay_ms(150);
      };
}

Прерывания повторяются нормально, но вот число выводимое на дисплей - константно и равно - 838(с каким-то странным префиксом - черный квадрат без двух точек внизу слева)

Что я сделал неправильно?
AHTOXA
Цитата(AnKing @ Feb 3 2008, 22:56) *
число выводимое на дисплей - константно и равно - 838(с каким-то странным префиксом - черный квадрат без двух точек внизу слева)
Что я сделал неправильно?


Видимо вот это:
Цитата(AnKing @ Feb 3 2008, 22:56) *
Код
lcd_gotoxy(0,0);
lcd_putchar(ADCH);


Не знаю, откуда там 838, но префикс в виде чёрного квадрата - это символ с кодом, равным ADCH. Чтобы из него получить число, надо использовать, например, ф-ю itoa().
Ну и желательно не заниматься этим в прерывании.
Nanobyte
Цитата(AnKing @ Feb 3 2008, 20:56) *
...PC0(ADC0) подключаю к короткой ноге фотодиода и через резистор 5КОм в GND...
Что я сделал неправильно?

А не мало ли 5 КОм? Лучше будет поставить 100 КОм. Кроме того, нужно убедиться, что длинная нога фотодиода - это катод, ибо встречалась мне и обратная маркировка. В случае, если вы будете мерять фото-ЭДС, тогда второй вывод ФД нужно соединить с GND, а резистор не нужен.
=GM=
Цитата(AnKing @ Feb 3 2008, 17:56) *
Прерывания повторяются нормально, но вот число выводимое на дисплей - константа и равно - 838(с каким-то странным префиксом - черный квадрат без двух точек внизу слева). Что я сделал неправильно?


1) В прерывании вы посылаете на печать байт ADCH=0х05 (lcd_putchar(ADCH)), хотя сначала надо бы прочитать байт по этому адресу, (неплохо также перевести его в милливольты или вольты, а то измеряемое напряжение будет в попугаях), затем преобразовать его в читаемые символы ASCII и уж затем выдавать его на дисплей.

2) Чтобы читать только старший байт ацп, надо установить бит ADLAR в регистре ADMUX для настройки на левую границу слова.

3) Не надо выполнять #asm ("cli") в конце прерывания, оно всё равно разрешается аппаратно.
AnKing
Зашиваю этот код в контроллер и он виснет, ADC0 вообще отпаял от схемы

Код
#include <mega8.h>
#include <delay.h>
#include <stdlib.h>

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

// Declare your global variables here

char sstr[10];

interrupt [ADC_INT]  void  adc_isr(void)
{
lcd_gotoxy(0,1);
lcd_putsf("RABOTAET");
lcd_gotoxy(0,0);
//ADCL = 0xFF;
lcd_gotoxy(11,0);
itoa(ADCL,sstr);
lcd_puts(sstr);

lcd_gotoxy(9,1);

ADCSRA|=0x40;        ///если закомментировать эту строку
//#asm ("cli")            //на экран выводится   255
}


void __init_mk(void) {

ADCSRA=0x8F;

ADMUX=0;
#asm("sei")
}


void main(void)
{
lcd_init(16);

lcd_clear();

__init_mk();

ADCSRA|=0x40;

while (1)
      {
      PORTB = (1<<0);
      
      lcd_gotoxy(0,0);
      itoa(ADCL,sstr);
      lcd_puts(sstr);        //выводит 255
      
      lcd_gotoxy(8,0);
      itoa(ADCH,sstr);
      lcd_puts(sstr);       //выводит 3
      
      
      lcd_gotoxy(9,1);
      //lcd_putchar(rand());
      itoa(rand(),sstr);
      lcd_puts(sstr);
      lcd_gotoxy(15,1);
      lcd_putchar(sstr[2]);
      delay_ms(25);
      
      ADCSRA|=0x40;
      PORTB = (0<<0);
      delay_ms(150);
      };
}


Подключаю ADC0 к GND и к +5V ничего не помогает, на дисплее всеравно висяк.
=GM=
Цитата(AnKing @ Feb 4 2008, 15:30) *
Зашиваю этот код в контроллер и он виснет, ADC0 вообще отпаял от схемы. Подключаю ADC0 к GND и к +5V ничего не помогает, на дисплее все равно висяк

Ну, а зачем вы запускаете преобразование и в прерывании и в фоне? Думаете, быстрее получится? Ничего подобного, прерывание еще не завершилось, а вы его сбрасываете в фоне. Добейтесь сначала результата при работе по ожиданию (в фоне), на прерывания потом перейдёте.
AnKing
Работает только в фоне. На дисплей выводит:

lcd_gotoxy(0,0);
itoa(ADCL,sstr);
lcd_puts(sstr); //выводит 255

lcd_gotoxy(8,0);
itoa(ADCH,sstr);
lcd_puts(sstr); //выводит 3

и 255 то, что в прерывании.

Вне зависимости от ножки ADC0(заземлена она или подключена к питанию)
=GM=
Цитата(AnKing @ Feb 4 2008, 18:52) *
Работает только в фоне. На дисплей выводит:
lcd_gotoxy(0,0);
itoa(ADCL,sstr);
lcd_puts(sstr); //выводит 255
lcd_gotoxy(8,0);
itoa(ADCH,sstr);
lcd_puts(sstr); //выводит 3
и 255 то, что в прерывании.
Вне зависимости от ножки ADC0(заземлена она или подключена к питанию)

Ну вот, уже есть результат, какой-никакой. Результат означает вот что. Ваш код на выходе ацп равен 11 1111 1111. Как бы переполнение. Объясню почему. Командой ADMUX=0 вы выключили внутреннее опорное напряжение, поэтому все входные напряжения, превышающие 0 будут вызывать переполнение. Надо бы вам включить внутреннюю опору битами REFS10=11 в регистре ADMUX, тогда ацп начнёт выполнять нормальное преобразование.
AnKing
Оказалось AREF запитал не к плюсу питания а к GND. Теперь все работает, правда не так как хотелось бы.
lcd_gotoxy(0,0);
itoa(ADCL,sstr);
lcd_puts(sstr);

lcd_gotoxy(8,0);
itoa(ADCH,sstr);
lcd_puts(sstr);

Этот код рисует 2 числа - одно от 0 до 999 а второе (0-3) как бы обьеденить их воедино?
=GM=
Цитата(AnKing @ Feb 4 2008, 19:33) *
Так я же запитал ногу AREF к питанию МК, разве этого не достаточно? И как соеденить эти две цифры воедино? какую битовую операцию применить?

Недостаточно, надо чтобы биты REFS10=01 (внешняя опора)

voltage=((adch<<8)+adcl)*step;

где step=Uref/1024, лучше в милливольтах
AHTOXA
Цитата(AnKing @ Feb 5 2008, 00:33) *
Этот код рисует 2 числа - одно от 0 до 999 а второе (0-3) как бы обьеденить их воедино?


Код
itoa(ADC,sstr);
lcd_puts(sstr);
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.