Ние програмираме avr. C програмиране - микроконтролери и технологии

Побитовите операции се основават на логически операции, което вече обсъдихме по-рано. Те играят ключова роля при програмирането на AVR и други видове микроконтролери. Почти никоя програма не може без използването на битови операции. Преди това съзнателно ги избягвахме, за да улесним процеса на изучаване на програмирането на MK.

Във всички предишни статии програмирахме само I/O портове и не използвахме допълнителни вградени възли, например таймери, аналогово-цифрови преобразуватели, прекъсвания и други вътрешни устройствабез които МК губи цялата си сила.

Преди да преминете към овладяването на вградените MK устройства, трябва да научите как да контролирате или проверявате отделни битове AVR MK регистрира. Преди това извършвахме проверка или задавахме цифрите на целия регистър наведнъж. Нека да разберем каква е разликата и след това да продължим.

Побитови операции

Най-често, когато програмирахме AVR микроконтролери, ние го използвахме, тъй като е по-визуален в сравнение с и е добре разбран за начинаещи MK програмисти. Например, трябва да зададем само 3-тия бит на порт D. За да направим това, както вече знаем, можем да използваме следния двоичен код:

PORTD = 0b00001000;

С тази команда обаче задаваме 3-та цифра на единица и нулираме всички останали (0, 1, 2, 4, 5, 6 и 7-ма) на нула. Сега нека си представим ситуация, при която 6-ти и 7-ми бит се използват като ADC входове и в този момент сигнал от някакво устройство се получава на съответните MK пинове и ние използваме горната команда, за да нулираме тези сигнали. В резултат на това микроконтролерът не ги вижда и смята, че сигналите не са пристигнали. Следователно, вместо такава команда, трябва да използваме друга, която да зададе само 3-тия бит на единица, без да засяга останалите битове. За да направите това, обикновено се използва следната побитова операция:

PORTD |= (1<<3);

По-долу ще обсъдим неговия синтаксис подробно. А сега още един пример. Да кажем, че трябва да проверим състоянието на 3-тата цифра на PIND регистъра, като по този начин проверим състоянието на бутона. Ако този бит се нулира, тогава знаем, че бутонът е натиснат и след това се изпълнява кодът на командата, който съответства на състоянието на натиснатия бутон. Преди това щяхме да използваме следната нотация:

ако (PIND == 0b00000000)

(всеки код)

С негова помощ обаче проверяваме не само 3-тия бит, а всички битове на PIND регистъра наведнъж. Следователно, дори ако бутонът е натиснат и желаният бит се нулира, но в този момент се получи сигнал на някой друг щифт на порт D, съответната стойност ще бъде зададена на единица и условието в скобите ще бъде невярно. В резултат на това кодът във фигурните скоби няма да бъде изпълнен дори когато бутонът е натиснат. Следователно, за да проверите състоянието на отделен 3-ти бит от регистъра PIND, трябва да се използва побитова операция:

ако (~PIND & (1<<3))

(всеки код)

За да работи с отделни битове на микроконтролера, езикът за програмиране C има инструменти, които могат да се използват за промяна или проверка на състоянието на един или повече отделни битове наведнъж.

Задаване на единичен бит

За да зададете единичен бит, като порт D, се използва побитова операция ИЛИ. Това е, което използвахме в началото на статията.

PORTD = 0b00011100; // първоначална стойност

PORTD = PORTD | (1<<0); применяем побитовую ИЛИ

PORTD |= (1<<0); // сокращенная форма записи

PORTD == 0b00011101; // резултат

Тази команда задава нулевия бит и оставя останалите непроменени.

Например, нека инсталираме още един 6-ти бит на порт D.

PORTD = 0b00011100; // първоначално състояние на порта

PORTD |= (1<<6); //

PORTD == 0b01011100; // резултат

За запис на един до няколко отделни бита наведнъж, например нулевия, шестия и седмия порт бПрилага се следната нотация.

PORTB = 0b00011100; // първоначална стойност

PORTB |= (1<<0) | (1<<6) | (1<<7); //

PORTB == 0b1011101; // резултат

Нулиране (нулиране) на отделни битове

За да нулирате един бит, се използват едновременно три обсъдени по-рано команди: .

Нека нулираме 3-тия бит на регистъра PORTC и оставим останалото непроменено.

PORTC = 0b00011100;

PORTC &= ~(1<<3);

PORTC == 0b00010100;

Нека извършим подобни действия за 2-ра и 4-та цифра:

PORTC = 0b00111110;

PORTC &= ~((1<<2) | (1<<4));

PORTC == 0b00101010;

Превключване на битове

В допълнение към настройката и нулирането се използва и полезна команда, която превключва един бит в противоположно състояние: едно към нула и обратно. Тази логическа операция се използва широко при конструирането на различни светлинни ефекти, например новогодишен гирлянд. Нека да разгледаме примера на PORTA

PORTA = 0b00011111;

PORTA ^= (1<<2);

PORTA == 0b00011011;

Нека променим състоянието на нулата, втория и шестия бит:

PORTA = 0b00011111;

PORTA ^= (1<<0) | (1<<2) | (1<<6);

PORTA == 0b01011010;

