Перейти к содержанию

Определение лог. уровня


;tv

Рекомендуемые сообщения

              Господа профессионалы! Приветствую вас! Подскажите пожалуйста, где в представленном ниже коде ошибка, которая не позволяет отразить лог. уровень переменной "А". на ПОРТ.В

   Код самый простой, вроде и логика присутствует, но видимо она не совпадает с логикой камня. Но почему? камень атмега8, среда атмел студио 6. язык: "С".


#define F_CPU8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
unsigned char A;                                                 // обявление глобальной переменной

void int0_set(void)
{
    MCUCR &= ~( (1<<ISC11)|(1<<ISC10)|(1<<ISC01)|(1<<ISC00) );   //сбрасываем все биты ISCxx
    MCUCR |= (1<<ISC01);                                         //настраиваем на срабатывание INT0 по спадающему фронту
    GICR |= (1<<INT0);                                           //активируем прерывание по INT0;
}

ISR(INT0_vect)
{        
    for (unsigned char i=0;i<=115;i++){}                           // инициализируем и запускаем счетчик (частоту "тиков" определяет F_CPU;)
    //PORTC|=(1<<0);                                                // тестовое условие -для наглядности результата срабатывания "for".
    //PORTC&=~(1<<0);                                               // тестовое условие
    PORTC&=0b00000010;                                              // определяем лог.состояние ПИНС.1 в точке по условию"for".
    A=PORTC;                                                      // присваивае результат переменной "А".
    
     switch (A)                                                   // тестовое условие для определения лог.величины "А" -активируем оператор "switch".
       {
           case 2:                                                
           PORTB|=(1<<0);                                         // условие при состоянии лог."1" переменной "А". 
           break;                                                 
           case 0:
           PORTB&=~(1<<0);                                        // условие при состоянии лог."0" переменной "А"
           break;
       } 
              
}

int main(void)
{
     
     DDRD&=0x00;                                        //все пины на вход, в том числе и пин на котором прерывание
     PORTD&=0x04;
     DDRB|=0xFF;
     PORTB&=0x00;
     DDRC|=0xFD;                                        //ПИНС.1 установлен на вход ?-правильно?
     PORTC&=0x00;          
     int0_set();                                        //запустили инициализацию прерывания.
     sei();                                             //глобально разрешили прерывания
     
    while(1)
    {    }
}

       На PIND.2 подаются П-образные импульсы создающие условие для срабатывания прерывания INT0. На PINC1 тоже подаются П-образные импульсы но с отличным от подающего на PIND2 частотой.  Соответственно при замере лог. уровня в "точке" определяющем условием "if", результаты должны быть то "0", то "1". Соответственно "А" должно быть или "0" или "2". Условием "switch" состояние PORTB должно реагировать на"А", но этого не  происходит. А жаль!  А почему?

 

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

немного не понятны условия, я не нашёл в вашем коде "if" (возможно им стал case)
как минимум такой код работать будет не правильно

A=PORTC;                                                      // присваивае результат переменной "А".

надо хотя бы так

A = PINC & 0x02;

зачем это? PORTC&=0b00000010;                                              // определяем лог.состояние ПИНС.1 в точке по условию"for".
вы же настроили уже пин как вход

цикл for в прерывании это плохо, надо убрать, а зачем он там?

в AVR Studio есть очень хороший отладчик, наверно он есть и в Atmel Studio прогоните код через отладчик, многое сами увидите

Изменено пользователем dm37
Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Выбираем схему BMS для заряда литий-железофосфатных (LiFePO4) аккумуляторов

Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

12 часа назад, dm37 сказал:

немного не понятны условия, я не нашёл в вашем коде "if" (возможно им стал case)
как минимум такой код работать будет не правильно


A=PORTC;                                                      // присваивае результат переменной "А".

надо хотя бы так


A = PINC & 0x02;

зачем это? PORTC&=0b00000010;                                              // определяем лог.состояние ПИНС.1 в точке по условию"for".
вы же настроили уже пин как вход

