Пункт 4. Объявление переменных
Перед использованием переменной в программе на Си её необходимо объявить - т.е. указать компилятору какой тип данных она может хранить и как она называется. Наиболее подробно об этом было сказано в предидущих параграфах. Ниже сжато - самое главное:
Формат объявления переменной таков:
[<storage modifier>] <type definition> <identifier>;
[<storage modifier>]- необязательный элемент, он нужен только в некоторых случаях и может быть:
extern- если переменная может использоваться в других файлах исходного кода программы, например объявляется во внешнем файле - хидере delay.hприведенном выше, а используется в основном файле программы.
volatile - ставьте если нужно предотвратить возможность повреждения содержимого переменной в прерывании, и не позволить компилятору попытаться выкинуть её при оптимизации кода.
пример:
volatile unsigned char x;
static- если переменная локальная т.е. объявлена в какой либо функции после скобки { и должна сохранять свое значение до следующего вызова этой функции.
register- разместить переменную в регистрах AVR - это может ускорить доступ к ней. Компилятлор по-умолчаниюразмещает переменные в регистрах до их заполнения.
eeprom- разместить переменную в EEPROM. Это энергонезависимая память - значение таких переменных сохраняется при выключении питания и при перезагрузке МК.
пример:
eeprom unsigned int x;
<type definition> - тип данных которые может хранить переменная.
наиболе часто используемые типы данных :
unsigned char- хранит числа от 0 до 255 (байт)
unsigned int - хранит числа от 0 до 65535 (слово == 2 байта)
unsigned long int - хранит от 0 до 4294967295 двойное слово == 4 байта)
Вместо unsigned char - можно писать просто char, так как компилятор по-умолчанию считает char без знаковым байтом.
А если вам нужен знаковый байт то объявляйте его так :
signed char imya_peremennoi;
<identifier> - имя переменной - некоторый набор символов по вашему желанию, но не образующий зарезервированные слова языка Си.
Выше был уже пример идентификатора - имени переменной: imya_peremennoi.
Принято использовать маленькие буквы, а для отличия имен переменных от названия функций - имена переменных можно напримерначинать с буквы, а названия функций (кроме main конечно) с символа подчеркивания.
Например так :
moya_peremennaya _vasha_funkziya
Глобальные переменные, а также локальные с модификатором static - при старте и рестарте программы равны 0 если вы не присвоили им (например оператором =) иное значение при их объявлении или по ходу программы.
Вот несколько примеров объявления переменных:
unsigned char my_peremen = 34;
unsigned int big_peremen = 34034;
Это объявлены две переменные и им присвоены значения.
Первая my_peremen - символьного типа - это 1 байт, она может хранить
число от 0 до 255. В данном случае в ней хранится число 34.
Вторая big_peremen - целого типа, два байта, в ней может хранится
число от 0 до 65535 , а в примере в неё поместили десятичное число 34034.
КОНСТАНТЫ.
flash и const ставятся перед объявлением констант - неизменяемых данных хранящихся во флэш памяти программ. Они позволяют вам использовать не занятую программой память МК. Обычно для хранения строковых данных - различные информационные сообщения, либо чисел и массивов чисел.
Примеры объявления констант
flash int integer_constant=1234+5;
flash char char_constant=’a’;
flash long long_int_constant1=99L;
flash long long_int_constant2=0x10000000;
flash int integer_array1[ ]={1,2,3};
flash int integer_array2[10]={1,2};
flash int multidim_array[2][3]={{1,2,3},{4,5,6}};
flash char string_constant1[ ]=”This is a string constant”;
const char string_constant2[ ]=”This is also a string constant”;
пункт 5
Описание функций-обработчиков прерываний.
/* В ЭТОЙ программе - есть только одно прерывание и значит одна функция обработчик прерывания.
Программа будет переходить на неё при возникновении прерывания :
ADC_INT - по событию "окончание АЦ преобразования" */
interrupt [ADC_INT] void adc_isr(void)
{
PORTB=(unsigned char) (~(ADCW>>2));
/* отобразить горящими светодиодами подключенными от питания МК через резисторы 560 Ом к ножкам порта_B старшие 8 бит результата аналого-цифрового преобразования Сделаем паузу 127 МСек - просто как пример пауз */
delay_ms(127);
В реальных программах старайтесь не делать пауз в прерываниях ! Обработчик прерывания должен быть как можно короче и быстрее. */
/* начать новое АЦПреобразование, установив в 1 бит 6 в регистре ADCSRA*/ ADCSRA|=0x40; } // закрывающая скобка обработчика прерывания
Эта строка означает следующее: - берем значение переменной ADCSRA (это регистр МК - значит программа прочитает его, возьмет число из него)
- выполняем с этим числом операцию обозначаемую вертикальной черточкой | ( это поразрядная операция ИЛИ) с числом 0x40
- присвоим или поместим результат поразрядного ИЛИ обратно в переменную ADCSRA - т.е. запишем результат в регистр ADCSRA
0x40 это в двоичном виде: 0100 0000
так как в результате поразрядного ИЛИ биты в ADCSRA напротив нулей не изменятся, а вот бит_6 в ADCSRA оказывается напротив "1" и теперь он станет "1" не зависимо от того каким он был до этого !
т.е. смысл рассматриваемой строки программы
ADCSRA|=0x40;
"установить" (т.е. сделать "1") бит_6 в регистре ADCSRA (флаг запуска АЦП)
Функция обработчик прерывания может быть названа вами роизвольно - как и любая функция кроме main.
Здесь она названа : adc_isr
При каком прерывании ее вызывать - компилятор узнает из строчки : interrupt[ADC_INT]
По первому зарезервированному слову - interrupt - он узнаёт, что речь идет об обработчике прерывания, а номер вектора прерывания (адрес куда физически, внутри МК перескочит программа при возникновении прерывания) будет подставлен вместо ADC_INT препроцессором компилятора перед компиляцией - этот номер указан в подключенном нами ранее заголовочном файле ("хидере") описания МК - mega16.h - это число сопоставленное слову ADC_INT.
Очень информативна следующая строка программы:
PORTB = (unsigned char) (~(ADCW >> 2));
Проанализируем как она работает.
Нужно вычислить выражение справа и поместить его в переменную PORTB. Вычислим что справа от оператора присваивания.
ADCW - это переменная слово (двухбайтовая величина - так она объявлена в файле mega16.h) в котором компилятор AVR сохраняет 10-битный результат АЦП - а именно в битах9_0 (биты с 9-го по 0-й) т.е. результат выровнен обычно - вправо.
Схема имеет только 8 светодиодов - следовательно нужно отобразить 8 старших бит результата - т.е. биты_9_2 - для этого мы сдвигаем все биты слова ADCW вправо на 2 позиции
ADCW >> 2 /* биты 1 и 0 выходят вправо из числа, бит_9 перемещается в позицию бит_7, бит_8 в позицию бит_6 и так далее до бит_2 становится бит_0 */
Теперь старшие 8 бит результата АЦП встали в биты 7_0 младшего байта слова ADCW.
>> n означает все биты числа сдвинуть вправо на n позиции. Это равносильно делению на 2 в степени n;
<< nозначает сдвинуть все биты влево на n позиции умножению на 2 в степени n.
|
Дата добавления: 2016-12-27; просмотров: 1877;