Проверка на състоянието на отделен бит. Нека ви напомня, че проверката (за разлика от писането) на I/O порт се извършва чрез четене на данни от PIN регистъра.

Най-често тестването се извършва чрез един от двата оператора за цикъл: if и while. Вече сме запознати с тези оператори по-рано.

Проверка на бита за наличие на логическа нула (нулиране) с ако

if (0==(PIND & (1<<3)))

Ако третият бит на порт D е изчистен, тогава се изпълнява Code1. В противен случай се изпълнява Code2.

Подобни действия се извършват с тази форма на запис:

ако (~PIND & (1<<3))

Проверка на бита за наличие на логическа единица (настройка) с ако

if (0 != (PIND & (1<<3)))

ако (PIND & (1<<3))

Горните два цикъла работят по подобен начин, но могат, поради гъвкавостта на езика за програмиране C, да имат различна форма на нотация. Операторът != означава не е равно. Ако третият бит на PD входно-изходния порт е зададен (един), тогава се изпълнява Code1; ако не, се изпълнява Code2.

Изчакване на бит за нулиране докато

докато (PIND & (1<<5))

Code1 ще се изпълнява, докато 5-ият бит на регистъра PIND е зададен. Когато го нулирате, Code2 ще започне да се изпълнява.

Изчаква се задаване на бит докато

Тук синтаксисът на C ви позволява да пишете код по два от най-често срещаните начини. На практика се използват и двата вида запис.

Реших да напиша кратка уводна статия за тези, които за първи път се занимават с програмиране на микроконтролери и никога преди не са били запознати с езика C. Няма да навлизаме в подробности, ще говорим за всичко малко, за да добием обща представа за работата с CodeVisionAVR.

По-подробна информация можете да намерите на английски в Ръководството на потребителя на CodeVision, а също така препоръчвам сайта http://somecode.ru с видео уроци по C за микроконтролери и книгата „Как да програмираме на C“ от Deitel, това е единствената добра книга, която знам, че съм започнала.

Нека започнем с факта, че каквито и действия да правим, в крайна сметка всичко се свежда до фърмуера на микроконтролера. Самият процес на фърмуера протича по следния начин: с помощта на определена програма се избира файл на фърмуера, избират се параметри, натиска се бутон и фърмуерът директно се флашва, което по същество е копие. Точно както копирате музика или документи от компютър на флаш устройство, физиката на процеса е същата.

Самият фърмуер има разширение .hex и представлява набор от инструкции, под формата на единици и нули, които са разбираеми за микроконтролера. Откъде мога да взема фърмуера? Можете да го изтеглите от уебсайтове за електроника или да го напишете сами. Можете да го напишете в специални програми, наречени среда за разработка. Най-известните ми са AVR Studio, IAR, CodeVision, WinAVR... Невъзможно е да се каже коя от тези среди е по-добра или по-лоша, всеки сам. Можем да кажем, че тези програми се различават основно по удобство, програмен език и цена. В рамките на този сайт се взема предвид само CodeVision.

Подредихме средата, сега нека да разгледаме процеса на писане на фърмуер. В CodeVision първо трябва да създадете проект. Може да бъде създаден с помощта на съветника за код или празен. Във всеки случай трябва да изберете вида на използвания микроконтролер и да посочите неговата честота. Когато използвате съветника, ще бъдете помолени да изберете първоначални настройки и да генерирате изходен код с настройките. След това ще се появи прозорец, в който можете да редактирате този код. Въпреки че можете да напишете своя изходен код в Notepad и след това да го прикачите към проекта в настройките.

Файлът с изходен код е набор от команди на език за програмиране, задачата на CodeVision е да преведе тези команди в двоичен код, вашата задача е да напишете този изходен код. CodeVision разбира езика C, файловете с изходен код имат разширение „.c“. Но CodeVision има някои конструкции, които не се използват в C, поради което много програмисти не го харесват и използваният език се нарича C-подобен. Това обаче не пречи да пишете сериозни проекти. Много примери, генератор на код и голям набор от библиотеки дават голямо предимство на CodeVision. Единственият минус е, че е платен, въпреки че има безплатни версии с ограничение на кода.

Изходният код трябва да съдържа заглавие с вида на използвания микроконтролер и основната функция. Например се използва ATtiny13

#включи void main(void) ( ) ;

#включи void main(void) ();

Преди основната функция можете да свържете необходимите библиотеки, да декларирате глобални променливи, константи и настройки. Библиотеката е отделен файл, обикновено с разширение „.h“, който вече съдържа предварително написан код. В някои проекти може да имаме нужда от този код, но в други нямаме нужда от него. Например в един проект използваме LCD дисплеи, а в друг не. Можете да свържете библиотеката за работа с LCD дисплей “alcd.h” така:

#включи #включи void main(void) ( ) ;

#включи #включи void main(void) ();

Променливите са области от паметта, в които могат да бъдат поставени определени стойности. Например, ако съберете две числа, трябва да запишете резултата някъде, за да го използвате в бъдеще. Първо трябва да декларирате променливата, т.е. разпределете памет за него, например:
int i=0;
тези. декларирахме променливата i и поставихме стойност 0 в нея, int е типът на променливата или по-просто казано, това означава размерът на разпределената памет. Всеки тип променлива може да съхранява само определен диапазон от стойности. Например, int може да се запише като числа от -32768 до 32767. Ако трябва да използвате числа с дробна част, тогава променливата трябва да бъде декларирана като float; за символи използвайте типа char.

