Здравствуйте, MySkuвчане! Герой нашего обзора — микроконтроллер Atmega8A-16PU. Я расскажу вам о программировании данного мк в интегрированной среде разработки CodeVisionAvr, помигаем светодиодом, рассмотрим плюсы и минусы работы в данной среде. Возможно, в дальнейшем это послужит для вас альтернативой уже ставшей «народной» Arduino. Если заинтересовались, гоу под cut.
Преамбула.
Так уж сложилось, что свое знакомство с мк я начал с Arduino. Мигал светодиодом, подключал различные датчики и шилды, делал различные проекты. Все работало, меня устраивало, однако хотелось чего-то большего. Подвернулся мне один проект, где участвует Atmega8A, под которую нужно самостоятельно написать прошивку. Именно он подтолкнул меня к изучению процесса программирования «голого» мк.
Итак, перед нами микроконтроллер фирмы Atmel, семейства AVR Atmega8A.
Технические характеристики:
Распиновка:
Тут находится
datasheet
Теперь для работы и программирования нужно подключить его к программатору по схеме:
К сожалению, я как сапожник — без сапог, сейчас под руками нет программатора, поэтому я буду использовать Arduino UNO для загрузки в мк готовой прошивки и настройки фьюзов. Достаточно лишь загрузить скетч «Arduinoisp» из папки примеров Arduino IDE и подключить по схеме:
Однако, у данного решения есть существенный недостаток, о котором расскажу чуть позже. Перед тем, как приступить к написанию программы в CodeVisionAvr (далее CvAvr), нам нужно определиться, на какой частоте будет работать наш мк. По умолчанию, с завода наш герой работает от внутреннего rc-генератора на частоте 1Мгц (с возможностью перенастройки на 2, 4, и 8Мгц). Поскольку внутренний rc-генератор калибруют на заводе при определенных условиях (точное напряжение, температура), то точность его работы в «полевых» условиях может отличаться от 3% до 10%. Для задач, где не нужна высокая точность тактирования, этим можно пренебречь, в остальных случаях лучше использовать внешний кварц. В своем проекте я использовал внешний кварц на частоту 8 Мгц. Теперь нам надо «объяснить» мк, что нужно работать от внешнего кварца. Делается это при помощи изменения фьюзов. Если пояснить «на пальцах», то это что то вроде БИОСа, как на материнской плате, где вы указываете режимы её работы, аналогично мы сообщаем мк, в каких режимах, помимо частоты, он должен работать. Вся информация будет храниться в энергонезависимой памяти.
О прошивке фьюзов я расскажу под спойлером, те, кто умеет это делать самостоятельно, могут листать дальше.
Дополнительная информация
Как же прописать эти самые фьюзы?! Для этого я использовал программу AvrDude, она бесплатна и легко найдется в интернете. Для того, чтобы правильно выставить фьюзы в соответствии с нужной частотой, смотрим datasheet, а можно и воспользоваться простым
он-лайн калькулятором.
Выставляем параметры, как на картинке.
Тут все просто:
Clock Source — задаем частоту (External Crystal 3 — 16 Mhz) от внешнего кварца.
Start-up Time — скорость старта мк после снятия RESET или подачи питания (16K CK + 4.1ms fast).
Ставим галку: Ext. Clock/RC Osc./Low-freq. Crystal: enable internal Capacitors (36 pF)
Internal R/C Osc.: leave unchecked! External Crystal: enable full swing (neccessary for >8 MHz).
Таким образом, мы получили Low Fuse 0xEF и High Fuse 0xC9. Отлично, полдела сделали. Теперь подключаем мк к Arduino UNO, а саму Arduino к компьютеру соответственно. Запускаем командную строку, переходим в папку с AvrDude. Далее вводим строку: avrdude -C avrdude.conf -c avrisp -P COM13 -b 19200 -p m8 -U lfuse:w:0xef:m -U hfuse:w:0xc9:m
Вот как это выглядит на картинке:
Разберем строку, которую ввели:
avrisp — это тип нашего ардуиноподобного программатора
COM13 — номер com порта, которым определяется наша Arduino в системе (в вашем случае его надо посмотреть в диспетчере устройств)
19200 — скорость com порта, оставляем как есть
m8 — указываем, что наш мк — Atmega8
-U lfuse:w:0xef:m -U hfuse:w:0xc9:m — тут указаны наши Low Fuse 0xEF и High Fuse 0xC9
Будьте
ВНИМАТЕЛЬНЫ !!, неправильно указанные Fuse могут привести к окирпичиванию мк (танцы с бубном по восстановлению нам не нужны).
Нажимаем «Ввод» и на выходе получаем результат, как на картинке:
Если не появилось никаких ошибок в процессе, то работа выполнена, наш мк теперь будет работать от внешнего кварца.
Очень подробно о фьюзах можно прочитать
тут и
тут, а так же используя поиск в google.
Теперь мы готовы приступить к программированию. Для себя я выбрал среду разработки CvAvr. Язык программирования будет отличается от «ардуиновского», в CvAvr он Си-подобный. Напишем наш первый Blink.
После установки и запуска среды воспользуемся мастером создания проектов. Выбираем «File» — «New» — «Project». На вопрос, будем ли мы использовать мастер, отвечаем утвердительно. Target AVR Chip Type указываем AT90, ATtity, ATmega.
Так выглядит мастер проектов:
На вкладке Chip выбираем ATmega8A, Clock 8.000000 Mhz. Переходим во вкладку Ports. Наш светодиод будет подключен к 14 выводу микроконтроллера, согласно распиновке — PB0. На вкладке выбираем Port B, Bit 0 переключаем с IN на OUT, т.е. переводим режим работы 14 ножки нашего мк на выход.
На этом работа мастера окончена. Выбираем «Program» — «Generate, Save and Exit». Сохраняем наш проект, например, под именем Blink.
Получим такую вот портянку
/*******************************************************
This program was created by the
CodeWizardAVR V3.12 Advanced
Automatic Program Generator
Chip type: ATmega8A
Program type: Application
AVR Core Clock frequency: 8.000000 MHz
Memory model: Small
External RAM size: 0
Data Stack size: 256
*******************************************************/
#include <mega8.h>
#include <delay.h>
// Declare your global variables here
void main(void)
{
// Declare your local variables here
// Input/Output Ports initialization
// Port B initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=Out
DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (1<<DDB0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=0
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);
// Port C initialization
// Function: Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRC=(0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (0<<DDC0);
// State: Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTC=(0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);
// Port D initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=(0<<CS02) | (0<<CS01) | (0<<CS00);
TCNT0=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=0xFFFF
// OC1A output: Disconnected
// OC1B output: Disconnected
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (0<<CS10);
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=0xFF
// OC2 output: Disconnected
ASSR=0<<AS2;
TCCR2=(0<<PWM2) | (0<<COM21) | (0<<COM20) | (0<<CTC2) | (0<<CS22) | (0<<CS21) | (0<<CS20);
TCNT2=0x00;
OCR2=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<TOIE0);
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=(0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
// USART initialization
// USART disabled
UCSRB=(0<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (0<<RXEN) | (0<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);
// 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<<ACIC) | (0<<ACIS1) | (0<<ACIS0);
SFIOR=(0<<ACME);
// ADC initialization
// ADC disabled
ADCSRA=(0<<ADEN) | (0<<ADSC) | (0<<ADFR) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (0<<ADPS1) | (0<<ADPS0);
// SPI initialization
// SPI disabled
SPCR=(0<<SPIE) | (0<<SPE) | (0<<DORD) | (0<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);
// TWI initialization
// TWI disabled
TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE);
while (1)
{
}
}
Тут ничего страшного нет, в проекте указаны режимы работы портов, таймеров, прерываний, USART, Analog Comparator, ADC, SPI и подключенных библиотек. Словом, все те параметры, которые мы указывали в мастере, все, кроме портов и чипа, у нас настроено по умолчанию. Основной цикл программы будем писать в while (1) { текст программы }. Т.к. мы работаем с PB0 (14 ножка), в цикле программы напишем:
while (1)
{
PORTB.0=1;
delay_ms (1000);
PORTB.0=0;
delay_ms (1000);
}
Тут мы устанавливаем высокий уровень на PB0, ждем 1 секунду и устанавливаем низкий уровень, затем цикл повторяется. Еще не забываем подключить библиотеку в начале проекта #include <delay.h>. Наша программа готова!!! Как видите, всё очень просто. Теперь выбираем «Project» — «Build All». Если ошибок допущено не было, то увидим отчет мастера:
Размер нашей программы составил 198 bytes, и занял 2.4% памяти мк.
Далее собираем схему:
Теперь переходим в папку с нашим проектом, заходим в папку «Debug», затем «Exe», там находится файл с расширением hex. В моем случае это blink.hex.
Остался последний шаг. Копируем этот файл в папку с AvrDude. Снова запускаем командную строку, переходим в нашу папку. Вводим строку avrdude -C avrdude.conf -c avrisp -P COM13 -b 19200 -p m8 -U flash:w:blink.hex
Так это выглядит на картинке:
Если все ввели правильно, жмем «Ввод»
Поздравляю! Работа выполнена, светодиод должен вам радостно мигать :)
Заключение.
В заключении хочу сказать о недостатке ардуиноподобного программатора, CvAvr его просто не поддерживает. Имея на руках, например, AVRISP mkII, выполнить прошивку фьюзов и загрузку программы можно непосредственно из CodeVisionAvr. Кстати, использовать графический интерфейс AvrDude доморощенный программатор то же отказался и работал только из командной строки.
С CodeVisionAvr я разобрался довольно быстро, в интернете полно текстовых и видео уроков. За пару недель освоил работу аппаратного ШИМ, прерываний, таймеров, работу с кнопками и подключение графического дисплея. Конкретно мне надо было сделать часть своего проекта: на Atmega8 организовать аппаратный 16-битный ШИМ, подключить 2 кнопки для его управления, а также выводить режимы его работы на графический дисплей, что с легкостью я и сделал :) Вот пара фото:
Дополнительная информация
Итоги в сравнении с Arduino:
+ Разобраться в CvArv не сложно т.к. есть мастер создания проектов;
+ Наличие подключаемых библиотек, их достаточно
много;
+ Быстрая компиляция;
+ Возможность симуляции проекта в Proteus, а так же отладки его силами встроенного debugger`а;
+ Размер программы в разы меньше. Стандартный Blink у нас занял 198 Байт, аналогичный скетч в Arduino IDE 1084 Байт + 2 Кб загрузчик;
+ Возможность реализовать режимы, которые нельзя сделать на Arduino. Например 16-битный ШИМ (вообще, на Arduino можно, но только с «костылями»);
+ Возможность применять для своих проектов мк типа ATtiny, ATmega там, где Arduino будет избыточен;
— Все же новичку начинать осваивать мк лучше с Arduino;
— Язык программирования отличается от ардуиновского processing`a;
— Библиотек к Arduino все же больше;
— CodeVisionAvr является платной программой, есть бесплатные версии с ограничениями;
Программируя «голый» мк в CodeVisionAvr, я получил огромный опыт работы в свою копилку. Изучение таймеров, регистров, режимов работы, архитектуры, чтение datasheet увеличит вашу квалификацию, расширит кругозор и откроет новые аспекты работы с микроконтроллерами.
В качестве бонуса прилагаю пару фото, когда разбирался с графическим жк-дисплеем, немного поигрался.
P.s. Много еще о чем хотел написать, но это уже получится не обзор, а огромная статья. Готов ответить на вопросы в рамках своей компетенции, в привате или комментариях. Очень много уроков по AVR можно подсмотреть
тут.
upd 25.01.2016 Хочу привести ссылку на
Geektimes, где рассматривается работа Arduino против прямого программирования «голого мк».
Можно взять готовый урок и просто из этого состряпать что то. Как это вяжется с тематикой сайта я не понимаю.
Вот так? —
Вы, я смотрю, здесь совсем недавно…
На сайте есть множество категорий товаров, не только женское бельё и безделушки, а обзоры на электронику здесь занимают весьма почётную нишу, людям такие обзоры нравятся. Меня вот например не интересуют обзоры чехольчиков и селфи-палок, но я же не набрасываюсь на людей с вопросом «а нафига оно здесь надо?» )))
Как правило обзоры содержат хотя бы немного обзора, а не забиваются с первых же слов уроком или еще чем то.
Вы как болельщик Спартака в секторе Зенита)
Где с хорошей ценой АТ89С51 и С55 найти бы?
иногда это облегчает задачу.
ЗЫ про вскрытие — шутка, если что
Я, вообще, ожидал более чёткой картинки…
Цитата с сайта: «чтобы группа энтузиастов смогла восстановить схему процессора из топологии». Вот они монстры то!
Спасибо.
Но попробуйте задать такие вопросы где-нить на хабре или радиокоте — забросают тапками:)
— Хабрахабр — для грамотных людей
— Хабрахабр — для спокойных людей
— Хабрахабр — не для правонарушителей
Здесь же, есть некоторый простор для безобразия)
На хабр — да, нужен инвайт, для написания комментов, и прочих «плюшек».
Хотя я немного удивлён, что у Вас, с Вашими то обзорами, его до сих пор нет…
С другой стороны — на mysku гораздо уютнее, нежели на хабре.
Иногда так и хочется откомментить кого-то, но увы, пару моих статей не приняли(
а сцайт и правда катится в сраное гавно, даже фильтр не помогает, потому что я подписан на самопальные рубрики
у меня тоже полно всякого мелкого гавна, но даже в голову не приходит выкладывать тут
а вот обзор трусов и палок вполне подходит, товары широкого потребления
вчера например в ютубе видел обзор палки со стабилизатором камеры
мне не нужно, но посмотрел с интересом
На ардуине или msp430 например, если собираешь проект, работающий
от аккумуляторов, то благодаря АЦП можно замерить напряжение, и уже
затем вывести уровень заряда на какой-нибудь экранчик.
А вот что такое АПЦ — уже затруднюсь ответить:)
Или к этой однобаксовой микросхеме ещё и винду за 100$ докупать нужно?
если очень хочется можно даже с оригинального образа поставить и даже не крякать, работать будет, если вы такой зануда…
ЗЫ. Мне три версии винды за 8 лет обошлись в 150 баков
А посоветуйте патриотическую ось?
ЗЫ. Воруют в таком случает не у пиндосов, а у наших работников мелкософта
rupts, инцидентщики, партнёры, аутсорсеры — все наши.
Я прост увидел в обзоре скрины из винды и знаю, что она денег стоит.
А сам то Linux юзаю на дом. компах, вот и спросил…
А вообще Атмеги 8 зачастую хватает для большинства несложных проектов, поэтому её в основном и использую. Вот например:
В этом устройстве тоже стоит Атмега8, да и во многих вещах ее до сих пор активно используют.
А вот то, что они потом спрашивают на форуме — как подключить светодиод к микроконтроллеру, очень печально :(
Программы я писать не умею, кстати, вообще.
Прогресс не остановишь на Земле!
В отместку Intel и другим засранцам
Мы сделаем процессор на реле!