реклама на сайте
подробности

 
 
4 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> Работа таймера TMR0 (PIC16)
loghir
сообщение May 23 2011, 15:43
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 13-03-11
Пользователь №: 63 577



На данный момент проблема в смутном описании бита T0CS регистра OPTION:
Цитата
бит 5: T0CS: Выбор тактового сигнала для TMR0
1 = внешний тактовый сигнал с вывода RA4/T0CKI
0 = внутренний тактовый сигнал CLKOUT

внутренний тактовый сигнал - это Fosc/4?
Go to the top of the page
 
+Quote Post
xemul
сообщение May 23 2011, 17:33
Сообщение #2



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(loghir @ May 23 2011, 19:43) *
На данный момент проблема в смутном описании бита T0CS регистра OPTION:

внутренний тактовый сигнал - это Fosc/4?

Да. На блок-схеме TMR0 всё разрисовано.
Go to the top of the page
 
+Quote Post
Redguy
сообщение May 25 2011, 05:42
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 41
Регистрация: 14-01-10
Из: Россия, Самара
Пользователь №: 54 801



Блок-схема TMR0 тебе в помощь!
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
loghir
сообщение May 25 2011, 11:20
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 13-03-11
Пользователь №: 63 577



Спасибо.
Но лучше бы авторы даташита делали его в одном стиле, с большим числом информации.
Пробую получить с помощью TMR0 временной интервал в 1 сек - не работает. Цифры не меняются.
Код
// MK pic16f72

#include <pic.h>

__CONFIG (XT & WDTDIS & PWRTDIS & BOREN & UNPROTECT);
#define XTAL FREQ 4MHZ
#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;
unsigned char time3 = 0;
unsigned char time4 = 0;
unsigned char tmp100 = 0;
bit DDF = 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;
}

// для общего анода
const unsigned char arr_seg [10] =
{
0b00000011, // «0» (справа-налево) 0-горит
0b10011111, // «1»
0b00100101, // «2»
0b00001101, // «3»
0b10011001, // «4»
0b01001001, // «5»  
0b01000001, // «6»  
0b00011111, // «7»  
0b00000001, // «8»
0b00001001, // «9»
};

void init (void)
{
// настройка TMR0 на 100 Hz (сотые доли секунды).
// регистр OPTION
T0CS = 0;    // bit 5 TMR0 Выбор источника сигнала 0 - Fosc/4 (внутренний); 1 - подача на T0CKI
T0SE = 0;    // bit 4 TMR0 Выбор фронта приращения TMR0 при внешнем тактовом сигнале (0-передний фронт)
PSA  = 0;    // bit 3 Выбор включения предделителя: 0 - перед TMR0, 1 - перед WDT
PS2  = 1;    // bit 2 Настройка предделителя
PS1  = 0;    // bit 1 Настройка предделителя
PS0  = 1;    // bit 0 Настройка предделителя
TMR0 = 100;      // предзагрузка TMR0, сбрасывается при переполнении.
// конец настройки TMR0 на 100 Hz (сотые доли секунды).
}

void stTMR0 (void)    // запуск TMR0
{
GIE = 1;        // разрешены все немаскированные прерывания
PEIE = 1;        // разрешены все немаскированные прерывания от переферийных модулей
T0IE = 1;        // Разрешение прерывания по переполнению TMR0
T0IF = 0;         // сброс флага прерывания по переполнению TMR0
}

void intTMR0 (void) // обработчик прерываний TMR0 (вариант для 1 сек):
{
while (tmp100 < 100)
{
if(T0IF == 1)
    {
    tmp100 = tmp100 + 1;    // прибавление до 100 (в сумме 1 сек)
    GIE = 1;        // разрешены все немаскированные прерывания
    T0IF = 0;         // сброс флага прерывания по переполнению TMR0
    T0IE = 1;        // Разрешение прерывания по переполнению TMR0
    TMR0 = TMR0 + 100;    // предзагрузка TMR0
    }
}
time1 = time1 + 1;
}

void main (void)
{
podgot();
init();
for(;;)
{
all_1 = 0;
PORTB = arr_seg [time1];
if ((RA0 == 0)|(DDF == 1)) // запуск TMR0 или продолжение счета при DDF == 1
    {
    DDF = 1;
    stTMR0(); // запуск TMR0
    intTMR0(); // обработчик прерываний TMR0 (вариант для 1 сек):
    }
if (RA1 == 0) // останов TMR0
    {
    DDF = 0;
    T0IE = 0; // запрет прерывания по переполнению TMR0
    }
if (time1 > 9) // чтобы "time1" не вышла за пределы массива
    {
    time1 = 0;
    }
}
}

вроде все правильно , а в итоге "фиг вам". smile3046.gif
Go to the top of the page
 
+Quote Post
sargein
сообщение May 25 2011, 11:51
Сообщение #5


Участник
*

Группа: Свой
Сообщений: 72
Регистрация: 31-01-10
Из: Минск
Пользователь №: 55 176



программка жесткая какая-то, в частности выносы в функции меня в данном случае только больше запутывают sm.gif

