Здравствуйте, Сергей. Отвечаю на ваши вопросы:
1. Компилятор ругается на CS12 и TOIE1.
CS12 и TOIE1 - это стандартные имена битов в регистрах TCCR1B и TIMSK. Компилятор по ходу текста заменяет эти названия на их порядковые номера в регистре, руководствуясь строками заголовочных файлов mega16.h и(или) mega16_bits.h:
Code
#define CS12 2 // Prescaler source of Timer/Counter 1
#define TOIE1 2 // Timer/Counter1 Overflow Interrupt Enable
в итоге получается:
Code
TCCR1B|=(1<<2);
TIMSK|=(1<<2);
У меня установлен CVAVR v2.04.4a, вероятно в этой версии введены другие имена битов. Откройте указанные заголовочные файлы в директории C:\cvavreval\inc (возможно он там у вас вообще один) и уточните имена битов в регистрах TCCR1B и TIMSK. 2. Зачем писать TCCR1B|=(1<<CS12); вместо TCCR1B =0x04?
Можно писать и TCCR1B =0x04, но только, если вам не дорого состояние остальных битов в этом регистре, потому что такая запись сбрасывает их в ноль. Вы могли установить один из них в предыдущих командах, а в этой, сами того не заметив, сбросите. Первая запись использует операцию побитового логического “ИЛИ” и за счёт этого оставляет состояние остальных битов регистра неизменными (см. статью Операции с переменными и регистрами). Можно использовать и простое присвоение, но при этом всегда смотреть, не сбрасываете ли вы нужные биты, и это будет даже на пару тактов быстрее. На счёт читабельности не уверен, что из записи ADCSRA=0x8E легко понять какие именно биты здесь устанавливаются.
3. Зачем нам вообще нужен таймер для такой простой програмки?
На самые простые вопросы сложнее всего отвечать. Альтернатива задержки на таймере только одна – циклическая операция, например отнимания от огромного числа единицы в течение нужного времени. Использовать её значит гробить быстродействие фона программы, ведь пока она не пройдёт такую задержку не сможет делать ничего полезного разве что в прерываниях, а это очень важно для насыщенной программы.
Вообще говоря, для меня универсальный вариант организации задержек такой – запускаем таймер, вызывающий прерывания каждые 10 миллисекунд. Далее, если мы хотим организовать задержку в 100 мс, то записываем в некую переменную число 10 – Tmr=10; (это начало задержки) и в обработчике, каждые 10мс, отнимаем от него единицу – Tmr- -; пока она не станет равной нулю (это конец задержки). Если нужно реализовать ещё один интервал, например, в секунду используем ещё одну переменную Tmr2=100; и в обработчике делаем то же самое Tmr2- -; пока Tmr2 не равно нулю. Так, используя всего один таймер, можно реализовать любое количество задержек. Рекомендую сразу привыкать к таким решениям, а про задержки в виде пустых циклов забыть
4. Status – это переменная? Я ее должен объявить? Какой тип данных она должна хранить?
Status введён для управления последовательностью действий программы это просто признак текущего состояния; объявлен в приведённом мной исходнике, как переменная типа unsigned char (значения от 0 до 255).
Можете обозвать его так, как вам будет угодно. Если вы внимательно посмотрите на фон программы, то увидите, что там постоянно отслеживается текущее значение признака Status и выполняются необходимые действия.
Status=1; так мы даём понять фону, что сработал таймер и пора запускать АЦП на преобразование.
Status=3; указывает на то, что преобразование закончилось, результат скопирован в переменную AdcCode и можно приступать его обработке и отображению.
Status=2; позволяет больше не проходить по ветке соответствующей значению Status=1 иначе команда ADCSRA|=(1<<ADSC); будет выполняться многократно.
Status=0; также защитное значение - позволяет избежать повторных проходов по ветке обработки и отображения результата на ЖКИ.
P.S. В качестве полезного чтива по технической части очень рекомендую книгу "Микроконтроллры AVR семейств Tiny и Mega фирмы "ATMEL". Евстифеев А. В." Это фактически перевод DataSheet с хорошими пояснениями. Имея её, вы вряд ли будете нуждаться в чём-то ещё