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

Управление таймером по кнопкам в ATmega16

Составил програмку, которая выдает заданную времянку на два порта. Частота выдачи зависит от частоты таймера/счетчика 0 (частота тактирования сейчас не принципиальна и принята 1МГц). Меняется частота по нажатию кнопок 1,2,3. Останавливается - по кнопке 0.

Выложил в прикрепленном файле проект для cvavr и vmlab. В vmlabe код работает, но есть такие проблемы:

1. Если нажать и удерживать кнопку 1 или 2, то генерация частоты прекращается, а с кнопкой 3 такого не происходит (хотя частота генерации падает), почему так, непонятно? Как сделать генерацию не зависящей от того как долго удерживается клавиша?

2. Как-то громоздко мне кажется задается код опроса клавиш, но упростить не вижу как. Может кто подскажет другие, поизящнее что-ли, варианты?

177736.zip

 

1. В конструкции if(i==116&(!(chet%2))) Вы уверены, что хотели написать один амперсанд, а не два?
2. Обнуление TCNT0 в обработчике прерываний бессмысленно.
3. Не нужно в main дергать регистр TCCR0 несколько сотен тысяч раз в секунду, даже если значения в нем и не изменяются. Тут у любого таймера крыша поедет. Удивительно, что он еще хоть на одной кнопке не затыкается (видимо на той, то висит на PINB.3 - тут цепочка команд проверки наиболее длинная).

Один из вариантов решения п.3:

int main
{...
char oldValue = PINB;
...
while(1)
{newValue = PINB;
if (newValue != oldValue)
{oldValue = newValue;
if ((newValue & 0x01) == 0)...
else if ...
}
...

 

chav1961: Удивительно, что он еще хоть на одной кнопке не затыкается (видимо на той, то висит на PINB.3
Да, точно, на этой почти не затыкается (только частота падает немного)

chav1961: В конструкции if(i==116&(!(chet%2))) Вы уверены, что хотели написать один амперсанд, а не два?
Был уверен, а теперь нет Да, действительно надо && указать, это же проверка только если два условия ИСТИНА, а не равенство их лог.1. Блин, а с одним & тоже работало, но памяти на 0,3% больше отводилось. Как так? Спасибо, что заметили!

chav1961: Обнуление TCNT0 в обработчике прерываний бессмысленно.
А почему, ведь МК может команды исполнять в это время и в счетный регистр записывать тоже? Если записывать новые значения в TCNT0, то в vmlab-е частота генерации изменяется. Или с обработкой счетного и регистра конфигурации TCCR0 есть какие-то особенности в моем случае?

chav1961: int main
А что значит int перед main?

 

1. Особенностей работы с TCNT нет, оно бессмысленно как раз в Вашем случае - раз Вы попали в прерывание, значит, в TCNT уже ноль. А если и не ноль - не нужно сбивать счет
2. В соответствии со стандартом языка С функция main должна быть описана в виде: int main (int argc, char **argv) (вариант int main(int argc, char *argv[]) ). В принципе, если компилятор не заругался, можете на это наплевать (WinAVR, например, ругается). Для микроконтроллеров эти параметры никакого смысла не несут, поскольку программа вызывается на выполнение по вектору сброса, а не из операционной системы, которой на микроконтроллерах просто нет Просто я на С программирую не только на микроконтроллерах, вот ручки сами и пишут всякую фигню

 

chav1961: В соответствии со стандартом языка С функция main должна быть описана в виде: int main
В соответствии с тем-же стандартом, если тип опустить, то по умолчанию предполагается int
Можно void ещё попробовать ставить, чтобы компилятор не ругался.

 

Тогда понятно всё. ОК ;)

 

chav1961: раз Вы попали в прерывание, значит, в TCNT уже ноль. А если и не ноль - не нужно сбивать счет
Ну а вообще, менять значение регистра TCNT0 в обработчике прерывания не совсем уж "криминал" если надо, например, частоту таймера изменить или лучше это в основном цикле делать?

 

Можно TCNT менять где угодно, просто делайте это поаккуратнее, особенно при малых коэффициентах деления прескалера. Можно запросто набрать систематическую погрешность (если точность временнЫх интервалов важна), поскольку своими изменениями Вы вмешиваетесь в процесс счета.

 

chav1961: Можно запросто набрать систематическую погрешность (если точность временнЫх интервалов важна
Спасибо, буду иметь ввиду, это для меня просто неочевидно.