цикл for в прерывании это плохо, надо убрать, а зачем он там?

в AVR Studio есть очень хороший отладчик, наверно он есть и в Atmel Studio прогоните код через отладчик, многое сами увидите

A=PORTC; означает, что численное значения байта, которую представляет PORTC, а именно 0b00000010; .т.е. число"2", записывается в глобальной переменной "А".

Оператор "for" там за тем, что замер лог.уровня PINC0 должно произойти в то время когда это нужно тебе, а когда это нужно тебе, нужно прописать в условиях кода. Как? Включаем инкримент, и когда "for" досчитает до 115, (в моем случае i<=115;)  т,е, пройдет определенное вами время, программа выйдет из "for", и следующим шагом сделает замер с использованием "&". PORTC&=0b00000010;               

Вы наверно не обратили внимание на пояснения ниже кода. Там прописано что на PINC1 подается П-образное колебание с частотой отличной от подаваемой на PIND2  т.е. INT0  PINC1 является входом и именно лог. уровень входящего сигнала и нужно измерить в нужное время которое и определяет "for". По поводу того что "for" в прерывании плохо, я не знал.  Где можно прочитать по этому поводу?  Я  "тело" прерывания воспринимал как обычную функцию в которой можно приписать нужны код без ограничений. Подскажите пожалуйста, где прописаны условия ограничения в коде при записи в "ISR(){}". 

И если вы знаете, пропишите пожалуйста вариант кода где в прерывании INT0, в НУЖНЫЙ МОМЕНТ возможно замерить лог.уровень  N-пина.  Или это не возможно?

Ссылка на комментарий
Поделиться на другие сайты

Дело в том что строчкой PORTC&=0b00000010; вы сбрасываете все разряды, кроме первого в PORTC в ноль
Если вы хотите считать состояние разрядов порта, то для этого используется PINC, а не PORTC.
Кодом

PORTC&=0b00000010;                                              // определяем лог.состояние ПИНС.1 в точке по условию"for".
A=PORTC;                                                      // присваивае результат переменной "А".

вы сначала сбрасываете разряда PORTC, а потом считываете из PORTC (выходной регистр), то что получилось в итоге

 

14 минуты назад, ;tv сказал:

A=PORTC; означает, что численное значения байта, которую представляет PORTC, а именно 0b00000010; .т.е. число"2", записывается в глобальной переменной "А".

а что вам мешает сразу записать A = 2
 

for можно пока оставить в прерывании, нужно только понять насколько он там нужен

 

Т.е. задача такая:

при приходе прерывания INT0 вы немного ждёте (for), а после считываете состояние сигнала на линии PIND2 и на линии 0 PORTB выставляете сигнал аналогичный на входе PIND2?

Ссылка на комментарий
Поделиться на другие сайты

9 часов назад, солар сказал:

Приведите, пожалуйста, схему и саму задачу.

          Здравствуйте! Задача следующая; Имеется ФМ модуль(китайсткий 433кгц), приемник и передатчик. Нужно собрать беспроводной эл.звонок. В целях исключения случайного срабатывания реле приемника по причине эфирных помех, срабатывание реле приемника планируется при получении кода(байта) от кнопки вызова(генератора кода-байта). Соответственно нужно создать программу для чтения кода с последующим сравнением принятого кода с эталоном(ключом) прописанным в EEPROM.  Для симуляции условия "максимально приближенного к боевым" я в протеусе собрал такую схему: (АТМЕГА8)   Там генератор на PIND2/ на 17кгц, а на PINC1 на 10кгц. PINC0 контрольная точка тестового режима для наглядного наблюдения за точкой замера. в коде прописано //PORTC|=(1<<0);    тестовое условие... 

          Думаю ответил на все ваши вопросы, слово за вами! В чем ошибка в моем коде и какое решение задачи предложите.  (Купить в магазине звонок- ОТКЛОНЯЕТСЯ) типа шутка!