bit, _Bit 0 или 1 char от -128 до 127 unsigned char от 0 до 255 int от -32768 до 32767 unsigned int от 0 до 65535 long int от -2147483648 до 2147483647 unsigned long int от 0 до 4294967295 float от ±1. 1 75e- 38 до ±3.402e38

Вътре в основната функция основната програма вече работи. След като изпълни функцията, програмата ще спре, така че те правят безкраен цикъл while, който повтаря една и съща програма постоянно.

void main(void) ( while (1) ( ) ; ) ;

void main(void) ( while (1) ( ); );

Можете да напишете коментар във всяка част от изходния код; това няма да повлияе по никакъв начин на работата на програмата, но ще ви помогне да правите бележки върху написания код. Можете да коментирате ред с две наклонени черти //след което компилаторът ще игнорира целия ред или няколко реда /**/, например:

/*Основни математически операции:*/ int i= 0; //декларираме променливата i и й присвояваме стойност 0//Събиране: i = 2 + 2 ; //Изваждане: i = 2 - 2 ;//след изпълнението на този израз, променливата i ще бъде равна на 0 //Умножение: i = 2 * 2 ;//след изпълнението на този израз, променливата i ще бъде равна на 4 //Делене: i = 2 / 2 ;

//след изпълнението на този израз, променливата i ще бъде равна на 1

/*Основни математически операции:*/ int i=0; //декларираме променлива i и й присвояваме стойност 0 //Добавяне: i = 2+2; //след изпълнението на този израз, променливата i ще бъде равна на 4 //Изваждане: i = 2-2; //след изпълнението на този израз, променливата i ще бъде равна на 0 //Умножение: i = 2*2; //след изпълнението на този израз, променливата i ще бъде равна на 4 //Делене: i = 2/2; //след изпълнението на този израз, променливата i ще бъде равна на 1

if(i>3) //ако i е по-голямо от 3, тогава присвоете на i стойността 0 ( i=0; ) /*ако i е по-малко от 3, тогава отидете на кода, следващ тялото на условието, т.е. след скоби ()*/

Също така if може да се използва заедно с else - иначе

ако (i<3) //если i меньше 3, то присвоить i значение 0 { i=0; } else { i=5; //иначе, т.е. если i больше 3, присвоить значение 5 }

Има и оператор за сравнение “==”, който не трябва да се бърка с “=” assign. Обратната операция не е равна на "!=", да речем

if(i==3)//ако i е 3, присвоете i стойността 0 ( i=0; ) if(i!=5) //ако i не е 5, присвойте i стойността 0 ( i=0; )

Нека да преминем към по-сложни неща - функции. Да приемем, че имате определена част от кода, която се повтаря няколко пъти. Освен това този код е доста голям по размер. Неудобно е да го пишете всеки път. Например, в програма, която по някакъв начин променя променливата i, когато натиснете бутони 0 и 3 на порт D, се изпълнява същия код, който в зависимост от стойността на променлива i включва краката на порт B.

