Свежие обсуждения
Микроконтроллеры

Что может быть в программе не так?

1 2

Проблема такая. Если в обработчике прерывания (от любого таймера) перезагружать счетный регистр (TCNTх==0хХХ), то меандр на "железном" выходе таймера искажается (удлиняется пауза) и на дополнительном выходе, соответственно, тоже. Если убрать перезагрузку счетного регистра, то всё ОК.
Но установка нового значения TCNTх необходима, т.к. надо более- менее гибко менять частоту меандра (одного изменения коэф. предделителя clk не хватает). Как тут быть?

186308.txt

 

Лучше не перегружать TCNTх, поскольку запись может блокировать сравнение, что у вас и происходит. У вас таймер считает до МАХ и начинает опять с 0, а в это время происходит сравнение, поскольку OCRn=0, отсюда вылезают всякие бяки.

Поставьте таймер в СТС mode и новые значения (полу-)периода записывайте в OCRn регистр. Таймер будет считать от 0 до значения в OCRn и автоматом сбрасываться в 0, при этом будет инверсия OCR-пина.

 

Спасибо, прояснили. Я думал над CTC-mode, но у меня "железный" выход таймера 0 (PB.3) уже занят под кнопки. Поэтому и выбрал Normal-режим с обработкой в прерывании по переполнению. Т.е. я понимаю другого выхода как переделать кнопки без использования "железного" выхода OCR0 (PB.3) и использовании прерывания по совпадению у меня нет?

П.С. пробовал прерывания в обработчике по переполнению запрещать/разрешать, но не помогало!?

 

Ну, выход есть всегда...Например, отключить OCR0-пин (com01-com00=00), а вместо прерываний по переполнению использовать прерывания по сравнению и там внутре тоглировать любой пин, какой пожелаете.

 

Попробовал другой вариант (cv_2.txt). Ерунда какая-то. Если посмотреть на "железные" выходы таймеров, то там меандр чёткий, а в прерываниях этих таймеров (хоть по сравнению, хоть по переполнению) стоит всего по одной простенькой команде на инверсию состояния порта, а получается не мендр, а непонятно что. Что за "щет", где грабли? Запарился уже TCNT даже не трогаю ведь.

186359.txt

 

Прилагаю скрин симуляции. Картинка 88кб на самом деле.

 

Заменил команду инверсии состояния порта с помощью XOR:

PORTD.x^=1;

на инвертирование:

PORTD.x=~PORTD.x;

Меандр стал вроде нормальным, насколько можно судить по симулятору, вроде как копией меандра на "железных" выходах таймеров. Кто-нибудь может прокомментировать такую проблему, я не понимаю какая МК разница, ведь генерируемые частоты ниже тактовой во много раз? Разве XOR такая непосильная команда?

 

Новый скрин симуляции.

 

Да, какая-то ерунда получается.
А вы ассемблерный код поглядите. Интересно, во что он превращает такую простую команду. Справедливости ради, надо заметить, что в классике Си нет операций с битовыми переменными. Это кодевижн упрощает жизнь.

Я еще заметил любопытную штуку в кодевижне. Если какому-то биту порта в дефайне дать другое имя и использовать его в программе, то компилятор будет ругаться. Выходит дело, что #define не умеет работать с битовыми переменными?

Я последнее время завязал с битовыми переменными. Подключаю макросы типа:
#define SetBit(x,y) (x|=(1< < y))
#define ClrBit(x,y) (x&=~(1< < y))
#define ToggleBit(x,y) (x^=(1< < y))

Вот вам, кстати последний макрос подойдет. Попробуйте, может все-таки дело в некоректной работе с битами?

 

Спасибо, попробую на выходных. Вообще может на ICC for AVR переходить попробовать, он 4кб кода бесплатно разрешает, и мастер кода тоже есть, мне бы хватило. Не знаю только насколько в нем всё корректно будет и как он с vmlab сдружится?