|
|
  |
Подключения АЦП, Глючит и ничего не показывает |
|
|
|
Feb 3 2008, 17:56
|
Участник

Группа: Участник
Сообщений: 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(с каким-то странным префиксом - черный квадрат без двух точек внизу слева) Что я сделал неправильно?
|
|
|
|
|
Feb 3 2008, 19:49
|

фанат дивана
     
Группа: Свой
Сообщений: 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(). Ну и желательно не заниматься этим в прерывании.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Feb 3 2008, 22:48
|

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

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

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") в конце прерывания, оно всё равно разрешается аппаратно.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Feb 4 2008, 15:30
|
Участник

Группа: Участник
Сообщений: 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 ничего не помогает, на дисплее всеравно висяк.
|
|
|
|
|
Feb 4 2008, 17:00
|

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

|
Цитата(AnKing @ Feb 4 2008, 15:30)  Зашиваю этот код в контроллер и он виснет, ADC0 вообще отпаял от схемы. Подключаю ADC0 к GND и к +5V ничего не помогает, на дисплее все равно висяк Ну, а зачем вы запускаете преобразование и в прерывании и в фоне? Думаете, быстрее получится? Ничего подобного, прерывание еще не завершилось, а вы его сбрасываете в фоне. Добейтесь сначала результата при работе по ожиданию (в фоне), на прерывания потом перейдёте.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Feb 4 2008, 18:52
|
Участник

Группа: Участник
Сообщений: 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(заземлена она или подключена к питанию)
|
|
|
|
|
Feb 4 2008, 19:19
|

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, тогда ацп начнёт выполнять нормальное преобразование.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Feb 4 2008, 19:33
|
Участник

Группа: Участник
Сообщений: 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
|
|
|
|
|
Feb 4 2008, 20:21
|

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, лучше в милливольтах
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|