void main(void) ( if (PIND.0== 0 ) //проверете дали бутонът на PD0 е натиснат( ако (i== 0 ) //ако i==0 разреши PB0( PORTB.0= 1 ; ) ако (i== 5 ) // ако i==5 разреши PB1( PORTB.1= 1 ; ) ) … ако (PIND.3== 0 ) // направете същото, когато проверявате бутона PD3( if (i== 0 ) ( PORTB.0= 1 ; ) if (i== 5 ) ( PORTB.1= 1 ; ) ) )

void main(void) ( if(PIND.0==0) //проверете дали бутонът на PD0 е натиснат ( if(i==0) //if i==0 включете PB0 ( PORTB.0=1; ) if( i==5) // if i==5 включете PB1 ( PORTB.1=1; ) ) ... if(PIND.3==0) // направете същото, когато проверявате бутона PD3 ( if(i==0 ) ( PORTB.0=1; ) if(i==5) ( PORTB.1=1; ) ) )

Като цяло кодът не е много голям, но може да бъде многократно по-голям, така че би било много по-удобно да създадете своя собствена функция.
Например:

void i_check() ( if (i== 0 ) ( PORTB.0= 1 ; ) if (i== 5 ) ( PORTB.1= 1 ; ) )

void i_check() ( if(i==0) ( PORTB.0=1; ) if(i==5) ( PORTB.1=1; ) )

void означава, че функцията не връща нищо, повече за това по-долу i_check() - това е името на нашата функция, можете да я наричате както искате, аз я нарекох точно така - проверете i. Сега можем да пренапишем нашия код:

void i_check() ( if(i==0) ( PORTB.0=1; ) if(i==5) ( PORTB.1=1; ) ) void main(void) ( if(PIND.0==0 ) //проверява дали бутонът на PD0 е натиснат ( i_check(); ) ... if(PIND.3==0) ( i_check(); ) )

Когато кодът достигне ред i_check(); след това ще скочи във функцията и ще изпълни кода вътре. Съгласете се, кодът е по-компактен и по-ясен, т.е. функциите помагат да се замени един и същ код, само един ред. Моля, обърнете внимание, че функцията е декларирана извън основния код, т.е. преди основната функция. Можете да кажете защо имам нужда от това, но докато изучавате уроците, често ще срещнете функции, например изчистване на LCD екрана lcd_clear() - функцията не приема никакви параметри и не връща нищо, но изчиства екран. Понякога тази функция се използва почти на всеки друг ред, така че икономиите на код са очевидни.

Изглежда много по-интересно да се използва функция, когато тя приема стойности, например има променлива c и има функция сума, която приема две стойности от тип int. Когато основната програма изпълни тази функция, аргументите вече ще бъдат в скоби, така че "a" ще стане равно на две, а "b" ще стане равно на 1. Функцията ще бъде изпълнена и "c" ще стане равно на 3 .

int c= 0;

void sum(int a, int b) ( c= a+ b; ) void main(void ) (sum(2, 1) ; )

int c=0; void sum(int a, int b) ( c=a+b; ) void main(void) (sum(2,1); )

Една от най-често срещаните подобни функции е преместване на курсора върху LCD дисплея lcd_gotoxy(0,0); който, между другото, също приема аргументи - координати x и y.

Друг вариант за използване на функция, когато тя върне стойност, сега тя вече няма да бъде празна, нека подобрим предишния пример на функция за събиране на две числа:

int c= 0;

int sum(int a, int b) ( return a+ b; ) void main(void) ( с= sum(2, 1) ;)

int c=0; int sum(int a, int b) ( return a+b; ) void main(void) ( с=sum(2,1); )
Резултатът ще бъде същият като последния път c=3, но имайте предвид, че присвояваме на променливата „c“ стойността на функция, която вече не е void, но връща сумата от две числа от тип int. По този начин не сме обвързани с конкретна променлива „c“, което добавя гъвкавост при използването на функциите. Прост пример за такава функция е четене на ADC данни, функцията връща измерената стойност result=read_adc();. Нека приключим с функциите.
Общият брой на елементите на масива е посочен в квадратни скоби. Можете да присвоите стойността на третия елемент на променливата "c" по следния начин:
с=синус;
Моля, обърнете внимание, че номерирането на елементите на масива започва от нула, т.е. "c" ще стане равно на пет. Този масив няма синусов елемент!!!
Можете да присвоите стойност на отделен елемент по следния начин:
синус=10;

Може би вече сте забелязали, че CodeVision няма низови променливи. Тези. не можете да създадете променлив низ hello=”hello”; За да направите това, ще трябва да създадете масив от отделни знаци.

lcd_putchar(здравей); lcd_putchar(здравей); lcd_putchar(здравей);

и т.н.
Оказва се доста тромаво, тук на помощ идват циклите.
Например цикъл while

докато (PINB.0!=0) ( )

Докато не бъде натиснат бутона, не правете нищо - стартирайте празен цикъл.

Друг вариант е for цикълът

int i;< 6 ; i++ ) { lcd_putchar(hello[ i] ) ; }

за (i= 0; i<6;i++) { lcd_putchar(hello[i]); }

int i; за (i=0;i

Значението е абсолютно същото като това на while, добавят се само първоначалното условие i=0 и условието, което се изпълнява всеки цикъл i++. Кодът вътре в цикъла е максимално опростен.

След като напишете вашата програма, изходният код се компилира и ако няма грешки, ще получите желания фърмуер в папката на проекта. Сега можете да флашнете микроконтролера и да се насладите на работата на устройството.

Не трябва веднага да се опитвате да използвате цикли, масиви и функции във вашия фърмуер. Вашата основна задача е да накарате фърмуера да работи, така че го правете както ви е по-лесно и не обръщайте внимание на размера на кода. Ще дойде време, когато искате не само да напишете работещ код, но и да го напишете красиво и компактно. Тогава ще бъде възможно да се потопите в дебрите на езика C. За тези, които искат да овладеят всичко, отново препоръчвам книгата „Как да програмираме на C“, има много примери и задачи. Инсталирайте Visual Studio, създайте конзолно приложение win32 и практикувайте там до насита. Има много инструменти за разработка за програмиране на AVR микроконтролери, но най-популярният, несъмнено, е пакетът AVR студио . Причините за тази популярност са редица - това е безплатен пакет, разработен от компанията ATMEL

, съчетава текстов редактор, асемблер и симулатор. AVR Studio се използва и заедно с инструменти за отстраняване на грешки в хардуера. Тази статия използва примери, за да обсъди как да работите с пакета, което ще помогне на начинаещите програмисти бързо да разберат взаимодействието на отделните компоненти на AVR Studio.

Пакетът AVR Studio има солидна история на развитие, което се отразява в броя на съществуващите версии. В края на 2003 г. излезе версия 4.08, която има редица полезни допълнения, а в началото на 2004 г. беше пусната актуализация (Service Pack 1), добавяща поддръжка за трето поколение AVR контролери от семейството ATmega48. Производството на микросхеми от това семейство е планирано за втората половина на 2004 г.

Дистрибуцията на пакета и сервизния пакет могат да бъдат изтеглени от уебсайта www.atmel.com или можете да получите компактдиск с тази дистрибуция от руския дистрибутор на ATMEL.

Удобно е да се разгледа работата на пакета AVR Studio на всяка конкретна програма. Като илюстрация ще разгледаме създаването на проект за проста програма, която ще свети два светодиода на свой ред. За да бъдем конкретни, нека вземем микросхемата Atmega128и свържете два светодиода към щифтове 31 и 32 (това са битове 6 и 7 на порт D на чипа ATmega128). AVR контролериимат мощни изходни етапи, типичният ток на всеки изход е 20 mA, максималният изходен ток е 40 mA и това се отнася както за входящия, така и за изходящия ток. В нашия пример светодиодите са свързани чрез своите аноди към клемите на контролера, а катодите са свързани към земята чрез охлаждащи резистори. Това означава, че светодиодът свети чрез прилагане на „1“ към съответния щифт на порта. Схематичната диаграма е показана на фигурата. Диаграмата показва и два бутона, които ще се използват в една от програмите.

Тук е подходящо да направим кратко отклонение относно избора на типа микросхема за прост пример. Наистина, на пръв поглед може да изглежда странно защо е необходим такъв мощен кристал в 64-пинов пакет, където би била достатъчна 8-пинова микросхема ATtiny12? В този подход обаче има логика. Известно е, че почти всеки AVR контролер се базира на едно и също ядро. Като цяло контролерите се различават по капацитет на паметта, брой I/O портове и набор от периферни модули. Характеристиките на всеки конкретен контролер са обвързването на логически имена на I/O регистри към физически адреси, адреси на вектори за прекъсване, дефиниции на битове на портове и др. са описани във файлове с разширение .inc, които са включени в пакета AVR Studio. Следователно, използвайки конкретен тип кристал, можете да отстраните грешки в програмата както за самия него, така и за всеки младши кристал. Освен това, ако използвате най-стария кристал като кристал за отстраняване на грешки, днес това е ATmega128, можете да коригирате грешки в програмата за почти всеки AVR контролер, просто трябва да не използвате хардуерни ресурси, които целевият микроконтролер няма. По този начин, например, можете да дебъгвате програма на ATmega128, която ще бъде изпълнена на ATtiny13. В този случай изходният код ще остане почти същият, само името на включения файл ще се промени от 128def.inc на tn13def.inc. Този подход има и своите предимства. Например, „допълнителни“ I/O портове могат да се използват за свързване LCD индикатор, към който може да се изведе информация за отстраняване на грешки. Или използвайте вграден емулатор, който се свързва към JTAG порта на чипа ATmega128 (контролерът ATtiny13 няма такъв порт). По този начин можете да използвате една платка за отстраняване на грешки, на която е инсталиран „старшият“ AVR контролер, за да отстранявате грешки във всички новоразработени системи, естествено също базирани на AVR микроконтролери. Една от тези платки се нарича AS-megaM. Именно това беше използвано за създаване на примерните програми, дадени в статията. Това е универсален контролер с една платка, базиран на чипа ATmega128, който съдържа външна RAM памет, два порта RS-232, порт за свързване на LCD индикатор, вграден програматор и емулатор В JTAG ICE. Платката също така има място за разпояване на FLASH-ROM серия чип AT45в корпуси TSOP32/40/48 и серия двуканални DAC AD5302/ AD5312/ AD5322. Сега, след като обяснихте причините за използването на AVR чудовище за запалване на чифт светодиоди, можете да продължите напред.

Когато програмирате в средата на AVR Studio, трябва да изпълните стандартната последователност от действия:

  • компилация
  • Създаването на проект започва с избиране на лентата с менюта Проект\Нов проект. В прозореца „Създаване на нов проект“, който се отваря, трябва да посочите името на проекта (в нашия случай sample1) и името на файла за инициализация. След като щракнете върху бутона „Напред“, се отваря прозорецът „Избор на платформа за отстраняване на грешки и устройство“, където избирате платформата за отстраняване на грешки (симулатор или емулатор) и типа на микроконтролера.

    Можете да изберете един от предложените вътрешносхемни емулатори; имайте предвид, че всеки емулатор има свой собствен списък с поддържани чипове. За разглеждания пример ние избираме симулатора на AVR и чипа ATmega128 като платформа за отстраняване на грешки. След като щракнете върху бутона „Край“, виждаме реално работещите прозорци на пакета AVR Studio, които все още са празни. Трябва да поставите изходния текст на програмата в десния прозорец. Това може да стане по два начина, или чрез въвеждане на целия текст директно в прозореца на редактора, или чрез зареждане на съществуващ файл. По-долу е пълният текст на най-простата програма с коментари.

    ; Пример "LED Control"; написано за платката за разработка AS-MegaM; Честота на главния осцилатор 7.37 MHz; Светодиодите са свързани към щифтове PD6 и PD7 и чрез резистори към общия проводник. ; свързване на I/O описателен файл на чип ATmega128 .include "m128def.inc" ; стартиране на програмата start: ; първата операция е инициализация на стека; ако това не е направено, извикайте подпрограма или прекъсвайте; няма да върне контрола обратно; указателят към края на стека е настроен на последния адрес на вътрешната RAM - RAMEND ldi r16,low(RAMEND) out spl,r16 ldi r16,high(RAMEND) out sph,r16 ; за да управлявате светодиодите, свързани към щифтове PD6 и PD7, ; е необходимо тези заключения да бъдат обявени за празници. ; За да направите това, трябва да запишете „1“ в съответните битове на регистъра DDRD (DataDiRection) ldi r16,(1<<6) | (1<<7) out DDRD,r16 ; основной цикл программы loop: ldi r16,(1<<6) ; светится один светодиод out PORTD,r16 rcall delay ; задержка ldi r16,(1<<7) ; светится второй светодиод out PORTD,r16 rcall delay ; задержка rjmp loop ; повторение цикла; процедура задержки; примерно полсекунды при частоте 7,37 МГц; три пустых вложенных цикла соответственно delay: ldi r16,30 ; 30 delay1: ldi r17,200 ; 200 delay2: ldi r18,200 ; и еще 200 итераций delay3: dec r18 brne delay3 dec r17 brne delay2 dec r16 brne delay1 ret ; возврат в главную программу

    Един проект може да се състои от няколко файла, като един файл е определен като основен. Всички операции се извършват удобно с помощта на контекстния бутон на мишката. След свързване на изходния файл прозорците изглеждат така:

    Проектът се компилира с помощта на командата \Project\Build или чрез натискане на бутона F7. Процесът на компилиране се показва в прозореца „Изход“. Този прозорец може да бъде изваден с помощта на командата \View\Output.

    По принцип вече получихме изходен файл във формат .hex, който вече може да бъде зареден в микросхемата и светодиодите да мигат. Въпреки това, целта на статията е да покаже пълния цикъл на работа в средата на AVR Studio, така че преминаваме към етапа на отстраняване на грешки. Това става с командата \Debug\Start Debugging.

    Сега задаваме кварцовата честота на 7,3728 MHz в прозореца „Опции на симулатора“, за да измерим точно времето за изпълнение на програмата.

    Останалите опции трябва да се оставят непроменени. Сега можете да изпълните програмата стъпка по стъпка с помощта на мишката или бутона F11.

    Пакетът AVR Studio съдържа мощни инструменти за преглед и редактиране на състоянието на вътрешните регистри и входно/изходните портове на дебъгвания микроконтролер, както и времето за изпълнение на програмата. Те са достъпни през прозореца „I/O“.

    Всъщност количеството информация, налична през прозорците за преглед на AVR Studio, е толкова голямо, че за максимален комфорт трябва да използвате компютър в конфигурация с два монитора.

    За отстраняване на грешки в нашия пример, за достъп до битовете на порт D, трябва да разширим линията I/O ATMEGA128 и след това линията PORTD. Сега и трите регистъра на този порт, PORTD, DDRD и PIND, са видими. За да видите полетата Value, Bits и Address, ще трябва да разширите дясната граница на прозореца, изтласквайки прозореца с изходния текст на програмата.

    Сега, преминавайки през програмата стъпка по стъпка, можете да видите промените в текущите състояния на тези регистри в полето Bits. Възможно е бързо да се промени състоянието на всеки бит от регистрите на порта, като това може да стане или чрез писане на нов код в полето Стойност, или директно чрез щракване върху желания бит в регистъра.

    За самостоятелни упражнения се предлага следната програма, която се различава от предишната по това, че светенето на светодиодите се управлява от два бутона.

    ; Пример “Управление на светодиоди от бутони”; написано за платката за разработка AS-MegaM; Светодиодите са свързани към щифтове PD6 и PD7 и чрез резистори към общия проводник. ; бутони - на PE4 и PE5 .include "m128def.inc" ; започва основната програма: ; инициализация на стека ldi r16,low(RAMEND) out spl,r16 ldi r16,high(RAMEND) out sph,r16; инициализация на светодиоди ldi r16, (1<<6) | (1<<7) out DDRD,r16 ; инициализация выводов, к которым подключены кнопки (на вход) ; внутренние подтягивающие резисторы подключены; для этого в PORTE нужно установить соответствующие биты в единицы ldi r16,(1<<4) | (1<<5) out PORTE,r16 ; а в DDRE - в нули ldi r16,0 out DDRE,r16 ; бесконечный цикл forever: in r16,PINE ; теперь в r16 находится текущее "состояние" кнопок com r16 ; кнопка "нажимается" нулем, поэтому инвертируем регистр lsl r16 ; переносим биты 4,5 в позиции 6,7 lsl r16 ; и обновляем "показания" светодиодов andi r16,(1<<6) | (1<<7) out PORTD,r16 rjmp forever ; цикл выполняется бесконечно

    По този начин, използвайки примера на най-простите програми, са показани някои от възможностите на пакета AVR Studio. Трябва да разберете, че това е само първото запознанство, което ще ви позволи бързо да свикнете с основните команди на пакета. Междувременно възможностите на въпросния пакет са много по-широки. Например, тук можете да дебъгвате програми, написани на езици от високо ниво. По-специално, компилаторът ImageCraft C използва дебъгера на AVR Studio „като че ли е роден“. За да направите това, когато компилирате изходния код, трябва да зададете опцията за генериране на изходен файл във формат, съвместим с AVR Studio. В този случай става възможно отстраняването на грешки в изходните кодове.

    Друга от многото функции на пакета AVR Studio е възможността за свързване на външни програми. Например, за да извикате обвивката на програматора AS2 в схемата, трябва да извършите няколко прости операции.

    В менюто Инструменти на главния прозорец на AVR Studio изберете Персонализиране;

    В прозореца Персонализиране изберете Инструменти;

    Щракнете двукратно върху бутона на мишката или натиснете Insert на клавиатурата, добавете нова команда към списъка и я наименувайте „AS2 Programmer“;

    Посочете пътя до изпълнимия файл на програмиста, като го въведете директно в полето за въвеждане "Команда" или като щракнете върху бутона "..." вдясно от това поле;

    Сега елементът „AS2 Programmer“ се появи в менюто Инструменти.

    Инструментите на пакета AVR Studio 4.08 ви позволяват да свържете спомагателни програми - плъгини. Първият плъгин за AVR Studio е програма за графичен редактор, която опростява процеса на инициализиране на LCD дисплей, който може да се управлява директно от ATmega169 AVR контролера. Максималният логически размер на LCD индикатора е 100 сегмента; на всеки елемент от индикатора се присвоява бит в специален регистър на контролера. За да се опрости процедурата за присвояване на специфични битове на всеки сегмент, може да се използва горната програма.

    По време на посещение в „родината на AVR“ - норвежкия офис на ATMEL, един от авторите на статията разговаря с Ларс Квенилд, ръководител на групата за програмиране, която създаде и поддържа пакета AVR Studio. Този човек, класически програмист, с брада, облечен в пуловер и обути в сандали на чорапите, говори за перспективите за развитие на пакета. Следващата версия (4.09) ще включва интерфейс за нов вътрешносхемен емулатор - JTAGICE mkII (наричан още AT JTAGICE2), който ще замени AT JTAGICE през втората половина на годината. Този емулатор има две съществени разлики. От една страна е добавена поддръжка за нов еднопроводен интерфейс за отстраняване на грешки за младши AVR контролери, debugWIRE. Този интерфейс е интересен, защото не заема допълнителни пинове на микроконтролера за своята работа, тъй като използва Reset pin на микроконтролера за смяна! От друга страна (можете да приемете този израз буквално), емулаторът AT JTAGICE2 най-накрая ще има USB интерфейс за комуникация с компютър.

    Литература

    1. Материали от техническия семинар AVR Technical Training. Atmel. Норвегия. декември 2003 г.
    2. Николай Королев, Дмитрий Королев AVR микроконтролери от второ поколение: инструменти за разработчици. // Компоненти и технологии, 2003 г. № 7
    3. Микроконтролери AVR от второ поколение: нови хардуерни възможности // Компоненти и технологии. 2003. № 4.
    4. Николай Королев, Дмитрий Королев. AVR микроконтролери: голямо в малко. // Схема", 2001, № 5
    5. Николай Королев, Дмитрий Королев. Микроконтролери AVR: софтуер // Компоненти и технологии, 2000. № 4.
    6. Николай Королев. AVR: хардуер за разработчици // Компоненти и технологии, 1999 г. № 1
    7. Николай Королев. RISC микроконтролери от ATMEL //Chip-News 1998, № 2
    8. Николай Королев, Дмитрий Королев AVR: нови 8-битови RISC микроконтролери от ATMEL // Microprocessor Review, 1998, № 1

    Микроконтролерите (наричани по-нататък МК) твърдо влязоха в живота ни, можете да намерите много интересни схеми, които се изпълняват на МК. Какво не можете да монтирате на MK: различни индикатори, волтметри, домакински уреди (защитни устройства, превключващи устройства, термометри ...), метални детектори, различни играчки, роботи и др. Списъкът може да отнеме много време. Видях първата схема на микроконтролер преди 5-6 години в радио списание и почти веднага обърнах страницата, мислейки си „Все още няма да мога да го сглобя“. Наистина, по това време MK бяха много сложно и неразбрано устройство за мен; нямах представа как работят, как да ги флашвам и какво да правя с тях в случай на неправилен фърмуер. Но преди около година за първи път сглобих първата си схема на MK; това беше схема с цифров волтметър, базирана на 7 сегментни индикатора и микроконтролер ATmega8. Случи се така, че купих микроконтролер случайно, когато стоях в отдела за радиокомпоненти, човекът пред мен купуваше MK и аз също реших да го купя и да се опитам да събера нещо. В моите статии ще ви разкажа за AVR микроконтролери, ще ви науча как да работите с тях, ще разгледаме програми за фърмуер, ще направим прост и надежден програмист, ще разгледаме процеса на фърмуера и, най-важното, проблемите, които могат да възникнат не само за начинаещи.

    Основни параметри на някои микроконтролери от семейството AVR:

    Микроконтролер

    Флаш памет

    RAM памет

    EEPROM памет

    I/O портове

    U мощност

    Допълнителни параметри на AVR mega MK:

    Работна температура: -55…+125*С
    Температура на съхранение: -65…+150*С
    Напрежение на щифта RESET спрямо GND: максимум 13V
    Максимално захранващо напрежение: 6.0V
    Максимален I/O линеен ток: 40mA
    Максимален захранващ ток VCC и GND: 200mA

    Изводи на модела ATmega 8X

    Pinouts за ATmega48x, 88x, 168x модели

    Оформление на щифта за модели ATmega8515x

    Оформление на щифта за модели ATmega8535x

    Оформление на щифта за ATmega16, 32x модели

    Оформление на щифта за модели ATtiny2313

    В края на статията е приложен архив с таблици с данни за някои микроконтролери.

    MK AVR инсталация FUSE битове

    Не забравяйте, че програмиран предпазител е 0, непрограмиран е 1. Трябва да внимавате, когато настройвате предпазители; неправилно програмиран предпазител може да блокира микроконтролера. Ако не сте сигурни кой предпазител трябва да програмирате, по-добре е да мигате MK без предпазители за първи път.

    Най-популярните микроконтролери сред радиолюбителите са ATmega8, следвани от ATmega48, 16, 32, ATtiny2313 и др. Микроконтролерите се продават в пакети TQFP и DIP, препоръчвам на начинаещите да купуват в DIP. Ако купите TQFP, ще бъде по-проблематично да ги флашнете; ще трябва да закупите или запоите платката, защото краката им са разположени много близо един до друг. Съветвам ви да инсталирате микроконтролери в DIP пакети на специални гнезда, това е удобно и практично, не е нужно да разпоявате MK, ако искате да го презаредите или да го използвате за друг дизайн.

    Почти всички съвременни MK имат възможност за вътрешносхемно програмиране на ISP, т.е. Ако вашият микроконтролер е запоен към платката, тогава за да сменим фърмуера, няма да се налага да го разпояваме от платката.

    За програмиране се използват 6 пина:
    НУЛИРАНЕ- Вход MK
    VCC- Плюс захранване, 3-5V, зависи от MK
    GND- Общ проводник, минус мощност.
    MOSI- MK вход (информационен сигнал в MK)
    MISO- MK изход (информационен сигнал от MK)
    SCK- MK вход (тактов сигнал в MK)

    Понякога те също използват щифтове XTAL 1 и XTAL2; ако МК се захранва от външен осцилатор в ATmega 64 и 128, щифтовете MOSI и MISO не се използват за програмиране на ISP; свързан към пин PE0, а MISO към пин PE1. Когато свързвате микроконтролера към програмиста, свързващите проводници трябва да са възможно най-къси, а кабелът, преминаващ от програматора към LPT порта, също не трябва да е твърде дълъг.

    Маркировката на микроконтролера може да съдържа странни букви с цифри, например Atmega 8L 16PU, 8 16AU, 8A PU и др. Буквата L означава, че MK работи при по-ниско напрежение от MK без буквата L, обикновено 2,7V. Числата след тирето или интервала 16PU или 8AU показват вътрешната честота на генератора, който е в MK. Ако предпазителите са настроени да работят от външен кварц, кварцът трябва да бъде настроен на честота, която не надвишава максимума според листа с данни, това е 20 MHz за ATmega48/88/168 и 16 MHz за други atmegas.

    Задача: Нека разработим програма за управление на един светодиод. При натискане на бутона светодиодът светва и при отпускане изгасва.

    Първо, нека разработим схематична диаграма на устройството. I/O портовете се използват за свързване на външни устройства към микроконтролера. Всеки от портовете може да работи както като вход, така и като изход. Нека свържем светодиода към един от портовете и бутона към другия. За този експеримент ще използваме контролер Atmega8. Този чип съдържа 3 I/O порта, има 2 осем-битови и 1 шестнадесет-битов таймер/брояч. Също така на борда има 3-канален PWM, 6-канален 10-битов аналогово-цифров преобразувател и много други. Според мен микроконтролерът е чудесен за изучаване на основите на програмирането.

    За свързване на светодиода ще използваме линия PB0, а за четене на информация от бутона ще използваме линия PD0. Диаграмата е показана на фиг.1.

    Урок No2. LED превключване

    Урок No3. LED мига

    Урок No4. Ходови светлини

    Урок № 5. Ходови светлини с помощта на таймер

    Урок №6. Ходови светлини. Използване на прекъсвания на таймера

    Урок №7. Оператори за управление на битове

    Урок № 8. Внедряване на ШИМ

    Цифровите устройства, например, микроконтролерът може да работи само с две нива на сигнала, т.е. нула и едно или изключено и включено. По този начин можете лесно да го използвате за наблюдение на състоянието на натоварване, като например включване или изключване на светодиод. Можете също така да го използвате, за да управлявате всяко електрическо устройство, като използвате подходящите драйвери (транзистор, триак, реле и т.н.), но понякога се нуждаете от нещо повече от просто „включване“ и „изключване“ на устройството. Така че, ако искате да контролирате яркостта на LED (или лампа) или скоростта на DC мотор, цифровите сигнали просто не могат да го направят. Тази ситуация е много често срещана в цифровите технологии и се нарича Широчинно-импулсна модулация (PWM).

    Споделете