Урок 1 — Структура проекта, директива #DEFINE и типы переменных

В этой части краткого курса, мы рассмотрим как строится проект на си для AVR, макроопределения в проекте и возможные типы используемых переменных.
Приступимс…
Для освоения этого урока вам понадобится немного терпения, внимательности, ПИВО и можно немного мозгов. Людям без мозгов потребуется больше пива, а возможно и водка.

И так, минимальная программа на си выглядит так:
main() { };
Но она не очень интересная и к тому же, ничего он делать не будет.
Приблизительная структура проекта состоит из таких пунктов:
1. Подключение заголовочного файла микроконтроллера;
2. Подключение заголовочных файлов необходимых библиотек;
3. Макроопределения проекта;
4. Глобальные переменные проекта;
5. Функции обработчиков прерывания;
6. Пользовательские функции;
7. Функция main().
Пункты 7 единственны обязательный пункт, в структуре проекта.

Заголовочные файлы МК и файлы библиотек обычно подключаются так:
#include <mega328p.h> //подключили заголовочный файл МК Atmega328P
#include <delay.h> // Подключили библиотеку задержек
Если вы создаёте проект в CVAVR ,используя, мастер начального кода, — то файл МК сам пропишется в проекте.

Далее у нас идут макроопределения, а в частности директива #define.
Это нереально удобная штука! И записывается она так:
#define Значение_1 Значение_2
Здесь Значение_2 заменяется на Значение_1 везде где встретится в проекте!
Например:
#define BUTON_OK PINB.0
Здесь мы определили что PINB.0 будет «маскироваться» под название BUTON_OK .
Это что касается удобства название, но это не все!
Представьте себе, вы пишите проект, долго и нудно пишите — в котором используется некая константа 666, скажем, прописана она в 50 строках кода!
Представили??
— А теперь представьте что после отладки устройства вам необходимо изменить её значение на другое!!!
— Вот же неудача, да? Но воспользовавшись, директивой #define мы могли бы записать так:
#define KONSTANTA 666
А в строках естественно использовать слово KONSTANTA.
И теперь чтобы изменить значение в 50 строках – нужно сделать одно изменение напротив директивы. Имена могут быть любыми, — лишь бы они не конфликтовали с зарезервированными именами и названиями портов.
Так же под макроопределения можно маскировать функции:
#define FUNKCIAY read_adc(1);
Многострочные определения:
#define STOP TCCR0B=0x00; //остановить таймер
#define GO TCCR0B=0x01 ; //запустить таймер
Есть ещё одна удобная директива — #if, #ifdef, #ifndef, #else, #ellif, #endif.
Все они используются для условной компиляции проекта.

Например:
#if условие 1
Какой ни будь код …при истинности условия 1
#elif условие 2
Какой ни будь код …при истинности условия 1
#else если не одно из условий
Какой ни будь код …
#endif конец условия

Для того чтоб наш проект работал и что то выполнял, — нам нужны переменные в которых мы будем хранить данные. Переменные бывают следующих типов и могут содержать в себе такие значения:
bit – битовая переменная, может содержать – 0 или 1;
char – знаковая переменная , от -128 до 127;
unsigned char –знаковая переменная, от 0 до255;
signed char – знаковая переменная , от -128 до 127;
int – целая знаковая переменная, от -32768 до 32767;
short int – целая знаковая переменная, от -32768 до 32767;
unsigned int – целая беззнаковая переменная, от 0 до 65535;
signed int – целая знаковая переменная, от -32768 до 32767;
long int – длинная целая знаковая переменная, от -2147483648 до 2147483647;
unsigned long int – беззнаковая целая длинная переменная, от 0 до 4294967295;
signed long int – длинная целая знаковая переменная, от -2147483648 до 2147483647;
float – переменная с плавающей запятой, от ±1.175e-38 до ±3.402e38;
double – переменная с плавающей запятой, от ±1.175e-38 до ±3.402e38.
Для переменных, так же, может быть определён формат:
extern — если переменная может использоваться в других файлах исходного кода программы;
volatile — ставьте если нужно предотвратить возможность повреждения содержимого переменной в прерывании, и не позволить компилятору попытаться выкинуть её при оптимизации кода;
пример:
volatile unsigned char x;
static — если переменная локальная т.е. объявлена в какой либо функции после скобки { и должна сохранять свое значение до следующего вызова этой функции;
register — разместить переменную в регистрах AVR — это может ускорить доступ к ней.
eeprom — разместить переменную в EEPROM. Это энергонезависимая память — значение таких переменных сохраняется при выключении питания и при перезагрузке МК.
пример:
eeprom unsigned int x;
Ну и на последок, пример простого проекта:
[c]
#include
#include

#define BTN PINB.0
#define OUT_LED PORTB.1

unsigned char t=0;

void main(void)
{
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
//нам нужно настроить порт В
DDRB.0 = 0; //сделали бит 0 порта В входом
PORTB.0 = 1; //включили подтягивающий резистор(внутрений) на бит 0 порта В
DDRB.1 = 1; //сделали бит 1 порта В выходом
PORTB.1 =0; //установили логичекий ноль на выходе
//будем зажигать и тушить светодиод по кругу
while (1)
{ //для этого используем оператор if

if(BTN==0) //проверяем значение пина где подключена кнопка
{ //если уровень опустился
delay_ms(500);//задержка
t++;//прибавили значение переменной
}

if(t==1){OUT_LED=1;} //проверяем значение t и если оно равно 1 — подаём единицу на выход
else{OUT_LED=0;} //иначе подаём ноль

if(t>1){t=0;} //проверяем значение t и если оно больше 1 — обнуляем его

}
}
[/c]
Соберём в Proteus небольшую схему.

1

В результате выполнения программы будет зажигаться светодиод – одно нажатие зажигает, — следующее выключает.
При первом нажатии кнопки(t=1).

3

При следующем нажатии(t=0).

2

Урок 1 — Структура проекта, директива #DEFINE и типы переменных: 2 комментария

  1. А ця стрічка
    if(t>1){t=0;} //проверяем значение t и если оно больше 1 — обнуляем его
    не має ТАК
    if(t>=1){t=0;} //проверяем значение t и если оно больше 1 — обнуляем егобути написана?

Добавить комментарий для AVL Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *