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

;tv

Members
  • Постов

    60
  • Зарегистрирован

  • Посещение

Информация

  • Пол
    Мужчина
  • Интересы
    хочу все знать!
  • Город
    москва

Электроника

  • Стаж в электронике
    Менее года
  • Сфера радиоэлектроники
    радиосвязь,микроконтроллеры

Посетители профиля

1 221 просмотр профиля

Достижения ;tv

Стажер

Стажер (3/14)

  • 10 постов на форуме
  • Неделя на форуме
  • Месяц на форуме
  • Год на форуме

Последние значки

-6

Репутация

  1. Генадий и DrobyshevAlex, спасибо большое! И всем кто уделил внимание! Реально ошибка была в игнорировании состояния OCF2.
  2. С бумажкой в стране напряженка и поэтому разберу код в соответствии моих знаний/незнаний, тут! В настройках таймера прописаны комментарии, откуда следует что таймер в режиме СТС-(WGM-21),число для срабатывания по совпадению указана в OCR2,=50 делитель частоты установлен в максимум -1024, общие прерывания разрешены (sei). Условия работы таймера прописаны, и осталось только запустить его. В бесконечном цикле кодом while(PIND&_BV(PD0)){}; обусловливается точка запуска таймера, т.е. после завершения данного условия включается таймер TIMSK|=(1<<OCIE2);. при условии TCNT2=0; , т.к. На графике протеуса она отражается контрольной точкой КТ-6. В момент совпадения OCR2 и TCNT2, код уходит в прерывание и тут и должна сработать КТ-7, НО!!! На графике протеуса, КТ-7 срабатывает еще и сразу после TIMSK|=(1<<OCIE2);. С КАКОГО ПЕРЕПУГУ??? Постоялец ruhi, пишите: смотрите внимательно, там вроде было что то, когда прерывание сравнения срабатывает и по переполнению или сравнение меняет направление счета счетчика таймера. Там хороший таймер - много настроек ! Поясните пожалуйста что зашифровано в вашем послании? Сторожил Генадий, спасибо за подсказку! Мне говорили что протеус это протез, (как вы упомянули), но как и у всех, неверие до своих шишек! После сообщения Генадий, с позитивным настроем собрался просмотреть работу кода в осциллографе, и вот господа, оказывается "протез" не совсем протез! Скрин говорит сам за себя! Желтый график КТ6, зелный КТ7. КТ-7 как и в протеусе срабатывает 16-раз, а по коду в прерывание по совпадению должен уходить 8-рас. В чем ошибка?
  3. ;tv

    Atmega8_ TC2 .

    Приветствую вас! С целью разобраться таймером, прописал самый простой код, но так и не смог понять причину появления одного действия микроконтроллера. Задача: в теле обработчика прерывания, сканировать уровень лог. уровень входящего от генератора сигнала. Начало отсчета OCR2, спадающий фронт П-образного колебания. При совпадений OCR2 c TCNT2, программа уходит в прерывание и там при желании и можно сделать замер лог.уровня. Все вроде очень просто, но по неизвестной мне причине, программа заходит в тело прерывания по совпадению не только в момент OCR2 =TCNT2, а еще и при спадающем фронте сигнала. Как от этого входа в тело прерывания избавиться и почему это происходит, никак не пойму. Извращался над кодом всяко разно, но никак!! Знаю все просто, но когда знаешь! Подскажите чтоб знал! Спасибо, с уважением к вам! P.S. код и протеус (фото) прилогаеться.1.c1.c
  4. Приветствую! Если F_CPU от внешнего RC генератора, fuse low byte равно 0xC8;
  5. Здравствуйте! Зашел на вашу тему чтоб набраться опыта, и не претендую на осознания всего вашего кода, но с моей колокольни бросается в глаза обозначение частоты кварца, F_CPU 1200000LU. Для меня сочетание LU ново, может это то чего я еще не знаю, но обычно в просматриваемых мной кодах частота обозначается (в вашем случае), F_CPU 1200000UL.
  6. ОПЕЧАТКА PORTB&=0B00001000;-НЕ ПРАВИЛЬНО. PORTB&=0b00000001;-ПРАВИЛЬНО!
  7. Задача такая: считать с PINC1, лог. уровень в момент обусловленный оператором "for". Это в коде видно с условия PORTC&=0b00000010; Эта запись значит: PORTC = 0b000000x0; чтоб вычислить значение "х" пользуемся свойством оператора "&"а именно 1&1=1. & 0b00000010; --------------------------------------------- 0b000000Y0 где Y =X следовательно "А" =Y (0 или1) т.е. его надо не прописать а вычислить и прописать сигнал "код" подается на PINC1. а на PIND2 подается сигнал для управления прерыванием int0 которое нужно для старта таймера отсчитывающего "for".
  8. Спасибо за информацию! Да, я знаю, есть LMххх, который при настройке пассивных элементов создает шифратор/дешифратор. НО! Главная задача для меня не решить вопрос с беспроводным звонком, в конце концов ее можно и купить, а в том что у меня есть желание поэтапно изучить программирование микроконтроллеров. По этому, я не ищу пути как обойти проблему с кодом, а пытаюсь с помощью и подсказки форумчан изучить вопрос и тем самым сделать шаг вперед! По поводу манчестерского кодирования я слышал и UART-ом скоро займусь, но если я не смогу решить такую простую задачу как УСТАНОВИТЬ ЛОГ. УРОВЕНЬ В N-ТОЧКЕ, значить нефиг дальше шагать!!! Реально ведь это так просто; PORTB&=0b00001000; и вот мы знаем что записано в пин В0. Но я не справился с такой простой задачей. Код вроде логичный, но чего то я еще не знаю! По этому и обращаюсь: Господа профессионалы ... Может и найдется такой и подскажет как блоху подковывать!
  9. Здравствуйте! Задача следующая; Имеется ФМ модуль(китайсткий 433кгц), приемник и передатчик. Нужно собрать беспроводной эл.звонок. В целях исключения случайного срабатывания реле приемника по причине эфирных помех, срабатывание реле приемника планируется при получении кода(байта) от кнопки вызова(генератора кода-байта). Соответственно нужно создать программу для чтения кода с последующим сравнением принятого кода с эталоном(ключом) прописанным в EEPROM. Для симуляции условия "максимально приближенного к боевым" я в протеусе собрал такую схему: (АТМЕГА8) Там генератор на PIND2/ на 17кгц, а на PINC1 на 10кгц. PINC0 контрольная точка тестового режима для наглядного наблюдения за точкой замера. в коде прописано //PORTC|=(1<<0); тестовое условие... Думаю ответил на все ваши вопросы, слово за вами! В чем ошибка в моем коде и какое решение задачи предложите. (Купить в магазине звонок- ОТКЛОНЯЕТСЯ) типа шутка!
  10. A=PORTC; означает, что численное значения байта, которую представляет PORTC, а именно 0b00000010; .т.е. число"2", записывается в глобальной переменной "А". Оператор "for" там за тем, что замер лог.уровня PINC0 должно произойти в то время когда это нужно тебе, а когда это нужно тебе, нужно прописать в условиях кода. Как? Включаем инкримент, и когда "for" досчитает до 115, (в моем случае i<=115;) т,е, пройдет определенное вами время, программа выйдет из "for", и следующим шагом сделает замер с использованием "&". PORTC&=0b00000010; Вы наверно не обратили внимание на пояснения ниже кода. Там прописано что на PINC1 подается П-образное колебание с частотой отличной от подаваемой на PIND2 т.е. INT0 PINC1 является входом и именно лог. уровень входящего сигнала и нужно измерить в нужное время которое и определяет "for". По поводу того что "for" в прерывании плохо, я не знал. Где можно прочитать по этому поводу? Я "тело" прерывания воспринимал как обычную функцию в которой можно приписать нужны код без ограничений. Подскажите пожалуйста, где прописаны условия ограничения в коде при записи в "ISR(){}". И если вы знаете, пропишите пожалуйста вариант кода где в прерывании INT0, в НУЖНЫЙ МОМЕНТ возможно замерить лог.уровень N-пина. Или это не возможно?
  11. ;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 должно реагировать на"А", но этого не происходит. А жаль! А почему?
  12. ;tv

    Приветствую вас DM37!     Говорите код у вас сработал???  Я обращаюсь к вам с просьбой, подскажите в чем ошибка в моем коде? Однозначно вы что-то скоректировали иначе и у меня она бы заработала. Просмотрите пожалуйста еще раз код, обратите внимание на комментарии и подскажите отличие от вашего рабочего кода.

     

    /*
     * Atmega8_decoder_zvonok.c
     *
     * Created: 14.09.2016 21:42:57
     *  Author: SUN 
     */ 

    #define F_CPU8000000UL                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
    #include <avr/io.h>
    #include <avr/interrupt.h>

    //**********************************************************************8                                                      
                                          
                                            
    void int0_set(void)
    {
    MCUCR &= ~( (1<<ISC11)|(1<<ISC10)|(1<<ISC01)|(1<<ISC00) );   //сбрасываем все биты ISCxx
    MCUCR |= (1<<ISC01)|(1<<ISC00);                              //настраиваем на срабатывание INT0 по переднему фронту
    GICR |= (1<<INT0);                                           //разрешаем глобальное прерывание 
    GIFR|=(1<<INTF0);                                            //опрос вектора на разрешения запрета прерывания
                                                         
    }

    void pauza_set (void)
    {
        TCNT2=50;                    //число/старт отсчета до числа OCR2
        TIMSK|=(1<<OCIE2);          // по совпадению
        OCR2=150;                   // число по совпадению TCNT2=OCR2
        TCCR2|=(1<<WGM21);          // режим CTC;
        TCCR2|=(1<<CS20);           // prescaler                             
    }

     void puls_set(void)
     {
        
        TCNT2=0;                    //число/старт отсчета до числа OCR2    
        TIMSK|=(1<<OCIE2);          // по совпадению
        OCR2=200;                   // число по совпадению TCNT2=OCR2
        TCCR2|=(1<<WGM21);          // режим CTC;
        TCCR2|=(1<<CS20);           // prescaler    
     }
                                                 
    ISR( INT0_vect )
    {                     
        pauza_set ();                   // инициировали и запустили условия pauza_set();        
    }
     
     ISR(TIMER2_COMP_vect)               //при pauza_set=0; т.е. по истечении времени обусловленного pauza_set();
     {
        PORTC|=(1<<1);                   // тестовый импульс на ПИНС0 для контроля срабатывания INT0 (на форуме высказали сомнение)
        PORTC&=~(1<<1);                     //"------------------------------------------------------------------------------------"
        unsigned char pauza;             // инициализация локалной переменной  (иначе ругается)!
        if (!pauza)                      // если pauza=0
        {
            PORTC|=(1<<0);               // лог"1"
            pauza++;                     // pauza=1;
            puls_set();                     // запускаем условия puls_set; (отсчитав обусловленное время, возврашается к условию if)
        } 
        else
        {
            PORTC&=~(1<<0);              // проверив условие if, т.к.pauza=1, сработает условие else. (НЕ СРАБАТЫВАЕТ!!!!)        
        }    
          TCCR2=0;                         
          TIMSK=0;                                                                       
     }
          
    int main(void)
    {  
        DDRD&=0x00;                                       //0;//все пины на вход, в том числе и пин на котором прерывание
        PORTD&=0x00;
        PORTD|=(1<<2);                                    //подтягивоющий резистор.
        DDRB|=0xFF;
        PORTB&=0x00;
        DDRC|=0xFF;
        PORTC&=0x00;
        int0_set();                                         //запустили инициализацию прерывания.
        sei();                                             //глобально разрешили прерывания
        
        while(1)
        {            
                asm("nop");
        }
        
    }
     

     Тут ниже для наглядности картинка с протеуса. INT0-работает, pauza_set(); отрабатывает свое время(ПИНС.1)

     

     

    Снимок.PNG

    1. dm37

      dm37

      Привет,

      ну что сразу бросилось в глаза это

       unsigned char pauza;             // инициализация локалной переменной  (иначе ругается)!

      эта переменная должна определятся как глобальная, т.е. должна быть здесь

       /*
       * Atmega8_decoder_zvonok.c
       *
       * Created: 14.09.2016 21:42:57
       *  Author: SUN 
       */ 
      #define F_CPU8000000UL                                                                                                                             #include <avr/io.h>
      #include <avr/interrupt.h>
      
      //**********************************************************************8                                                      
      volatile unsigned char pausa;

      надо поставить volatile, чтобы компилятор не выбросил операции с этой переменной из кода после оптимизации (так надо поступать со всеми переменными, которые меняются в прерываниях). Когда вы объявили переменную внутри прерывания, да ещё и не присвоили ей значение вы при сравнении в переменной pausa, в лучшем случае будет всегда получать 0, а обычно там разный мусор (т.к. для локальных переменных компилятор старается использовать регистры, которые при этом не инициализирует). Глобальные переменные, по умолчанию, всегда инициализируются 0.

      Попробуйте сначала изменить это, потом дальше посмотрим

      можно немного оптимизировать функции pauza_set() и pulse_set():
      вынести настройку режима CTC (выполнять только один раз в main()), а оставить только настройку задержек, т.е.
      - останавливаем таймер (prescaler = 0)
      - устанавливаем новое значение задержки
      - запускаем таймер

  13. ;tv

    Работа с T/C2

    Он установлен!
  14. Виктор здравствуйте! Извините за беспокойства, но видимо без вашей  подсказки моя задача не разрешится решением. Думал вы выскажите свое обоснованное, как всегда, мнение, но так и не дождался. Надеюсь у вас все хорошо и вас не слышно по причине занятости! В общем, если найдете пару минут, просмотрите мою тему "Работа с T/C2", и скажите пару слов, которых ждет народ!:acute:

     

  15. ;tv

    Работа с T/C2

    DM37, спасибо за вариант, но он у меня все равно не заработал. Может я не так перевел? Вот вариант перевода: /* * _8_zvinok_2.c * * Created: 20.09.2016 19:19:28 * Author: SUN */ #define F_CPU1000000UL #include <avr/io.h> #include <avr/interrupt.h> volatile unsigned char pause; void int0_set(void) { MCUCR &= ~((1<<ISC11)|(1<<ISC10)|(1<<ISC01)|(1<<ISC00)); //сбрасываем все биты ISCxx MCUCR |= (1<<ISC01)|(1<<ISC00); //настраиваем на срабатывание INT0 по переднему фронту GICR |= (1<<INT0); //разрешаем глобальное прерывание GIFR |= (1<<INTF0); // Сбросить флаг } void pauza_set(void) { TCCR2 = 0; TCCR2 |= (1<<WGM21) | (0<<WGM20); // режим CTC; TCCR2 |= (0<<CS22) | (1<<CS21) | (0<<CS20); // prescaler TIMSK |= (1<<OCIE2); // по совпадению OCR2 = 250; // число по совпадению TCNT2=OCR2 TIFR=(1<<OCF2); } void puls_set(void) { TCCR2 = 0; TCCR2 |= (1<<WGM21) | (0<<WGM20); // режим CTC; TCCR2 |= (0<<CS22) | (1<<CS21) | (0<<CS20); // prescaler TIMSK |= (1<<OCIE2); // по совпадению OCR2 = 150; // число по совпадению TCNT2=OCR2 TIFR |=(1<<OCF2); } ISR(INT0_vect) { PORTC &= ~(1<<0); // установили ПИНС0 в лог"0" pauza_set(); // инициировали и запустили условия pauza_set(); } ISR(TIMER2_COMP_vect) { if(!pause) { PORTC |= (1<<0); // начало импульса / старт лог"1" pause++; puls_set(); // инициализация и запуск условия puls_set (); !!!!!!!!!!!!!!! НЕ ЗАПУСКАЕТСЯ !!!!!!!!!!!!!!!!!!!!!!!!! } else { /* * _8_zvinok_2.c * * Created: 20.09.2016 19:19:28 * Author: SUN */ #define F_CPU1000000UL #include <avr/io.h> #include <avr/interrupt.h> volatile unsigned char pause; void int0_set(void) { MCUCR &= ~((1<<ISC11)|(1<<ISC10)|(1<<ISC01)|(1<<ISC00)); //сбрасываем все биты ISCxx MCUCR |= (1<<ISC01)|(1<<ISC00); //настраиваем на срабатывание INT0 по переднему фронту GICR |= (1<<INT0); //разрешаем глобальное прерывание GIFR |= (1<<INTF0); // Сбросить флаг } void pauza_set(void) { TCCR2 = 0; TCCR2 |= (1<<WGM21) | (0<<WGM20); // режим CTC; TCCR2 |= (0<<CS22) | (1<<CS21) | (0<<CS20); // prescaler TIMSK |= (1<<OCIE2); // по совпадению OCR2 = 250; // число по совпадению TCNT2=OCR2 TIFR=(1<<OCF2); } void puls_set(void) { TCCR2 = 0; TCCR2 |= (1<<WGM21) | (0<<WGM20); // режим CTC; TCCR2 |= (0<<CS22) | (1<<CS21) | (0<<CS20); // prescaler TIMSK |= (1<<OCIE2); // по совпадению OCR2 = 150; // число по совпадению TCNT2=OCR2 TIFR |=(1<<OCF2); } ISR(INT0_vect) { PORTC &= ~(1<<0); // установили ПИНС0 в лог"0" pauza_set(); // инициировали и запустили условия pauza_set(); } ISR(TIMER2_COMP_vect) { if(!pause) { PORTC |= (1<<0); // начало импульса / старт лог"1" pause++; puls_set(); // инициализация и запуск условия puls_set (); !!!!!!!!!!!!!!! НЕ ЗАПУСКАЕТСЯ !!!!!!!!!!!!!!!!!!!!!!!!! } else { PORTC &= ~(1<<0); // конец импульса /лог"0" TCCR2 = 0; // TIMSK = 0; // } } int main(void) { DDRD = 0x00; //0;//все пины на вход, в том числе и пин на котором прерывание PORTD = (1<<2); //подтягивоющий резистор. DDRB = 0xFF; PORTB = 0x00; DDRC = 0xFF; PORTC = 0x00; int0_set(); //запустили инициализацию прерывания. sei(); while(1) { asm("nop"); } } // } } int main(void) { DDRD = 0x00; //0;//все пины на вход, в том числе и пин на котором прерывание PORTD = (1<<2); //подтягивоющий резистор. DDRB = 0xFF; PORTB = 0x00; DDRC = 0xFF; PORTC = 0x00; int0_set(); //запустили инициализацию прерывания. sei(); while(1) { asm("nop"); } } В таком варианте, ПИНС0 при INT0 уходит в лог "0" и там остается. Тут мне не понятна смысл логики функции " if ". Я прочитал ее так: if(!pauza), -pauza по умолчанию "0", и условие значит: если пауза истина, т.е. (=1) выполнится часть "тела" PORTC &= ~(1<<0); // конец импульса /лог"0" TCCR2 = 0; // TIMSK = 0; и далее условие в " if ()" никак не поменяется. В результате и получается лог"0" по условию ISR(TIMER2_COMP_vect). Надеюсь кто поправит мое понимание кода или подскажет правильное решение!!! PS. код второпях прописал дважды, надеюсь не создаст больших проблем! Пардон!
×
×
  • Создать...