Данный урок предназначен для тех, кто хочет приобщиться к созданию устройств на микроконтроллерах. Стоит заранее сказать, что это гораздо проще, чем кажется.
Что представляет из себя микроконтроллер?
Микроконтроллер по сути — очень маленький компьютер, умещённый в одну микросхему. С его помощью можно как управлять подключенными к контроллеру устройствами (например дисплей, двигатель, светодиод), так и принимать для обработки сигналы с других устройств (например кнопок, датчиков температуры и влажности). Обработка данных и управление устройствами ведутся согласно записанной в память контроллера программы, а написание программы — одна из задач нашего урока.
Практически для любого языка программирования есть наиболее простая программа, с которой принято начинать своё обучение. Для микроконтроллеров самое простое что можно сделать — поморгать светодиодом.
Для этого нам потребуются:
контроллер Attiny 13A | |
ISP программатор | |
Источник питания (от 1.8 до 5.5 Вольт) | |
Провода | |
Макетная плата | |
Светодиод | |
Резистор на 150 Ом |
Пишем свою первую программу для контроллера
Можно конечно для написания программ пользоваться ассемблером, можно писать программы под микроконтроллеры, используя блокнот и WinAVR, компилируя свои труды из командной строки, но есть более простые средства. Одним из них является CodeVisionAVR. Он поможет нам быстро и просто стартовать — сгенерирует за нас начальный код программы и скомпилирует его для нашего устройства.
Создадим новый проект:
Конечно, мы используем помощника создания проекта
Наш контроллер (ATtiny 13A) принадлежит к семейству ATtiny, что отражено в его названии. Соответственно выбираем
Выбираем модель нашего устройства и частоту, на которой оно будет работать
Также сейчас нас интересует раздел «Порты». Здесь можно установить, является ли ножка микросхемы входом или выходом, т.е. будем ли мы принимать информацию или передавать. Нам надо моргать одним светодиодом, поэтому я установил на порте B нулевой бит как выход (Out) и выставил ему значение по умолчанию 0. Остальные ножки микроконтроллера мы сейчас использовать не будем, поэтому больше ничего не меняем.
Генерируем проект и выходим из мастера.
Нам предложат придумать названия для всех файлов, создаваемых при генерации, назовём их по порядку:
- tutor_1.c
- tutor_1.prj
- tutor_1.cwp
После чего увидим окно программы со сгенерированным проектом. Полученный исходный код должен представлять из себя что-то такое:
/******************************************************* This program was created by the CodeWizardAVR V3.10 Advanced Automatic Program Generator © Copyright 1998-2014 Pavel Haiduc, HP InfoTech s.r.l. <p data-wpview-marker="http%3A%2F%2Fwww.hpinfotech.com">http://www.hpinfotech.com</p> Project : Version : Date : суббота 11.04.2015 Author : Company : Comments: Chip type : ATtiny13A AVR Core Clock frequency: 8,000000 MHz Memory model : Tiny External RAM size : 0 Data Stack size : 16 *******************************************************/ #include <tiny13a.h> // Declare your global variables here void main(void) { // Declare your local variables here // Crystal Oscillator division factor: 1 #pragma optsize- CLKPR=(1<<CLKPCE); CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0); #ifdef _OPTIMIZE_SIZE_ #pragma optsize+ #endif // Input/Output Ports initialization // Port B initialization // Function: Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=Out DDRB=(0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (1<<DDB0); // State: Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=0 PORTB=(0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0); // Timer/Counter 0 initialization // Clock source: System Clock // Clock value: Timer 0 Stopped // Mode: Normal top=0xFF // OC0A output: Disconnected // OC0B output: Disconnected TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00); TCCR0B=(0<<WGM02) | (0<<CS02) | (0<<CS01) | (0<<CS00); TCNT0=0x00; OCR0A=0x00; OCR0B=0x00; // Timer/Counter 0 Interrupt(s) initialization TIMSK0=(0<<OCIE0B) | (0<<OCIE0A) | (0<<TOIE0); // External Interrupt(s) initialization // INT0: Off // Interrupt on any change on pins PCINT0-5: Off GIMSK=(0<<INT0) | (0<<PCIE); MCUCR=(0<<ISC01) | (0<<ISC00); // Analog Comparator initialization // Analog Comparator: Off // The Analog Comparator's positive input is // connected to the AIN0 pin // The Analog Comparator's negative input is // connected to the AIN1 pin ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIS1) | (0<<ACIS0); ADCSRB=(0<<ACME); // Digital input buffer on AIN0: On // Digital input buffer on AIN1: On DIDR0=(0<<AIN0D) | (0<<AIN1D); // ADC initialization // ADC disabled ADCSRA=(0<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (0<<ADPS1) | (0<<ADPS0); while (1) { // Place your code here } }
Далее, находим строку 23. Здесь мы подключаем к программе библиотеки. Нам понадобится библиотека, с помощью которой мы сможем отмерять нашим микроконтроллером задержки между включением и выключением нашего светодиода. Называется она delay.h
Подключить её очень просто:
#include <tiny13a.h> #include <delay.h> // Declare your global variables here
Здесь и далее я привожу новые строки кода рядом с 2-3 старыми, чтобы легче было сориентироваться.
Продолжаем. Основная исполняемая часть программы записывается в бесконечно исполняющийся цикл. Включим светодиод, подождём 0.5 секунды, выключим светодиод, подождём… И так до бесконечности, пока не сядет батарейка.
while (1) { // Place your code here PORTB.0 = 1;//включили светодиод, порт B, первый разряд delay_ms(500);//подождали PORTB.0 = 0;//выключили delay_ms(500);//подождали } }
С программированием закончили, надо скомпилировать наши старания:
Информационное окошко покажет, есть ли ошибки в вашем проекте. В данном случае, компиляция прошла без ошибок.
Далее, необходимо записать нашу программку в память контроллера. Для этого нам понадобится специальное устройство — программатор. Я пользуюсь примерно таким, только самодельным.
Правильно подключить к программатору нашу микросхему нам поможет документация на микроконтроллер и картинка, показывающая расположение выводов на программаторе. Подключаем одноимённые выводы друг к другу, для удобства я использовал для подключения к микросхеме специальную панельку:
Нам понадобится специальная программа для общения компьютера с программатором и заливки нашей программы в память контроллера. Я предпочитаю SinaProg. Скачать её вы можете здесь — SinaProg 2.1.1
Открываем программу, ищем папку, в которой лежит наш скомпилированный файл (на скриншоте ниже можно увидеть путь по умолчанию).
Для того, чтобы прошить наш контроллер, кликаем в разделе Flash на кнопку Program.
Собираем наше устройство согласно схеме. В этом нам поможет принципиальная схема и документация на микроконтроллер.
На видео нет резистора R1, который есть на схеме. Всё дело в том, что я использовал довольно сильно севшую батарейку, да и резистора нужного номинала у меня не было. Этот резистор ограничивает ток через диод. Без него можно угробить микросхему и диод.
И вот, мы собрали наше первое устройство на контроллере, поздравляю!
Не плохо, продолжай дальше выкладывать новые проекты, все толково.
Источник тока: ток измеряется в амперах, а не в вольтах. А батарея — это источник напряжения!
В программе куча всякого (типа #pragma optsize+). Слабо это объяснить?
#pragma optsize это директива, связанные с оптимизацией кода по размеру. А по поводу источника тока — поправил.
Не вижу смысла на данном этапе разбирать данный код досконально — большая часть его сгенерирована и лезть туда сейчас для мигания светодиодом не необходимо.