Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Чт сен 03, 2009 13:30:39
Здравствуйте, снова я со своими вопросами
!!
Вобщем проблема в том, что не работает (или я балбес
) аналоговый компаратор на MEGA8:
програмлю следующим образом:
- Код:
#include (avr/interrupt.h) // скобы конечно угловые
#include (util/delay.h)
#define F_CPU 1000000UL // 8 MHz
ISR(ANA_COMP_vect){ //Обработчик прерывания
PORTC = 0xff;
}
int main(void){
DDRC = 0xff;
ACSR=0x08; // аналоговый компаратор, прерывание по изменению
sei(); // Разрешение прерываний глобально
}
В итоге как ни изменяю уровни на AIN0 AIN1, все бестолку, никакого прерывания не происходит (на порт С не выводится 1)
Чт сен 03, 2009 13:55:32
по-моему вы или кто-то другой буквально день назад уже наступали на эти же грабли: нельзя делать main без вечного цикла: при "выходе" из main запрещаются прерывания и происходит зацикливание, т.е. прерывания разрешены у вас ровно 1 машинный такт.
Чт сен 03, 2009 13:57:35
Да, я тож подумал об этом, сделал, все равно не рабит
Чт сен 03, 2009 14:01:01
ну потрудитесь расписать побитово, что вы там устанавливаете в ACSR: то, что вы пишите - не воспринимается
Чт сен 03, 2009 14:16:58
[/code]
#include <avr>
#include <util>
#define F_CPU 1000000UL // 8 MHz
ISR(ANA_COMP_vect){ //Обработчик прерывания
PORTC ^= (PINC | 0x01);
}
int main(void){
DDRC = 0xff;
ACSR=0x08; // аналоговый компаратор, прерывание по изменению
sei(); // Разрешение прерываний глобально
while(1){}
}
[/code]
Прошу прощения просто после while(1){} make clean не сделал! Все работает. Спасибо !!
Чт сен 03, 2009 14:23:38
я тут уже советовал другим, посоветую и вам: используйте макросы, типы и т.п., являющиеся "стандартными" для WinAVR - это позволит вам иметь более читаемый другими любителями WinAVR код, да и сами будете лучше понимать, что делаете.
- Код:
ACSR = _BV(ACIE); // это ведь нагляднее, чем 0x08 - не так ли?
а это что бы означало:
- Код:
ISR(ANA_COMP_vect){ //Обработчик прерывания
PORTC ^= (PINC | 0x01); }
если надо переключать уровень на порту, то надо делать проще:
- Код:
PORТC ^= _BV(PC0); // переключаем 0 бит порта С
Чт сен 03, 2009 14:25:58
Хорошо, буду иметь ввиду.
Чт сен 03, 2009 16:16:34
-==MAXCELERON==- писал(а):Хорошо, буду иметь ввиду.
Не имей ввиду, все ты правильно делаешь, записывая в регистр конкретное число. Просто в коментах укажи какие биты в единицу, какие в ноль и все.
Почему? Потому что,
#define _BV(bit) (1 << (bit))
Это означает сдвиг единицы на определенное число, тем самым требуя на каждый сдвиг один такт. Если вы хотите установить седьмой бит в регистре, то знайте, уйдет семь тактов. А если просто 0x80 то всего один.
Эт я так, рекомендую.
А еще лучше, написать свои макросы типа
SET_ADC_ACIE = ACSR |= 0x80;
----------
Чт сен 03, 2009 16:26:40
__Alexander, я вам очень настоятельно рекомендую прежде чем давать рекомендации, хорошенько изучить язык Си... иначе вы можете попасть в глупое положение, когда ваши рекомендации не имеют ничего общего с реальностью...
в данном случае, вы забываете, что Си - это не бейсик, и все вычисления, которые могут быть сделаны на этапе компиляции, будут сделаны именно на этапе компиляции.
то есть все сдвиги сделает компилятор, а в код запишется только результат этих сдвигов. ведь не думаете же вы, что с = 2 * 8 + 16 / 4; приведет к генерации команд умножения, деления и сложения?! на самом деле в с сразу будет записано число 20.
кроме того, ваш совет на счет макросов - от него волосы поднимаются... в регистре 8 битов, устанавливать которые можно в разных комбинациях, т.е. всего 256 комбинаций... вы для каждой предлагаете написать макрос?! мой совет касался в соновном использования символьных имен битов для управляющих регистров, что имеет смысл - наглядность кода резко повышается... а ваш метод что дает?! только хуже сделает...
Чт сен 03, 2009 17:15:35
Мда, согласен, совет данного макроса был не совсем уместен.
Но вот когда в макросе происходят арифметические действия который будет получен после вызова функции... хотя, короче, чего это я. Это дело компилятора, я хотел сказать что макрос, это просто подставление его в код программы. А че с ним сделает компилятор - это другой вопрос.
----------
Ср май 30, 2012 20:48:40
Добрый день уважаемые. У меня тот же вопрос написал простой код для работы компоратора. В котором при изменении значения выхода ACO зажигается или тухнит светодиод PD7, а при изменении значения с 0 на 1 вызывается прерывание комп. Только вот почему то прерывание не вызывается, а PD7 горит не тухнит, при изменении значения входов с 0 до 2,5В.
Пробую пример в Proteuse 7 SP3
и на плате Pinboard 1.1. Подскажите в чем дело.
- Код:
#include<avr/io.h>
#include <avr/interrupt.h>
ISR (ANA_COMP_vect) {
PORTD ^= (1<<PD4);
}
//ОСНОВНАЯ ФУНКЦИЯ
int main(void) {
//Инициализация переферии
DDRD=(1<<PD4)|(1<<PD7);//На выход сигнала
DDRB=(0<<PB2)|(0<<PB3);//На вход
PORTB=(0<<PB2)|(0<<PB3);
//ACIE-разрешаем прерывание от компаратора.ACIS1;ACIS0-Ловим 0-1
ACSR=(1<<ACIE)|(0<<ACIS1)|(0<<ACIS0);
asm("sei");//Разрешаем объявленные прерывания
while (1) {
PORTD = (ACO<<PD7);//Заносим значение в PD7 значение ACO
}
}
Чт май 31, 2012 06:44:56
У Вас все нормально работает. Просто Вы неверно подключили приборы. Резистором RV2 устанавливается порог срабатывания компаратора, а срабатывание компаратора определяется движком резистора RV1 (или наоборот, это как Вам больше нравиться). Исправленная схема во вложении.
- Вложения
-
- easy_analog_compor_1.rar
- Компаратор
- (34.35 KiB) Скачиваний: 228
Чт май 31, 2012 22:32:05
siamds писал(а):У Вас все нормально работает. Просто Вы неверно подключили приборы. Резистором RV2 устанавливается порог срабатывания компаратора, а срабатывание компаратора определяется движком резистора RV1 (или наоборот, это как Вам больше нравиться). Исправленная схема во вложении.
Спасибо за ответ, действительно не правильно собрал схему.
Ваша схема у меня работает, только почему то с 55 секунды, тоесть до 55 с меняю значения на сопротивлениях и все молчит. Вы меняли что нибудь в коде?(Просто мой код прошивки тот который я привел не работает, а ваш работает)..... или может просто очередной баг Proteusa.
Пт июн 01, 2012 06:18:56
EmDmAl писал(а): с 55 секунды, тоесть до 55 с меняю значения на сопротивлениях и все молчит.
Вероятно это происходит потому что у Вас между портом и светодиодом не стоит токоограничительное сопротивление. Светодиоды нельзя напрямую подключать на выход порта. Поставьте резистор порядка 300ом и проблема должна исчезнуть.
Сб июн 02, 2012 11:23:46
По ошибки я выкладывал hex файл, в главном теле которого
- Код:
while (1) {
if (ACSR&(1<<ACO)) {//Если в ACO = 1
PORTD = (1<<PD7);
} else { PORTD = (0<<PD7);}
}
поэтому вариант PORTD = (ACO<<PD7); не работает.
Значит надо использовать связку выше.
Powered by phpBB © phpBB Group.
phpBB Mobile / SEO by Artodia.