ну а по теме: если вы хотите использовать прерывания то добавьте вот это после main() { }
Код
interrupt isr() {

if (T0IF) {
чего то делаем
T0IF = 0;
}

Go to the top of the page
 
+Quote Post
xemul
сообщение May 25 2011, 11:52
Сообщение #6



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Обработчик прерываний для мелких пиков должен выглядеть
Код
interrupt void isr(void)
{
   if(T0IF)
// или if(T0IF && T0IE)
   {
      ...
   }

   if(TMR1IF)
   {
      ...
   }
}

Имя функции обработчика прерывания не важно, но слово interrupt в её объявлении должно присутствовать.
Go to the top of the page
 
+Quote Post
loghir
сообщение May 25 2011, 12:46
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 13-03-11
Пользователь №: 63 577



sargein,
как работает оператор
Код
if (T0IF)
?
xemul,
при чем тут
Код
TMR1IF
?
как правильно объявить функцию обработчика прерываний и как ее вызвать?
Код
interrupt void isr(void)

при вызове выдает ошибку
Код
interrupt isr();

Error [195] D:\Work\PIC_CI\My_program\work_program_timer_dima\1.c; 95.1 expression syntax



Сообщение отредактировал loghir - May 25 2011, 13:47
Go to the top of the page
 
+Quote Post
sargein
сообщение May 25 2011, 13:58
Сообщение #8


Участник
*

Группа: Свой
Сообщений: 72
Регистрация: 31-01-10
Из: Минск
Пользователь №: 55 176



пишите в конце своей программы вот это:
Код
interrupt isr() {

if (T0IF) {
tmp100 = tmp100 + 1;
TMR0 = TMR0 + 100;
T0IF = 0;
}


Вызывать ничего не надо, это прерывание, оно автоматически вызывается в случае T0IF = 1



Go to the top of the page
 
+Quote Post
loghir
сообщение May 25 2011, 14:26
Сообщение #9


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 13-03-11
Пользователь №: 63 577



Если
Код
interrupt isr() {

if (T0IF) {
tmp100 = tmp100 + 1;
TMR0 = TMR0 + 100;
T0IF = 0;
}

писать до main, компилятор выдает ошибку:
Warning [349] D:\Work\PIC_CI\My_program\work_program_timer_dima\1.c; 69.1 non-prototyped function declaration for ""
Warning [349] D:\Work\PIC_CI\My_program\work_program_timer_dima\1.c; 69.1 non-prototyped function declaration for "isr"
А если до main так:
Код
void interrupt isr (void) {

if (T0IF) {
tmp100 = tmp100 + 1;
TMR0 = TMR0 + 100;
T0IF = 0;
}

то программа просто не работает: цифры не меняются.
Go to the top of the page
 
+Quote Post
sargein
сообщение May 25 2011, 14:37
Сообщение #10


Участник
*

Группа: Свой
Сообщений: 72
Регистрация: 31-01-10
Из: Минск
Пользователь №: 55 176



писать надо после main() { } я ведь это уже два раза написал

зы. по поводу программы, естественно ее еще отлаживать нужно, я просто указал как правильно обработку прерывания оформлять

ззы. рекомендую вот тут FAQ почитать

Сообщение отредактировал sargein - May 25 2011, 14:44
Go to the top of the page
 
+Quote Post
xemul
сообщение May 25 2011, 14:55
Сообщение #11



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(loghir @ May 25 2011, 16:46) *
xemul,
при чем тут
Код
TMR1IF
?

Я забыл добавить ... после if(TMR1IF) {...}, т.к. описывал общий случай.
У мелких пиков одноуровневая система прерываний, и все возможные прерывания обрабатываются в одной функции.
Больше наивных предположений и вставок на подумать делать не буду.
Цитата(loghir @ May 25 2011, 18:26) *
Если
Код
interrupt isr() {

if (T0IF) {
tmp100 = tmp100 + 1;
TMR0 = TMR0 + 100;
T0IF = 0;
}

писать до main, компилятор выдает ошибку:
Warning [349] D:\Work\PIC_CI\My_program\work_program_timer_dima\1.c; 69.1 non-prototyped function declaration for ""
Warning [349] D:\Work\PIC_CI\My_program\work_program_timer_dima\1.c; 69.1 non-prototyped function declaration for "isr"

В мануале писс есть описания всех сообщений компилятора.
Warning - предупреждение (в Вашем случае - о небрежном стиле программирования).
Не знаю, какими букварями по С Вы пользуетесь, но, имхо, в любом написано, что функция должна быть объявлена до её использования. Т.к. обработчик прерывания явно не вызывается, то его всегда стоит объявлять явно.
Код
void interrupt isr (void); // объявление (прототип) функции
int foo(int boo); // объявление другой функции с параметром и возвращаемым значением

bit fTMR0;

void main(void)
{
   if(fTMR0) { foo(...); fTMR0 = 0; }
}

void interrupt isr (void)  // сама функция (реализация)
{
   if(T0IF) { T0IF = 0; fTMR0 = 1; }
}

int foo(int boo)
{
   return boo+1;
}

Обычно прототипы функций помещают до main(), а реализацию - после или вообще в другом файле (тогда функция объявляется со словом extern).
Цитата
А если ...
то программа просто не работает: цифры не меняются.

Наверное, так прога написана. Предлагаете нам догадаться, как именно?
Go to the top of the page
 
+Quote Post
loghir
сообщение May 25 2011, 16:39
Сообщение #12


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 13-03-11
Пользователь №: 63 577



Спасибо за подсказку.
Буквари ценны тем, что быстро узнаешь структуру простейшей программы. А вот реализация у них, мягко говоря, хромает.
Прога не работает оттого, что c TMR0 проблема. TMR1 в этом же коде прекрасно работает без функции обработчика прерываний. Вся беда в том, что в программе мне надо 3 временных промежутка...
Основное достоинство самоучителей - что в одном не упомянут, в другом есть.

Сообщение отредактировал loghir - May 25 2011, 18:17
Go to the top of the page
 
+Quote Post
xemul
сообщение May 26 2011, 07:26
Сообщение #13



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(loghir @ May 25 2011, 20:39) *
Вся беда в том, что в программе мне надо 3 временных промежутка...

Определите минимально необходимый дискрет времени, заведите какой-нить аппаратный таймер с таким дискретом (пока контроллеру делать нечего - без разницы, с прерыванием или опросом), все требуемые интервалы сделайте на программных счётчиках.
Код
unsigned char FRCnt;

void main(void)
{
...
   for(;;)
   {
      if(T0IF)
      {
         TMR0 += TMR0_PRESET; // TMR0_PRESET - константа, расчёт которой можно поручить препроцессору С,
                              // задав частоту тактирования таймера и тот самый дискрет
         FRCnt++; // просто free-run counter, который поможет отсчитывать бОльшие интервалы
// синхронные задачи
// вызываемые на каждом дискрете
         dynamic_indication();
         timers();
// вызываемые, н-р, на каждом 16-ом дискрете
         if(!(FRCnt & (16-1)))
         {
            keyscan(); // сканирование кнопок
            keyparse(); // разбор нажатий/отжатий кнопок
            timers_16();
         }
// вызываемые на каждом 256-ом дискрете
         if(!FRCnt)
         {
            запорожскиеказакипишутписьмотурецкомусултану();
            timers_256();
            FRCnt1++; // эта музыка будет вечной
         }
      }
// а здесь можно разместить какие-нить асинхронные контроллеру задачи
// и неспешные задачи, которые можно выполнять по кускам
      ...
   }
}

void keyparse(void)
{
   if(Key0.b.Pressed)
   {
      LED0_OnTmr = LED_MAX_ON_TIME;
   }
   if(Key0.b.Released)
   {
      LED0 = 0; LED0_OnTmr = 0;
   }
}

void timers16(void)
{
   if(LED0_OnTmr)
   {
      if(!--LED0_OnTmr) // в пиках сюда укладывается инструкция decfsz,
                        // поэтому удобнее использовать down-counter'ы
      {
         LED0 = 0;
      }
      else
      {
         LED0 = 1;
      }
   }
}

Это, естесно, "рыба" на подумать, хоть я и обещал больше так не делать.
Go to the top of the page
 
+Quote Post
loghir
сообщение May 26 2011, 16:03
Сообщение #14


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 13-03-11
Пользователь №: 63 577



Цитата
все требуемые интервалы сделайте на программных счётчиках.

Спасибо, принцип мне понятен. И таймер удалось запустить. Как и сказано в #8, обработчик прервываний вызывается при появлении флага.
Но вот связать настройку предделителя с частотой на выходе... При кварце 4 МГц Fosc/4 = 1 МГц. Как считать частоту прерываний при коэфф. деления предделителя 2, 4... 256 ?

Сообщение отредактировал loghir - May 26 2011, 16:11
Go to the top of the page
 
+Quote Post
sergeeff
сообщение May 26 2011, 16:27
Сообщение #15


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Уважаемый loghir,

я убедился в том, что удивительный лодырь, обладающий определенным талантом напрячь окружающих на решение ваших задач. Сами думать вы, почему то, категорически не хотите.

Прерывание по таймеру работает? Да. Кто мешает в эту процедуру вставить переменную, инкрементироать ее и ваводить на свободный pin. Смотрим осциллографом частоту прерываний. Дальше играем с прескалером. Это что, фантастически сложно? Десять минут. Зато вы сами в чем-то разберетесь.
Go to the top of the page
 
+Quote Post
loghir
сообщение May 26 2011, 17:39
Сообщение #16


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 13-03-11
Пользователь №: 63 577



Цитата
я убедился в том, что удивительный лодырь, обладающий определенным талантом напрячь окружающих на решение ваших задач. Сами думать вы, почему то, категорически не хотите.

Я всего лишь прошу инфу по работе предделителя. А применю формулу расчета частоты прерываний самостоятельно. Лодырь тот, кто не написал ее в даташите. Я понимаю, что надо все делать через...осциллограф в данном случае. Может, сразу частотомер купить? (ну не даст осциллоскоп нужной точности...) Для эмпирического нахождения секретной формулы, которую никто не знает, а я напрягаю бедный форум ее выводить?
Go to the top of the page
 
+Quote Post
xemul
сообщение May 26 2011, 19:11
Сообщение #17



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(loghir @ May 26 2011, 20:03) *
Но вот связать настройку предделителя с частотой на выходе... При кварце 4 МГц Fosc/4 = 1 МГц. Как считать частоту прерываний при коэфф. деления предделителя 2, 4... 256 ?

Можно в уме, можно в столбик на бамажке, можно в куркуляторе. По-любому, сначала нужно представлять, как оно работает.
1. Задаёте частоту тактирования таймера и желаемую частоту F (или период) его прерываний.
2. Находите частное (или произведение) первого и второго. Обзовём его A.
3. (ceil(log2(A)) - (разрядность таймера)) даст Вам требуемый коэффициент деления прескейлера
4. A/2^(ceil(log2(A)) - (разрядность таймера)) даст Вам TMRx_PRESET

В случае, если у Вас есть причины заставить TMRx работать с определённым коэффициентом деления прескейлера, п.3. пропускается.

Когда надоедает считать самому, после недолгих раздумий эта работа поручается препроцессору. Правда, п.1 таки приходится выполнять самому.

Цитата
Я всего лишь прошу инфу по работе предделителя... Лодырь тот, кто не написал ее в даташите.

Предделитель делит. Трансформатор делает "у-у-у-у". "- Лодка? Она утонула."
Капитан Очевидность уже спешит к Вам на помощь.
Цитата
Я понимаю, что надо все делать через...осциллограф в данном случае.

В МПЛаб есть симулятор (МПСим), View->Logic Analizer позволит Вам в данном случае съэкономить на частотомере и осциллоскопе.
Если ещё и ман к МПСим прочитаете, то не придётся так часто менять ZF-сокет. А потом и до ICSP доберётесь.
Go to the top of the page
 
+Quote Post
sergeeff
сообщение May 26 2011, 20:36
Сообщение #18


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Вот-вот. Именно про это я писал. Выдавил таки топик-стартер кучу информации с форума, вместо персонального шевеления мозгами! Не хочет человек сам думать, хоть режь его. Чудеса, да и только. И при этом все излагает с фантастическим ехидством.

P.S. Осциллограф - главнейший прибор электронщика.
Go to the top of the page
 
+Quote Post
loghir
сообщение May 27 2011, 02:20
Сообщение #19


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 13-03-11
Пользователь №: 63 577



xemul, спасибо.
Буду разбираться. Проблема в том, что без предзагрузки таймер физически не может выдать желаемую частоту прерываний...
Пока что считаю для 8-разрядного таймера так:
Частота прерываний TMR0 (при Fosc/4, для 4 МГц, коэфф. - 256) = (1000000)/256/256 = 15,2587890625 Гц
Частота прерываний TMR0 (при Fosc/4, для 4 МГц, коэфф. - 64) = (1000000)/256/64 = 61,03515625 Гц
Частота прерываний TMR0 (при Fosc/4, для 4 МГц, коэфф. - 16) = (1000000)/256/16 = 244,184375 Гц

P.S. srergeeff, Мозги - вот главный прибор разработчика электронной аппаратуры. Тому, кто первый начал, нечего жаловаться по поводу ответного ехидства. rolleyes.gif
Go to the top of the page
 
+Quote Post
xemul
сообщение May 27 2011, 06:39
Сообщение #20



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(loghir @ May 27 2011, 06:20) *
Буду разбираться. Проблема в том, что без предзагрузки таймер физически не может выдать желаемую частоту прерываний...
Пока что считаю для 8-разрядного таймера так:
Частота прерываний TMR0 (при Fosc/4, для 4 МГц, коэфф. - 256) = (1000000)/256/256 = 15,2587890625 Гц
Частота прерываний TMR0 (при Fosc/4, для 4 МГц, коэфф. - 64) = (1000000)/256/64 = 61,03515625 Гц
Частота прерываний TMR0 (при Fosc/4, для 4 МГц, коэфф. - 16) = (1000000)/256/16 = 244,184375 Гц

Ну объясните мне, с чем здесь разбираться? Всё на уровне арифметики, если держать в голове 2^n для n хотя бы до 16.
Пусть хочется получить 50 Гц.
1000000/50 = 20000 - столько периодов тактовой частоты таймера помещается в 1 период требуемой частоты.
Сначала ищете требуемый прескейлер: (1000000/50)/256 = 78.125
Округляете вверх до степени 2: = 128 (в предыдущем посте я сначала неправильно написал, что округлять нужно вниз)
Считаете предустановку таймера: (1000000/50)/128 = 156

Далее в симуляторе ставите точку останова в нужном месте и смотрите, насколько врёт таймер. (а врать он будет и из-за целочисленности арифметики, и из-за сброса прескейлера при записи в таймер)

Если считать ручками, можно ещё проще.
20000 округляете вверх до степени 2: = 32768 = 2^15
Из 15 на таймер приходится 8 разрядов, значит степень предделителя 7.
Go to the top of the page
 
+Quote Post
sergeeff
сообщение May 27 2011, 09:02
Сообщение #21


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Цитата(loghir @ May 27 2011, 06:20) *
Мозги - вот главный прибор разработчика электронной аппаратуры


99% ошибок работы с железом состоит в том, что мы думаем или предполагаем, что оно должно работать так-то, а на самом деле работает оно по-другому. Вы зря ехидничаете насчет осциллографа. Это инструмент для действительного контроля работы вашей программы на реальном железе (в том случае, если это можно вообще как-то проанализировать или померять). Или у вас его нет? Тогда, пардон.
Go to the top of the page
 
+Quote Post
loghir
сообщение May 27 2011, 10:05
Сообщение #22


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 13-03-11
Пользователь №: 63 577



Цитата
Ну объясните мне, с чем здесь разбираться?

с информацией из #17. С Протеусом пока нехочу связываться - на реальном железе быстрее. Ненадо ни инсталляху искать, ни разбираться с управлением.
Цитата
Это инструмент для действительного контроля работы вашей программы на реальном железе

не спорю. Но в моем случае глазом видно, что при суммировании временных промежутков прерываний TMR0 частота слишком велика. Мой С1-68 все равно ее точно не покажет, не цифровик чай. (Лодырям вот сюда, на калькулятор http://pictimer.picbingo.com/download/index.php который просчитает и настройку, и предзагрузку, и даже код на С выдаст.)

Сообщение отредактировал loghir - May 27 2011, 10:06
Go to the top of the page
 
+Quote Post
sergeeff
сообщение May 27 2011, 10:44
Сообщение #23


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Вопрос на засыпку: откуда вы знаете, что ваш обработчик прерывания по таймеру 0 работает?
Go to the top of the page
 
+Quote Post
xemul
сообщение May 27 2011, 11:10
Сообщение #24



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(loghir @ May 27 2011, 14:05) *
С Протеусом пока нехочу связываться - на реальном железе быстрее.

Заниматься такими странностями Вам никто и не предлагал.
Отладка в железе может быть быстрее только при наличии железного отладчика или продуманного и отлаженного самопального способа общения с программой. У Вас нет ни того, ни другого, поэтому и тычетесь наугад в потёмках.
Я не понимаю, почему Вы упорно не желаете отлаживать свои программы в симуляторе МПЛаба - используемые Вами фичи контроллера он показывает во всех подробностях. А если ещё поймёте, зачем нужны стимулы, то можете справиться и с не-симулируемыми фичами. Через неделю Вы или поймёте, как оно (и контроллер, и симулятор) работает, или ... не поймёте.
Go to the top of the page
 
+Quote Post
loghir
сообщение May 29 2011, 14:19
Сообщение #25


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 13-03-11
Пользователь №: 63 577



Цитата
Вопрос на засыпку: откуда вы знаете, что ваш обработчик прерывания по таймеру 0 работает?

цифры на индикаторе меняются. Но очень быстро.
Код
void interrupt isr (void)
{
if (T0IF)
{
while (tmp100 < 100) // выполняется до тех пор, пока истинно (tmp100 < 100)
{
    T0IE = 0;                // Запрет прерываний по переполнению TMR0
    tmp100 = tmp100 + 1;    // прибавление до 100 (в сумме 1 сек)
    TMR0 = TMR0 + 100;        // предзагрузка TMR0
    PS2  = 1;    // bit 2 Настройка предделителя
    PS1  = 0;    // bit 1 Настройка предделителя
    PS0  = 1;    // bit 0 Настройка предделителя
    GIE = 1;                // разрешены все немаскированные прерывания
    T0IF = 0;                 // сброс флага прерывания по переполнению TMR0
    T0IE = 1;                // Разрешение прерывания по переполнению TMR0
}
time1 = time1 + 1;            // счет сотен циклов TMR0. Это число выводится 7-сегментный индикатор.
tmp100 = 0;                    // обнуление счетчика
}
}

где-то ошибка... Но где?
Цитата
Отладка в железе может быть быстрее только при наличии железного отладчика или продуманного и отлаженного самопального способа общения с программой. У Вас нет ни того, ни другого, поэтому и тычетесь наугад в потёмках.

В процессе тыканья отрабатываю самопальный способ. Всего-то надо 2 таймера запустить.
Цитата
Я не понимаю, почему Вы упорно не желаете отлаживать свои программы в симуляторе МПЛаба

нет времени и смысла разбираться, как он работает. (Там наверняка свои глюки есть. Вот будет смеху, если в в симуляторе МПЛаба все заработает, а в железе - нет.) Ради запуска 2-х таймеров?! В моей задаче точность не нужна. Всегда можно положить на таймеры и сделать простым суммированием машинных циклов.
Go to the top of the page
 
+Quote Post
sargein
сообщение May 29 2011, 14:36
Сообщение #26


Участник
*

Группа: Свой
Сообщений: 72
Регистрация: 31-01-10
Из: Минск
Пользователь №: 55 176



смутная программка sm.gif
а не могли бы вы еще раз уточнить, что конкретно нужно в итоге получить?
Go to the top of the page
 
+Quote Post
xemul
сообщение May 29 2011, 14:58
Сообщение #27



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(loghir @ May 29 2011, 18:19) *
где-то ошибка... Но где?

"- В ДНК." (из анекдота)
(я устал комментировать бездумное нагромождение букафф)
Цитата
В процессе тыканья отрабатываю самопальный способ. Всего-то надо 2 таймера запустить.

нет времени и смысла разбираться, как он работает. (Там наверняка свои глюки есть. Вот будет смеху, если в в симуляторе МПЛаба все заработает, а в железе - нет.) Ради запуска 2-х таймеров?! В моей задаче точность не нужна. Всегда можно положить на таймеры и сделать простым суммированием машинных циклов.

Флаг в руки, барабан на шею. Каждый сам себе злобный буратин.
Go to the top of the page
 
+Quote Post
loghir
сообщение May 29 2011, 15:34
Сообщение #28


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 13-03-11
Пользователь №: 63 577



xemul
в #14 я всего-навсего спросил, как рассчитать частоту прерываний TMR0 в зависимости от записанного в битах PS0...PS2. И более ничего! Нужную мне частоту я получу простым суммированием. Если много информации, я просто в ней теряюсь. Поэтому я не принимаю во внимание некоторые советы, ибо стараюсь делать программу (и процесс ее написания) попроще.

по поводу обработчика прерываний TMR0: он точно запускается, поскольку цифры на индикаторе меняются, и после нажатия RA1 счет прекращается. Частота прерываний TMR0 после предделителя у меня 100 Гц. Суммируя 100 временных интервалов прерываний я получаю 1 Гц, что и требуется. В #25 я написал мой обработчик прерываний для TMR0. Но цифры на индикаторе очень быстро меняются! Что-то там не так...
Go to the top of the page
 
+Quote Post
SKov
сообщение May 29 2011, 16:48
Сообщение #29


Знающий
****

Группа: Свой
Сообщений: 812
Регистрация: 22-01-05
Из: SPb
Пользователь №: 2 119



Цитата(loghir @ May 29 2011, 19:34) *
xemul
в #14 я всего-навсего спросил, как рассчитать частоту прерываний TMR0 в зависимости от записанного в битах PS0...PS2. И более ничего!

Эта информация есть в даташите в том месте,где описаны биты PS0...PS2. (описание регистра OPTION).
Коэффициент деления, вносимый пресалером, там указан в виде таблички.
Точно вычислить коэффициент предзагрузки TMR0 "по формуле" не представляется возможным,
поскольку не определен интервал времени между моментом прерывания и моментом предзагрузки - этот интервал
зависит от того, как написана ваша подпрограммы обработки прерывания(ППОП).
Обычно сначала грубо расчитывается частота прерваний, а более точно она подгоняется в дебагере.
Там все очень просто. Ставите точку останова на первом операторе ППОП
и замеряете время между двумя остановами (для этого надо открыть и обнулить окно StopWatch).
Затем вы корректируете константу предзагрузки в нужную сторону.

Цитата
по поводу обработчика прерываний TMR0: он точно запускается, поскольку цифры на индикаторе меняются, и после нажатия RA1 счет прекращается. Частота прерываний TMR0 после предделителя у меня 100 Гц. Суммируя 100 временных интервалов прерываний я получаю 1 Гц, что и требуется. В #25 я написал мой обработчик прерываний для TMR0. Но цифры на индикаторе очень быстро меняются! Что-то там не так...

У вас там все не так.
Не надо трогать в ППОП никаких флагов, кроме флага запроса прерывания. Т.е кроме T0IF = 0; все остальное, включая установки для
PS0...PS2. надо делать один раз вначале основной программы.
Все переменные, которые вы используете а ППОП (tmp100) надо описывать как volatile .
Предзагрузка делается не так: TMR0 = TMR0 + 100; а вот так TMR0 = 100;
И еще, если позволите, маленький совет.
Позиция "какие м...ки пишут эти даташиты!! Там ничего нельзя понять! Да и советы тут дают бестолковые.." не является оптимальной.
Гараздо более продуктивно встать в такую "позу" :
"Да, я, конечно, ламер и туго соображаю, но .. Братцы, выручайте!! Курсовик горит, а препод-зверь смотрит на меня как удав на кролика. ПАМАЖИТЕ!!!"
Такая позиция, как мне кажется, сможет вызвать к вам сочувствие и желание помочь. В отличие от первой позиции.
Удачи!
Go to the top of the page
 
+Quote Post
sargein
сообщение May 29 2011, 17:14
Сообщение #30


Участник
*

Группа: Свой
Сообщений: 72
Регистрация: 31-01-10
Из: Минск
Пользователь №: 55 176



ну как то примерно так

Код
unsigned char tmp100 = 0;
unsigned char time1 = 0;

void main(void) {
бла бла настройки таймера и прочей фигни

for (;;) {
if (tmp100 == 100) {
                           time1++;
                           tmp100 = 0;
                           функция вывода числа time1 на индикатор ();
                           }
}


}

void interrupt isr (void)
{
if (T0IF)
{
TMR0 = 100;
tmp100++;
T0IF = 0;
}
}
Go to the top of the page
 
+Quote Post
xemul
сообщение May 29 2011, 17:28
Сообщение #31



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(SKov @ May 29 2011, 20:48) *
Предзагрузка делается не так: TMR0 = TMR0 + 100; а вот так TMR0 = 100;

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

Цитата(sargein @ May 29 2011, 21:14) *
Код
volatile unsigned char tmp100;
...

Go to the top of the page
 
+Quote Post
sargein
сообщение May 29 2011, 17:51
Сообщение #32


Участник
*

Группа: Свой
Сообщений: 72
Регистрация: 31-01-10
Из: Минск
Пользователь №: 55 176



xemul, согласен, забыл про это sm.gif
Go to the top of the page
 
+Quote Post
SKov
сообщение May 29 2011, 18:01
Сообщение #33


Знающий
****

Группа: Свой
Сообщений: 812
Регистрация: 22-01-05
Из: SPb
Пользователь №: 2 119



Цитата(xemul @ May 29 2011, 21:28) *
Первый вариант позволяет таки учесть время, прошедшее с момента возникновения прерывания до момента собственно его обработки.

Не совсем так, т.к. при загрузке TMR0 сбрасывается прескалер.
Тогда уж логично сбрасывать не только прескалер, а и сам основной счетчик.
В этом случае мы как раз и получаем второй вариант.Ну, на самом деле это в принципе одно и то же (первый и второй вариант). Просто второй вариант действительно предзагрузка, а первый - предсуммирование или преддобавка, что звучит уж совсем коряво wink.gif
Относительно "равномерно размазанного" интервала я не понял.
Если предзагрузку ставить вначале ППОП (до ветвлений и других участков ППОП с неопределенным временем исполнения),
то никакой "размазаности" не будет. Будет четкий период.
Go to the top of the page
 
+Quote Post
xemul
сообщение May 29 2011, 19:00
Сообщение #34



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(SKov @ May 29 2011, 22:01) *
Не совсем так, т.к. при загрузке TMR0 сбрасывается прескалер.
Тогда уж логично сбрасывать не только прескалер, а и сам основной счетчик.
В этом случае мы как раз и получаем второй вариант.Ну, на самом деле это в принципе одно и то же (первый и второй вариант). Просто второй вариант действительно предзагрузка, а первый - предсуммирование или преддобавка, что звучит уж совсем коряво wink.gif
Относительно "равномерно размазанного" интервала я не понял.
Если предзагрузку ставить вначале ППОП (до ветвлений и других участков ППОП с неопределенным временем исполнения),
то никакой "размазаности" не будет. Будет четкий период.

Рассмотрите случай с несколькими источниками прерываний, когда прерывание от таймера возникает после проверки его флага, но внутри ППОП.
Сброс прескейлера, в предположении, что он равномерно размазан на все состояния прескейлера, учитывается совершенно отдельно - типа "TMR0 += TMR0_PRESET + 1;" (или, ещё точнее "TMR0 += TMR0_PRESET + 0.5;" - т.е. 1 добавляется через раз).
Go to the top of the page
 
+Quote Post
SKov
сообщение May 29 2011, 19:46
Сообщение #35


Знающий
****

Группа: Свой
Сообщений: 812
Регистрация: 22-01-05
Из: SPb
Пользователь №: 2 119



Цитата(xemul @ May 29 2011, 23:00) *
Рассмотрите случай с несколькими источниками прерываний, когда прерывание от таймера возникает после проверки его флага, но внутри ППОП.
Сброс прескейлера, в предположении, что он равномерно размазан на все состояния прескейлера, учитывается совершенно отдельно - типа "TMR0 += TMR0_PRESET + 1;" (или, ещё точнее "TMR0 += TMR0_PRESET + 0.5;" - т.е. 1 добавляется через раз).

Случай нескольких прерываний можно заменить, например, случаем, когда в основной программе есть куски с запретом прерываний.
Другими словами, мы говорим о случае, когда время реакции на прерывания непредсказуемо.
В этом случае надо смотреть на конкретный код программы. Если задержка реакции укладывается в несколько "тиков" таймера, тогда суммирование может нас спасти и обеспечить точность периода прерываний в пределах одного тика таймера.
А если задержка может быть большая, то вообще теряется смысл предустановки.
Можно рассмотреть и другой случай. Пусть задержка лежит в районе одного тика таймера плюс-минус несколько тактов Fosc/4.
В этом случае прибавление константы дает нам "дрожание" периода прерываний примерно на величину одного тика таймера.
А если мы выполняем загрузку таймера константой, то "дрожание" периода имеет величину всего лишь нескольких тактов Fosc/4.
Так что бывают случаи, когда загрузка лучше суммирования wink.gif

Go to the top of the page
 
+Quote Post
xemul
сообщение May 30 2011, 06:51
Сообщение #36



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(SKov @ May 29 2011, 23:46) *
Так что бывают случаи, когда загрузка лучше суммирования wink.gif

Я могу обосновать чиста математически, что загрузка в любом случае будет не лучше суммирования в смысле получения минимальной средней (или средней квадратичной - без разницы) ошибки формирования некоторого периода на любом числе периодов.
Случай, когда загрузка будет равна по ошибке суммированию, вообще один - прерывания только от таймера с минимальным прескейлером, никаких критических секций в коде.
Из очевидных минусов загрузки - собственно загружаемую константу придётся подрихтовать ручками, чтобы учесть задержку от возникновения прерывания до момента загрузки, или вставлять каким-либо образом этот учёт в считалку препроцессора. При суммировании оно учитывается само, и остаётся только решить, компенсировать ли сброс прескейлера или и так сойдёт.
Go to the top of the page
 
+Quote Post
loghir
сообщение May 30 2011, 07:29
Сообщение #37


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 13-03-11
Пользователь №: 63 577



Спасибо за гору инфы! Еще бы переварить... rolleyes.gif
Добавил квалификатор volatile а всем переменным, используемым в ППОП. От предзагрузки таймера временно отказался, пока не разберусь, что происходит. Пока мне точность не нужна.
Никак не докопаюсь, для чего нужен
Код
if (T0IF){}

ППОП и так вызывается при появлении прерывания по переполнению TMR0.
Также не пойму, как в некоторых случаях работает оператор while. В книге по микроС сказано:
Цитата
Ключевое слово while используется для организации условных циклов. Синтаксис оператора while:
while (expression) statement. Оператор statement (тело цикла) выполняется раз за разом пока величина выражения expression не станет ложной. Проверка производится перед выполнением оператора statement. Таким образом, если expression ложно в самом первом проходе, цикл не выполняется.

У Кернигана и Ритчи иная точка зрения:
Цитата
while (выражение) оператор.
Здесь вначале вычисляется выражение. Если оно не равно нулю, выполняется оператор, а затем выражение вычисляется снова. Эти действия повторяются до тех пор, пока выражение не станет равным нулю. после этого управление передается на следующий оператор.

И где истина?

Сообщение отредактировал loghir - May 30 2011, 07:33
Go to the top of the page
 
+Quote Post
SKov
сообщение May 30 2011, 07:40
Сообщение #38


Знающий
****

Группа: Свой
Сообщений: 812
Регистрация: 22-01-05
Из: SPb
Пользователь №: 2 119



Цитата(xemul @ May 30 2011, 10:51) *
Я могу обосновать чиста математически, что загрузка в любом случае будет не лучше суммирования в смысле получения минимальной средней (или средней квадратичной - без разницы) ошибки формирования некоторого периода на любом числе периодов.

Интересна не столько средняя ошибка, сколько ее дисперсия. Она определяет "дрожание" периода прерываний.
Я выше приводил пример, когда время задержки между событием, вызывающим прерывание и моментом загрузки гуляет около одного
тика таймера.(тик таймера = период срабатывания прескалера). Будем считать, что идеальным вариантом для нас является суммирование прескалера, когда задержка равна точно одному тику. Этот лишний тик мы учтем в прибавляемой константе. Это будет соответствовать нулевой ошибке.
Если время задержки в какой-то момент оказалось чуть-чуть меньше тика таймера,
то ошибка при суммирование таймера будет равна почти одному тику из-за обнуления прескалера, который к этому моменту накопил почти целый тик.
Если задержка чуть-чуть больше одного тика, то при суммировании будет ошибка небольшая. Короче говоря, ошибка при суммировании будет определяться состоянием прескалера на момент суммировния. В среднем это примерно половина тика.
В случае загрузки константы в моем примере дрожание периода определяется только интервалом времени, в котором гуляет задержка.
Это интервал между "чуть-чуть меньше тика" и "чуть-чуть больше тика".
Разница между этими моментами времени может быть существенно меньше времени тика таймера (и даже его половины).
И следовательно, дисперсия периода будет небольшой. Чиста математически wink.gif


Цитата(loghir @ May 30 2011, 11:29) *
Никак не докопаюсь, для чего нужен
Код
if (T0IF){}
.

Флаг запроса взводится автоматически при возникновении события, могущего вызвать прерывание.
А сбрасывать его должен сам программер в ППОП.
Сложность в том, что вы попадаете в одно и то же ППОП при срабатывнии прерываний от нескольких разных источников.
Вы должны определить, какой источник вас "позвал" в ППОП. Это делается опросом флагов запроса прерывания
(по-умному это называется "полинг прерываний".)
Если у вас разрешен только один источник прерываний, то эта проверка не нужна.
Цитата
Также не пойму, как в некоторых случаях работает оператор while. В книге по микроС сказано:
У Кернигана и Ритчи иная точка зрения:
И где истина?

Истина в вине wink.gif В смысле - оба источника правы. Т.к. "Ложь" кодируется нулем, а все остальное - "Правда"! wink.gif
Go to the top of the page
 
+Quote Post
xemul
сообщение May 30 2011, 08:18
Сообщение #39



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Цитата(SKov @ May 30 2011, 11:40) *
Интересна не столько средняя ошибка, сколько ее дисперсия.

Дисперсия == (средняя квадратичная ошибка)^2.
Цитата
Она определяет "дрожание" периода прерываний.

Занятное определение, ну да ладно.
Мне это было интересно во времена, когда у пиков система прерываний отсутствовала как класс, а строить какие-то диспетчеры задач и формировать интервалы всё равно приходилось. Повозил немного карандашом, пришёл к выводу... С тех пор математика (точнее, арифметика) работы таймеров не изменилась. Но у каждого кулика своё болото.sm.gif

Цитата(loghir)
Добавил квалификатор volatile а всем переменным, используемым в ППОП.

Он нужен только переменным, _модифицируемым_ в прерываниях.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение May 30 2011, 08:28
Сообщение #40


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Не встречал задач, где предзагрузка таймера в комбинации с прескалером была бы хорошим решением. Без прескалера - это я понимаю.
Go to the top of the page
 
+Quote Post
SKov
сообщение May 30 2011, 08:42
Сообщение #41


Знающий
****

Группа: Свой
Сообщений: 812
Регистрация: 22-01-05
Из: SPb
Пользователь №: 2 119



Цитата(xemul @ May 30 2011, 12:18) *
Дисперсия == (средняя квадратичная ошибка)^2.

Ну, это если "чиста математически". wink.gif
Квадратичная ошибка, да еще и в квадрате - это сильно! wink.gif
А если посмореть в букваре (можно в Википедии), то можно убедиться, что
Дисперсия ошибки == средний квадрат отклонения от средней ошибки.
Чувствуете разницу?
Go to the top of the page
 
+Quote Post
loghir
сообщение May 30 2011, 14:32
Сообщение #42


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 13-03-11
Пользователь №: 63 577



Вот что получилось:
Код
void init (void)
{
// настройка TMR0 на 100 Hz (сотые доли секунды).
// регистр OPTION
T0CS = 0;    // bit 5 TMR0 Выбор источника сигнала 0 - Fosc/4 (внутренний); 1 - подача на T0CKI
T0SE = 0;    // bit 4 TMR0 Выбор фронта приращения TMR0 при внешнем тактовом сигнале (0-передний фронт)
PSA  = 0;    // bit 3 Выбор включения предделителя: 0 - перед TMR0, 1 - перед WDT
PS2  = 1;    // bit 2 Настройка предделителя на 15 Гц
PS1  = 1;    // bit 1 Настройка предделителя на 15 Гц
PS0  = 1;    // bit 0 Настройка предделителя на 15 Гц
TMR0 = 0;      // предзагрузка TMR0, сбрасывается при переполнении.
// конец настройки TMR0 на 100 Hz (сотые доли секунды).
}


Код
void interrupt isr (void)
{
if (T0IF)    // опрос флага прерывания по переполнению TMR0 (чтобы не сработало от другого источника)
{    
while (45 - 1) // выполняется до тех пор, пока ( ) не равно 0. Задержка на 15 Гц * 45. Т.е. на 3 сек.
{
    T0IF = 0;            // сброс флага прерывания по переполнению TMR0
}
time1 = time1 + 1;        // это число выводится 7-сегментный индикатор.
T0IF = 0;                 // сброс флага прерывания по переполнению TMR0
}    
}

Вот только не срабатывает! Как был "0" на индикаторе, так и остался.
Вариант
Код
...
volatile unsigned char tmp100 = 45;
volatile unsigned char time1 = 0;
...
void interrupt isr (void)
{
if (T0IF)    // опрос флага прерывания по переполнению TMR0 (чтобы не сработало от другого источника)
{    
while (tmp100) // выполняется до тех пор, пока tmp100 не равно 0. Задержка на 15 Гц * 45. Т.е. на 3 сек.
{
    tmp100 = tmp100 - 1;    // изменение переменной-задержки
    T0IF = 0;                // сброс флага прерывания по переполнению TMR0
}
time1 = time1 + 1;        // это число выводится 7-сегментный индикатор.
tmp100 = 45;            // обнуление счетчика
T0IF = 0;                 // сброс флага прерывания по переполнению TMR0
}    
}

не изменяет скорость счета при изменении tmp100.
Попытка написать
Код
void interrupt isr (void)

после main() вызывает ощибку при компиляции.

Сообщение отредактировал loghir - May 30 2011, 14:33
Go to the top of the page
 
+Quote Post
SKov
сообщение May 30 2011, 15:28
Сообщение #43


Знающий
****

Группа: Свой
Сообщений: 812
Регистрация: 22-01-05
Из: SPb
Пользователь №: 2 119



Цитата(loghir @ May 30 2011, 18:32) *
Вот что получилось:
...
while (45 - 1)

Это что такое? Бесконечный цикл?
У вас проблемы не с микроконтроллером или с прерываниями.
У вас проблемы с элементарным программированием.
Go to the top of the page
 
+Quote Post
sargein
сообщение May 30 2011, 15:37
Сообщение #44


Участник
*

Группа: Свой
Сообщений: 72
Регистрация: 31-01-10
Из: Минск
Пользователь №: 55 176



Цитата(loghir @ May 30 2011, 17:32) *
while (45 - 1)


офигенное условие cranky.gif

Я же на прошлой странице привел фактически готовое решение, зачем столько хрени пихать в обработчик прерываний?
Go to the top of the page
 
+Quote Post
sergeeff
сообщение May 30 2011, 15:56
Сообщение #45


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Коллеги!

Уважаемый loghir не хочет сам ничего делать (читать, изучать, советы слушать). Поэтому, не поддавайтесь на его стиль вытягивания не мытьем, так катаньем, готового результата и лучше всего, просто перестаньте реагировать на его вопросы.
Go to the top of the page
 
+Quote Post
loghir
сообщение May 30 2011, 17:02
Сообщение #46


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 13-03-11
Пользователь №: 63 577



Цитата
У вас проблемы с элементарным программированием.

я это изначально не скрывал.
Цитата
Я же на прошлой странице привел фактически готовое решение, зачем столько хрени пихать в обработчик прерываний?

оно не работает. Как и while в обработчике прерываний.
sergeeff, если вам что-то не нравится - вот и не реагируйте на здоровье. Будет меньше спама.
Go to the top of the page
 
+Quote Post
loghir
сообщение May 31 2011, 07:56
Сообщение #47


Участник
*

Группа: Участник
Сообщений: 63
Регистрация: 13-03-11
Пользователь №: 63 577



Всем большое спасибо!!!!!!!
Получилось запустить TMR0 biggrin.gif .
Go to the top of the page
 
+Quote Post

4 страниц V   1 2 3 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 22:24
Рейтинг@Mail.ru


Страница сгенерированна за 0.01762 секунд с 7
ELECTRONIX ©2004-2016