Осваиваем микроконтроллеры, часть 1

Данный урок предназначен для тех, кто хочет приобщиться к созданию устройств на микроконтроллерах. Стоит заранее сказать, что это гораздо проще, чем кажется.

 

Что представляет из себя микроконтроллер?

Контроллер ATmega 16A

Контроллер ATmega 16A — типичный контроллер фирмы Atmel

Микроконтроллер по сути — очень маленький компьютер, умещённый в одну микросхему. С его помощью можно как управлять подключенными к контроллеру устройствами (например дисплей, двигатель, светодиод), так и принимать для обработки сигналы с других устройств (например кнопок, датчиков температуры и влажности). Обработка данных и управление устройствами ведутся согласно записанной в память контроллера программы, а написание программы — одна из задач нашего урока.

 Практически для любого языка программирования есть наиболее простая программа, с которой принято начинать своё обучение. Для микроконтроллеров самое простое что можно сделать — поморгать светодиодом.

Для этого нам потребуются:

контроллер Attiny 13A ATTUNY 13
ISP программатор

ISP программатор

Источник питания (от 1.8 до 5.5 Вольт)  CR2032 батарейка
Провода  Провода
Макетная плата  Макетная плата
Светодиод АЛ307
Резистор на 150 Ом Резистор 150 Ом

 

Пишем свою первую программу для контроллера

Можно конечно для написания программ пользоваться ассемблером, можно писать программы под микроконтроллеры, используя блокнот и WinAVR, компилируя свои труды из командной строки, но есть более простые средства. Одним из них является CodeVisionAVR. Он поможет нам быстро и просто стартовать — сгенерирует за нас начальный код программы и скомпилирует его для нашего устройства.

CVAVR

Окно программы CVAVR

 

Создадим новый проект:

titor_step1

 

 

 

Конечно, мы используем помощника создания проекта

titor_step2

 

Наш контроллер (ATtiny 13A) принадлежит к семейству ATtiny, что отражено в его названии. Соответственно выбираем

titor_step3

 

Выбираем модель нашего устройства и частоту, на которой оно будет работать 

 titor_step4

 

Также сейчас нас интересует раздел «Порты». Здесь можно установить, является ли ножка микросхемы входом или выходом, т.е. будем ли мы принимать информацию или передавать. Нам надо моргать одним светодиодом, поэтому я установил на порте B нулевой бит как выход (Out) и выставил ему значение по умолчанию 0. Остальные ножки микроконтроллера мы сейчас использовать не будем, поэтому больше ничего не меняем.

titor_step5

 

Генерируем проект и выходим из мастера.

titor_step6

 

Нам предложат придумать названия для всех файлов, создаваемых при генерации, назовём их по порядку:

  1. tutor_1.c
  2. tutor_1.prj
  3. 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);//подождали

      }

}

 

С программированием закончили, надо скомпилировать наши старания:

titor_step7

Информационное окошко покажет, есть ли ошибки в вашем проекте. В данном случае, компиляция прошла без ошибок.

titor_step8

 

 

Далее, необходимо записать нашу программку в память контроллера. Для этого нам понадобится специальное устройство — программатор. Я пользуюсь примерно таким, только самодельным.

310469409_155[1]

 

Правильно подключить к программатору нашу микросхему нам поможет  документация на микроконтроллер и картинка, показывающая расположение выводов на программаторе. Подключаем одноимённые выводы друг к другу, для удобства я использовал для подключения к микросхеме специальную панельку:

avr_isp[1]IMG_0971

 

Нам понадобится специальная программа для общения компьютера с программатором и заливки нашей программы в память контроллера. Я предпочитаю SinaProg. Скачать её вы можете здесь — SinaProg 2.1.1

 Открываем программу, ищем папку, в которой лежит наш скомпилированный файл (на скриншоте ниже можно увидеть путь по умолчанию).

titor_step9 titor_step10

Для того, чтобы прошить наш контроллер, кликаем в разделе Flash на кнопку Program.

titor_step11

Собираем наше устройство согласно схеме. В этом нам поможет принципиальная схема и документация на микроконтроллер.

sceme

На видео нет резистора R1, который есть на схеме. Всё дело в том, что я использовал довольно сильно севшую батарейку, да и резистора нужного номинала у меня не было. Этот резистор ограничивает ток через диод. Без него можно угробить микросхему и диод.

И вот, мы собрали наше первое устройство на контроллере, поздравляю!

3 комментария

  1. Алекс написал:

    Не плохо, продолжай дальше выкладывать новые проекты, все толково.

  2. visitor написал:

    Источник тока: ток измеряется в амперах, а не в вольтах. А батарея — это источник напряжения!
    В программе куча всякого (типа #pragma optsize+). Слабо это объяснить?

    • admin написал:

      #pragma optsize это директива, связанные с оптимизацией кода по размеру. А по поводу источника тока — поправил.
      Не вижу смысла на данном этапе разбирать данный код досконально — большая часть его сгенерирована и лезть туда сейчас для мигания светодиодом не необходимо.

Оставить комментарий

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

19 + шесть =