АТМЕГА8.PNG

Ссылка на комментарий
Поделиться на другие сайты

Делал в своё время радиомодем на RF сборке, но там не всё так просто. Дело в том, что для уменьшения постоянной составляющей в радиоканале (если АМ), необходимо использовать код манчестера. В противном случае будут проблемы при передаче одних нулей или единиц. В простом случае можно UART микроконтроллера подключить к RF модулю и отправлять байт (можно с CRC ;)). В таком случае ваша программа коренным образом измениться и станет даже проще, т.к. приём байта будет осуществлять микроконтроллер, а вам останется только сравнить принятые байты с эталоном.

Если не ошибаюсь можно обойтись без микроконтроллера - есть микросхемы шифраторы / дешифраторы команд для пропорционального управления моделями (авиа например)

Изменено пользователем dm37
Ссылка на комментарий
Поделиться на другие сайты

2 часа назад, dm37 сказал:

Делал в своё время радиомодем на RF сборке, но там не всё так просто. Дело в том, что для уменьшения постоянной составляющей в радиоканале (если АМ), необходимо использовать код манчестера. В противном случае будут проблемы при передаче одних нулей или единиц. В простом случае можно UART микроконтроллера подключить к RF модулю и отправлять байт (можно с CRC ;)). В таком случае ваша программа коренным образом измениться и станет даже проще, т.к. приём байта будет осуществлять микроконтроллер, а вам останется только сравнить принятые байты с эталоном.

Если не ошибаюсь можно обойтись без микроконтроллера - есть микросхемы шифраторы / дешифраторы команд для пропорционального управления моделями (авиа например)

                    Спасибо за информацию! Да, я знаю, есть LMххх, который при настройке пассивных элементов создает шифратор/дешифратор. НО! Главная задача для меня не решить вопрос с беспроводным звонком, в конце концов ее можно и купить, а в том что у меня есть желание поэтапно изучить программирование микроконтроллеров. По этому, я не ищу пути как обойти проблему с кодом, а пытаюсь с помощью и подсказки форумчан изучить вопрос и тем самым сделать шаг вперед!  По поводу манчестерского кодирования я слышал и UART-ом скоро займусь, но если я не смогу решить такую простую задачу как УСТАНОВИТЬ ЛОГ. УРОВЕНЬ В  N-ТОЧКЕ, значить нефиг дальше шагать!!!        Реально ведь это так просто; PORTB&=0b00001000; и вот мы знаем что записано в пин В0. Но я не справился с такой простой задачей. Код вроде логичный, но чего то я еще не знаю!  По этому и обращаюсь: Господа профессионалы ... Может и найдется такой и подскажет как блоху подковывать! 

Ссылка на комментарий
Поделиться на другие сайты

14 часа назад, dm37 сказал:

Дело в том что строчкой PORTC&=0b00000010; вы сбрасываете все разряды, кроме первого в PORTC в ноль
Если вы хотите считать состояние разрядов порта, то для этого используется PINC, а не PORTC.
Кодом


PORTC&=0b00000010;                                              // определяем лог.состояние ПИНС.1 в точке по условию"for".
A=PORTC;                                                      // присваивае результат переменной "А".

вы сначала сбрасываете разряда PORTC, а потом считываете из PORTC (выходной регистр), то что получилось в итоге

 

а что вам мешает сразу записать A = 2
 

for можно пока оставить в прерывании, нужно только понять насколько он там нужен

 

Т.е. задача такая:

при приходе прерывания INT0 вы немного ждёте (for), а после считываете состояние сигнала на линии PIND2 и на линии 0 PORTB выставляете сигнал аналогичный на входе PIND2?

          Задача такая: считать с PINC1, лог. уровень в момент обусловленный оператором "for". Это в коде видно с условия PORTC&=0b00000010; Эта запись значит:

                                                                                  PORTC =         0b000000x0;  чтоб вычислить значение "х" пользуемся свойством оператора "&"а именно  1&1=1.                                                                                                              &                                                                                                                                                                                                                                                                                                                        0b00000010;                                                                                                                                                                                                                                                            ---------------------------------------------                                                                                                                                                                                                                                                               0b000000Y0       где Y =X       следовательно "А" =Y (0 или1) т.е. его надо не прописать а вычислить и прописать

                сигнал "код" подается на PINC1.   а на PIND2 подается сигнал для управления прерыванием int0 которое нужно для старта таймера отсчитывающего "for".

