loghir 0 28 апреля, 2011 Опубликовано 28 апреля, 2011 (изменено) · Жалоба Доброго времени суток! Сохраняется ли предзагрузка таймера более одного цикла работы? После первого переполнения или сброса модулем CCP? Изменено 28 апреля, 2011 пользователем loghir Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ruslan1 17 28 апреля, 2011 Опубликовано 28 апреля, 2011 · Жалоба Доброго времени суток! Сохраняется ли предзагрузка таймера более одного цикла работы? После первого переполнения или сброса модулем CCP? нет. Если вы хотите именно через TMR1 организовать прерывание с какой-то постоянной периодичностью, то нужно переустанавливать таймер после каждого переполнения. В простейшем случае: TMR1 = VALUE Лучше (это веди PIC16, он побайтово работает, а таймер-то 16-битный, для исключения запланированных проблем таймер лучше остановить на время модификации) TMR1ON = 0 TMR1 = VALUE TMR1ON = 1 Но от момента переполнения(обнуления) до момента модификации уже прошло какое-то время, лучше его учесть, если хотите сохранить период прерываний неизменным: TMR1ON = 0 TMR1 = TMR1 + VALUE TMR1ON = 1 Но во время остановки таймер не считал, так что нужно еще и это время учесть, если хотите чтобы период был именно тот что вы хотите, а не чуть больше: TMR1ON = 0 TMR1 = TMR1 + VALUE + DELTA TMR1ON = 1 (DELTA зависит от того, во что компилируются ваши команды от остановки до запуска таймера и может быть четко и однозначно рассчитана только для ассемблерного варианта) Если же все это происходит не в прерывании, то также рекомендую запретить прерывания на время выполнения, чтобы не заложить запланированную проблему в код: GIE = 0 TMR1ON = 0 TMR1 = TMR1 + VALUE + DELTA TMR1ON = 1 GIE = 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xemul 0 28 апреля, 2011 Опубликовано 28 апреля, 2011 · Жалоба Позволю себе дополнить предыдущего оратора. Если используется прескейлер, то, т.к. он обнуляется при записи в TMR, через раз можно (если таки боремся за точность) накидывать ещё единичку TMR1 += VALUE + DELTA + 1 Результат компиляции TMR1 += VALUE + DELTA TMR1 = TMR1 + VALUE + DELTA может отличаться, если VALUE и/или DELTA не константы, с которыми справился препроцессор. (точнее было бы написать "должен отличаться", но писс, н-р, по-любому оптимизирует до TMR1 += VALUE + DELTA , а потом может сделать так TMR1 += (VALUE + DELTA) или так TMR1 += VALUE TMR1 += DELTA ) А если вдруг VALUE и/или DELTA окажутся volatile, то для получения однозначного результата проще оформить такой кусок ассемблерной вставкой. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ruslan1 17 28 апреля, 2011 Опубликовано 28 апреля, 2011 · Жалоба ......Но если хочется совсем-совсем точно, то нужно использовать TMR2 в сочетании с PR2. Этот таймер может работать в режиме "досчитал до значения равного содержащемуся в регистре PR2 и сбросился с установкой флага". В этом случае вообще все под контролем железяки и ничего не нужно переустанавливать программно. Но это уже ответ, выходящий за рамки вопроса :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
slavka012 0 28 апреля, 2011 Опубликовано 28 апреля, 2011 · Жалоба ......Но если хочется совсем-совсем точно, то нужно использовать TMR2 в сочетании с PR2. +1. Так же поддерживаю вариант с TMR1 = TMR1 + VALUE + DELTA Дельта вычисляется эксперементальным путем -- запускаем симулятор и засекаем время между срабатываниями. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
loghir 0 28 апреля, 2011 Опубликовано 28 апреля, 2011 · Жалоба Спасибо за неожиданно информативный ответ! Насчет TMR2: в даташите сказано: После сброса значение регистра PR2 равно FFh. Получается, после сброса значение регистра PR2 нужно задавать заново? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ruslan1 17 28 апреля, 2011 Опубликовано 28 апреля, 2011 · Жалоба Спасибо за неожиданно информативный ответ! Насчет TMR2: в даташите сказано: Получается, после сброса значение регистра PR2 нужно задавать заново? Речь идет о состоянии регистра после сброса микроконтроллера сигналом Reset или после включения :) К обнулению таймера это не относится :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VVD_2 0 15 мая, 2011 Опубликовано 15 мая, 2011 · Жалоба Доброго времени суток! Сохраняется ли предзагрузка таймера более одного цикла работы? После первого переполнения или сброса модулем CCP? для PIC16F876x Если Вам необходимо получить повторяющийся интервал на TMR1, то лучше использовать ССР1 в режиме автосброса таймера (CCP1CON bit3-0 = 1011 = Compare mode, trigger special event (CCPxIF bit is set, CCPx pin is unaffected); CCP1 resets TMR1) и предварительно загрузив требуемый период в CCPR1H и CCPR1L. Если период постоянный, то перезагружать CCPR1H и CCPR1L не надо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
loghir 0 17 мая, 2011 Опубликовано 17 мая, 2011 · Жалоба Все ли у меня в порядке с настройками таймера? void init (void) // настройка TMR1 для 1.90735 сек { GIE = 1; // разрешены все немаскированные прерывания // регистр T1CON T1CKPS1 = 1; // выбор коэфф. деления предделителя T1CKPS0 = 0; // выбор коэфф. деления предделителя T1OSCEN = 0; // выключить внутренний тактовый генератор модуля TMR1 TMR1CS = 0; // 1 - выбран внешний (0 - внутренний, Fosk/4) источник тактового сигнала модуля TMR1 TMR1H = 0x0; // preset for timer1 MSB register TMR1L = 0x0; // preset for timer1 LSB register } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
[sarge] 0 17 мая, 2011 Опубликовано 17 мая, 2011 · Жалоба PEIE забыли. Ну и в тексте программы где-то дальше не забудьте вставить TMR1IE = 1 и TMR1ON = 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
loghir 0 17 мая, 2011 Опубликовано 17 мая, 2011 · Жалоба sarqein спасибо! Добавлю в настройку PEIE = 1; // разрешены все немаскированные прерывания от переферийных модулей TMR1IE = 1; // Разрешение прерывания по переполнению TMR1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
loghir 0 17 мая, 2011 Опубликовано 17 мая, 2011 (изменено) · Жалоба Нигде не нашел данных: при Fosk/4 = 1 Mhz (при TMR1H = 0x0; TMR1L = 0x0;) 15,25879Hz T1CKPS1 = 0 T1CKPS0 = 0 7,62939Hz: T1CKPS1 = 0 T1CKPS0 = 1 3,8147Hz: T1CKPS1 = 1 T1CKPS0 = 0 1,90735 Hz: T1CKPS1 = 1 T1CKPS0 = 1 правильно? Изменено 17 мая, 2011 пользователем loghir Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
[sarge] 0 17 мая, 2011 Опубликовано 17 мая, 2011 · Жалоба Правильно, оно же все делением получается хорошо, что тут проверять? :) 11 = 1:8 10 = 1:4 01 = 1:2 00 = 1:1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
loghir 0 23 мая, 2011 Опубликовано 23 мая, 2011 (изменено) · Жалоба Таймер упорно не работает: (счет не начинается) // MK pic16f72 #include <pic.h> __CONFIG (XT & WDTDIS & PWRTDIS & BOREN & UNPROTECT); #define all_1 RC4 // общие провода 1-4 разрядов #define all_2 RC5 #define all_3 RC6 #define all_4 RC7 unsigned char time1 = 0; // объявляем глобальные переменные счетчика 1-4 разрядов и обнуляем их. unsigned char time2 = 0; void podgot (void) { ADCON1 = 0x07; // отключение АЦП TRISA = 0b111111; // (0/1 - выход/вход, нумерация битов в регистре справо-налево) TRISB = 0b00000000; // (0/1 - выход/вход, нумерация битов в регистре справо-налево) TRISC = 0b00000000; // (0/1 - выход/вход, нумерация битов в регистре справо-налево) RBPU = 1; PORTA = 0; PORTB = 0b11111111; PORTC = 0b11111111; } // для общего анода, КИПЦ-09. const unsigned char arr_seg [10] = { /* начало массива 0bABCDEFGH – расположение сегментов по битам */ 0b00000011, // «0» ! (справа-налево) 0-горит 0b10011111, // «1» ! 0b00100101, // «2» ! 0b00001101, // «3» ! 0b10011001, // «4» ! 0b01001001, // «5» ! 0b01000001, // «6» ! 0b00011111, // «7» ! 0b00000001, // «8» ! 0b00001001, // «9» ! }; void init (void) { // общие настройки таймеров // регистр INTCON GIE = 1; // разрешены все немаскированные прерывания PEIE = 1; // разрешены все немаскированные прерывания от переферийных модулей // настройка TMR1 для 1,90735 Hz // регистр T1CON T1CKPS1 = 1; // выбор коэфф. деления предделителя T1CKPS0 = 1; // выбор коэфф. деления предделителя T1OSCEN = 0; // выключить внутренний тактовый генератор модуля TMR1 TMR1CS = 0; // 1 - выбран внешний (0 - внутренний, Fosk/4) источник тактового сигнала модуля TMR1 TMR1H = 0x0; // preset for timer1 MSB register TMR1L = 0x0; // preset for timer1 LSB register // конец настройки TMR1 для 1,90735 Hz } void main (void) { podgot(); for(;;) { all_1 = 0; // общий анод PORTB = arr_seg [time1]; if (RA0 == 0) // запуск TMR1 { // регистр PIE1 TMR1IE = 1; // Разрешение прерывания по переполнению TMR1 TMR1ON = 1; // включить TMR1 } if (RA1 == 0) // останов TMR1 { // регистр PIE1 TMR1IE = 0; // Запрет прерывания по переполнению TMR1 TMR1ON = 0; // выключить TMR1 } while (TMR1IF == 0) // (пауза 1,90735 Hz) ожидание флага по переполнению TMR1 {} TMR1IF = 0; time2 = time2 + 1; if (time2 == 2) // деление частоты превывания TMR1 на 2 { time2 = 0; time1 = time1 + 1; } if (time1 > 9) // чтобы "time1" не вышла за пределы массива { time1 = 0; } } } где ошибка?! На RA0 и RA1 подается +5В через резистор 4к7. Кнопка замыкает линии порта на "массу". Изменено 23 мая, 2011 пользователем loghir Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xemul 0 23 мая, 2011 Опубликовано 23 мая, 2011 · Жалоба ... if (RA1 == 0) // останов TMR1 { // регистр PIE1 TMR1IE = 0; // Запрет прерывания по переполнению TMR1 TMR1ON = 0; // выключить TMR1 } while (TMR1IF == 0) // (пауза 1,90735 Hz) ожидание флага по переполнению TMR1 {} TMR1IF = 0; // как Вы предполагаете попасть сюда с "TMR1ON = 0"? ... } где ошибка?! Вы забыли вызвать init() Просто за жизнь: - time1, time2 у Вас глобальные и будут обнулены в стандартном стартапе (т.е. при объявлении timeX = 0 писать не обязательно); - разрешать прерывания лучше после инициализации соответствующей периферии; - "нет, я столько не выпью", поэтому даже не стал пытаться понять, зачем GIE = 1, но ни одно прерывание не разрешено, да логику программы в целом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться