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

 
 
 
Reply to this topicStart new topic
> Подключения АЦП, Глючит и ничего не показывает
AnKing
сообщение Feb 3 2008, 17:56
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 2-02-08
Пользователь №: 34 686



Задача: Собрать устройство которое будет выключать светодиод порта В при изменении освещения ниже допустимого уровня

Средства:
-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(с каким-то странным префиксом - черный квадрат без двух точек внизу слева)

Что я сделал неправильно?
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 3 2008, 19:49
Сообщение #2


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



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


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


Не знаю, откуда там 838, но префикс в виде чёрного квадрата - это символ с кодом, равным ADCH. Чтобы из него получить число, надо использовать, например, ф-ю itoa().
Ну и желательно не заниматься этим в прерывании.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Nanobyte
сообщение Feb 3 2008, 22:48
Сообщение #3


За битами по регистрам гоняюсь
***

Группа: Свой
Сообщений: 457
Регистрация: 24-04-06
Из: Таганрог
Пользователь №: 16 446



Цитата(AnKing @ Feb 3 2008, 20:56) *
...PC0(ADC0) подключаю к короткой ноге фотодиода и через резистор 5КОм в GND...
Что я сделал неправильно?

А не мало ли 5 КОм? Лучше будет поставить 100 КОм. Кроме того, нужно убедиться, что длинная нога фотодиода - это катод, ибо встречалась мне и обратная маркировка. В случае, если вы будете мерять фото-ЭДС, тогда второй вывод ФД нужно соединить с GND, а резистор не нужен.


--------------------
Курсор влево, курсор вправо - считается хакерством. FORMAT C: производится без предупреждения
Go to the top of the page
 
+Quote Post
=GM=
сообщение Feb 3 2008, 23:20
Сообщение #4


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



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


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

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

3) Не надо выполнять #asm ("cli") в конце прерывания, оно всё равно разрешается аппаратно.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
AnKing
сообщение Feb 4 2008, 15:30
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 2-02-08
Пользователь №: 34 686



Зашиваю этот код в контроллер и он виснет, 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 ничего не помогает, на дисплее всеравно висяк.
Go to the top of the page
 
+Quote Post
=GM=
сообщение Feb 4 2008, 17:00
Сообщение #6


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



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

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


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
AnKing
сообщение Feb 4 2008, 18:52
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 2-02-08
Пользователь №: 34 686



Работает только в фоне. На дисплей выводит:

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

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

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

Вне зависимости от ножки ADC0(заземлена она или подключена к питанию)
Go to the top of the page
 
+Quote Post
=GM=
сообщение Feb 4 2008, 19:19
Сообщение #8


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(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, тогда ацп начнёт выполнять нормальное преобразование.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
AnKing
сообщение Feb 4 2008, 19:33
Сообщение #9


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 2-02-08
Пользователь №: 34 686



Оказалось 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) как бы обьеденить их воедино?

Сообщение отредактировал AnKing - Feb 4 2008, 20:21
Go to the top of the page
 
+Quote Post
=GM=
сообщение Feb 4 2008, 20:21
Сообщение #10


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



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

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

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

где step=Uref/1024, лучше в милливольтах


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Feb 4 2008, 20:32
Сообщение #11


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



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


Код
itoa(ADC,sstr);
lcd_puts(sstr);


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post

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

 


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


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