Изменено пользователем ;tv
Ссылка на комментарий
Поделиться на другие сайты

12 часа назад, ;tv сказал:

                    Спасибо за информацию! Да, я знаю, есть LMххх, который при настройке пассивных элементов создает шифратор/дешифратор. НО! Главная задача для меня не решить вопрос с беспроводным звонком, в конце концов ее можно и купить, а в том что у меня есть желание поэтапно изучить программирование микроконтроллеров. По этому, я не ищу пути как обойти проблему с кодом, а пытаюсь с помощью и подсказки форумчан изучить вопрос и тем самым сделать шаг вперед!  По поводу манчестерского кодирования я слышал и UART-ом скоро займусь, но если я не смогу решить такую простую задачу как УСТАНОВИТЬ ЛОГ. УРОВЕНЬ В  N-ТОЧКЕ, значить нефиг дальше шагать!!!        Реально ведь это так просто; PORTB&=0b00001000; и вот мы знаем что записано в пин В0. Но я не справился с такой простой задачей. Код вроде логичный, но чего то я еще не знаю!  По этому и обращаюсь: Господа профессионалы ... Может и найдется такой и подскажет как блоху подковывать! 

   ОПЕЧАТКА   PORTB&=0B00001000;-НЕ ПРАВИЛЬНО. PORTB&=0b00000001;-ПРАВИЛЬНО!

Ссылка на комментарий
Поделиться на другие сайты

помочь готовы, но вот только с условиями задачи пока не поняли (я совсем запутался)
повторно спрошу, алгоритм такой?:

- по фронту на ножке PD2 мы попадаем в прерывание INT0
- немного ждём в цикле for
- считываем логический уровень с PC1
- если PC1 = 0, то на PB0 = 0
- а если PC1 = 1, то на PB0 = 1

подкорректируйте задачу, если я ошибся.

Ссылка на комментарий
Поделиться на другие сайты

@;tv  Учите мат. часть!!!

5 часов назад, ;tv сказал:

          Задача такая: считать с PINC1, лог. уровень в момент обусловленный оператором "for". Это в коде видно с условия PORTC&=0b00000010; Эта запись значит:

                                                                                  PORTC =         0b000000x0;  чтоб вычислить значение "х" пользуемся свойством оператора "&"а именно  1&1=1.                                                                                                              &                                                                                                                                                                                                                                                                                                                        0b00000010;                                                                                                                                                                                                                                                            ---------------------------------------------                                                                                                                                                                                                                                                               0b000000Y0       где Y =X       следовательно "А" =Y (0 или1) т.е. его надо не прописать а вычислить и прописать

                сигнал "код" подается на PINC1.   а на PIND2 подается сигнал для управления прерыванием int0 которое нужно для старта таймера отсчитывающего "for".

При инициализации  PORTC&=0x00; , т.е. PORTC=0; (0b00000000)

Выражение PORTC&=0b00000010; означает

PORTC=PORTC&0b00000010; , если PORTC=0 , то после выполнения этой строки PORTC останется 0

 0b00000000;

&

 0b00000010;

 -------------

 0b00000000;

A=PORTC; =>  A=0;

И выполняться будет только условие "case 0:"

5 часов назад, ;tv сказал:

          Задача такая: считать с PINC1

Так и считывайте PINC

Вам об этом уже писали:

В 28.09.2016 в 07:25, dm37 сказал:

надо хотя бы так


A = PINC & 0x02;
A = PINC & 0b00000010;

 

 

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...