Как понять ассемблер для AVR
Всем добрый вечер! Веду свою трансляцию из уютного мира, который называется «ассемблер». Сразу поясню что тема касается микроконтроллеров AVR — и я пока ещё не знаю, пригодится ли этот пост тем, кто хочет использовать ассемблер для любой другой задачи. Дело в том, что я буквально несколько дней назад начал учить ассемблер с нуля — нужно сделать одно устройство — и я решил сделать в нём всё самостоятельно. Так вот — в один прекрасный день понял, что учить ассемблер абсолютно бесполезно! Ассемблер можно только понять! То есть всем тем, кто хочет программировать на ассемблере я настоятельно рекомендую детально вникнуть в то, каким образом ФИЗИЧЕСКИ работает микроконтроллер, а затем уже изучать тонкости команд.
Так вот, я пожалуй начну небольшой цикл статей, в которых буду с самого начала рассказывать как именно я понял те или иные вещи в программировании на ассемблере — думаю для тех, кто вообще не понимает что такое асм я буду как раз таким «переводчиком» с языка тех, кто в этом деле очень хорошо шарит.
Сразу скажу, что я более-менее вкурил эту тему с подачи DIHALT — поэтому эти статейки будут являться неким переводом с супер-пупер-ассемблерно-микроконтроллерного языка на язык понятный большинству людей. Ну а гуру надеюсь будут меня поправлять по ходу пьесы и если вдруг я что то объясню неправильно — то они поправят меня.
Итак первые выводы об ассемблере, которые я сделал пару дней назад, меня потрясли до глубины души — и я просидел за статьями DI HALT’а с 11 вечера до 5 утра — после чего лёг спать довольным и счастливым. Я понял суть программирования на ассемблере для микроконтроллеров.
Как же это объяснить ещё проще? Думаю нужно начать с самой сути.
***
Изначально не будем вдаваться в технические подробности (о них мы поговорим в следующей статье) — просто представьте, что есть 3 персонажа:
1. Микроконтроллер — это англичанин Стив, который приехал к русскому. Он идеально знает английский язык, но по-русски он вообще не понимает — ни единого слова. Только английский. Он проиграл в споре и обязался делать бесприкословно всё то, о чём его попросит русский.
2. Ассемблер — это переводчик Вася у которого мама англичанка а папа русский. Он знает идеально и английский и русский язык.
3.Мы —это русский, к которому приехал англичанин. Ну то есть мы это мы=) При этом мы идеально знаем русский язык и (. ) чуть-чуть английский — самую малость, со словариком.
***
Представьте такую ситуацию — англичанин сидит у Вас в комнате на стуле. А Вы сидите себе за компом и читаете этот пост, как вдруг у Вас внезапно открылась форточка! Вот ведь незадача! Ветер дует, занавеска превратилась в парус… Было бы неплохо закрыть! Но вот ведь как лень вставать со стула, снимать ноги с системника, запихивать их в тапочки, отставлять кружку с кофе(пивом) и идти бороться со стихией. И тут Вы внезапно осознаёте, что у нас то в комнате есть проспоривший англичанин, которого самое время погонять! И вы ему так мило говорите «Дружище! Закрой форточку пожалуйста, а потом можешь опять присесть на стул!» а он сидит, смотрит на вас с недоумением и ничего не делает! Можно конечно по щам надавать — но он же тогда всё равно вас не поймёт! Тогда Вы звоните своему другу-переводчику Василию — он приходит, и садится рядом с англичанином на стул. И вы говорите — Переведи: «Стив, пойди и закрой форточку, а потом обратно сядь на стул!» Переводчик переводит на английский — англичанин понимает и идёт закрывает форточку, а затем приходит и садится на стул.
В этом моменте нужно просто понять роль ассемблера в этой цепочке «Мы-Ассемблер-Контроллер»
То есть как бы что такое ассемблер все поняли? Тогда читаем дальше.
***
Так вот, представляем такую ситуацию. Васе говоришь — «Слушай, ну короче такое дело — я калькулятор дома забыл, раздели 56983 на 2 и скажи Стиву, чтобы он столько раз отжался на кулаках» и Вася на калькуляторе считает и говорит Стиву по-английски » Отожмись на кулаках 28491 раз» Это называется «ДИРЕКТИВА» — другими словами директива это задание для Васи, результат выполнения которой это действие Стива.
Есть другая ситуация — Вы говорите Васе «Скажи Стиву, чтобы он отжался 28491 раз» и Вася просто переводит Ваши слова на английский. Это называется ОПЕРАТОР
Всё просто — есть директива и есть оператор. Оператор — это Ваше прямое указание что делать Стиву — Вася тут только переводит Ваше требование на инглиш. А Директива — это задание для самого Васи — и Вася сначала делает то, что Вы ему сказали, а потом уже в зависимости от результата говорит Стиву что-либо.
Теперь мы будем мучать англичанина регулярно! Но предварительно нужно получше познакомиться с нашим переводчиком Васей. Нужно знать следующее — Вася всегда Вас слушается беспрекословно — что ему сказали, то он и делает. Васин калькулятор не имеет десятичных знаков — если вы глянете пример с отжиманиями то 56983 \ 2 = 28491.5 — но у Васи всё после запятой обрубается — и он видит только целое число — причём неважно там будет 28491.000001 или там будет 28491.9999999 — для Васи это один фиг будет 28491 в обоих случаях. Ничего не округляется. Ещё важная информация про Васю. Вася жесток — ему пофиг на то, что Стив затрахается отжиматься двадцать восемь тысяч раз. Ему сказали — Вася перевёл. Причём не только перевёл — но и заставил сделать то, что Вы попросили. Так что если Стив помрёт на двадцать три тысячи пятьсот тринадцатом отжимании — то это будет исключительно Ваша вина.
Собственно это пока что всё. В следующем посте будем копать глубже — пока же просто достаточно понять это. Просто представить эту ситуацию и понять что к чему, кто исполняет какую роль и чем директива отличается от оператора.
А дальше мы постараемся называть всё своими именами и примерно прикинуть как же ассемблер работает с микроконтроллером по взрослому.
- ассемблер
- ассемблер для начинающих
- микроконтроллеры
- микроэлектроника
- микроконтроллер
- микросхема
Названия месяцев в арабском языке
В арабских странах пользуются двумя календарями : григорианским и традиционным исламским календарем.
В исламском (лунном) календаре год состоит из 12 месяцев. Вот их названия (с соблюдением последовательности):
محرم Мухаррам муХ а ррам
صفر Сафар С а фар
ربيع الأول Рабиу-ль-Авваль рабиЪу-ль а УУаль
ربيع الثاني Рабиу-т-Тани рабиЪу- с — с а:ни
جمادى الأولى Джумада аль-Уля джума:да-ль-у:ля
جمادى الآخرة Джумада-ль-Ахыра джума:да-ль-а:хыра
رجب Раджаб р а джаб
شعبان Шаабан шаЪаба:н
رمضان Рамадан рамаДа:н
شوال Шавваль шаУУа:ль
ذو القعدة Зу-ль-Каада з у-ль-К а Ъада
ذو الحجة Зу-ль-Хиджа з у-льХ и джа
Примечание: месяц Джумада-ль-Ахыра может также называться جمادى الثانية джума:да- с-с а:нийя Джумада-т-Тания.
Год в исламском календаре на 10 дней короче, чем год по григорианскому календарю, поэтому начало лунного месяца ежегодно «сдвигается» относительно григорианского календаря. Нельзя назвать какой-либо исламский месяц «летним» или «зимним» – так как с течением лет этот месяц может быть и зимним, и летним, и осенним, и весенним. Тем более, нельзя строго привязывать исламские месяцы к месяцам григорианского календаря.
Изучайте арабский язык самостоятельно и бесплатно по видеоматериалам
Для желающих изучать арабский онлайн (Skype) — информация
В арабском языке используются два варианта названия месяцев григорианского календаря: европейские и традиционные. Европейский вариант названий напоминает названия месяцев в русском языке:
يناير январь йана:йир
فبراير февраль фибра:йир
مارس март ма:рис
أبريل апрель абри:ль
مايو май м а йу, м а йо
يونيو июнь й у нийу, й у нио
يوليو июль й у лийу, й у лио
أغسطس август аГ у сТус
سبتمبر сентябрь сибт а мбар
أكتوبر октябрь укт у бар, окт о бэр
نوفمبر ноябрь нуф а мбар, ноф э мбэр
ديسمبر декабрь дис а мбар, дис а мбэр
Январь كانون الثاني
© Фотография: Ирина Бегань
© الصور ة: إ يرينا بيغان
Традиционные арабские названия месяцев григорианского календаря:
كانون الثاني январь кану:н а с — с а:ни
شباط февраль шуба:Т
آذار март а з а:р
نيسان апрель ниса:н
حزيران июнь Хази:р а :н
تموز июль тамму:з
أيلول сентябрь айлу:ль
تشرين الأول октябрь тишри:н аль- а УУаль
تشرين الثاني ноябрь тишри:н а с — с а:ни
كانون الأول декабрь кану:н аль- а УУаль
В разговорном арабском языке также используют числительные для обозначения месяцев григорианского календаря. Примерно, как в русском языке дату 09.02.2012 можно прочитать «девятого-второго-двенадцатого», то есть месяц февраль в данном случае назван «вторым». В арабском языке это иногда делается, чтобы избежать путаницы с использованием различных вариантов названий. Январь становится «первым месяцем», апрель – «четвертым месяцем», декабрь – «двенадцатым месяцем».
شهر الأول январь ш а h р аль- а УУаль
شهر الثاني февраль ша h р а с — с а:ни
شهر الثالث март ша h р а с — с а:лэ с
شهر الرابع апрель ша h р ар-ра:бэЪ
شهر الخامس май ша h р аль-ха:мэс
شهر السادس июнь ша h р ас-са:дэс
شهر السابع июль ша h р ас-са:бэЪ
شهر الثامن август ша h р а с — с а:мэн
شهر التاسع сентябрь ша h р ат-та:сэЪ
شهر العاشر октябрь ша h р аль-Ъа:шэр
شهر الحادي عشر ноябрь ша h р аль-Ха:ди-Ъ а шар
شهر الثاني عشر декабрь ша h р а с — с а:ни Ъ а шар
Есть еще один вариант названий месяцев григорианского календаря, встречающийся только в разговорной речи и считающийся «простоватым». К слову الشهر аш-ша h р «этот месяц; конкретный месяц» прибавляется числительное. Например: аш-ша h р Уа:Хад «январь» (дословно: месяц «один»); аш-ша h р с и та «июнь» (дословно: месяц «шесть»); аш-ша h р иХда:ш «ноябрь» (дословно: месяц «одиннадцать»).
2 комментария
Рабиуль-авваль так же называют и как «Рабиуль-Ахыр» (по аналогии с Джумадаль Ахыра).
В прошлом моем комментарии была опечатка. Рабиуссаний так же называют и как «Рабиуль-Ахыр» (по аналогии с Джумадаль Ахыра).
12 месяцев года на русском языке
Сегодня темой нашего урока будет 12 месяцев года на русском языке. В этой статье мы с вами рассмотрим названия месяцев на русском языке, а также познакомим вас с 12 интересными русскими поговорками и пословицами, которые связаны с каждым месяцем года. Месяцы года на русском: Январь [yan-VAR’] January Февраль [fye-VRAL’] February Март [MART] March Апрель [ap-RYEL’] […]
Thank You!
Your submission has been received.
Order number
Oops! Something went wrong.
12 месяцев года на русском языке
Статьи на русском языке
Сегодня темой нашего урока будет 12 месяцев года на русском языке. В этой статье мы с вами рассмотрим названия месяцев на русском языке, а также познакомим вас с 12 интересными русскими поговорками и пословицами, которые связаны с каждым месяцем года.
Месяцы года на русском:
Январь [yan-VAR’] January
Февраль [fye-VRAL’] February
Март [MART] March
Апрель [ap-RYEL’] April
Май [MAY] May
Июнь [ee-YOON’] June
Июль [ee-YOOL’] July
Август [AV-goost] August
Сентябрь [syen-TYABR’] September
Октябрь [ok-TYABR’] October
Ноябрь [no-YABR’] November
Декабрь [dee-KABR’] December
Русские поговорки и пословицы о месяцах года:
В прошлых статьях мы говорили с вами о русских поговорках и пословицах, а также о том, что они составляют значительную часть русского языка, литературы и культуры. В русских поговорках и пословицах о месяцах обычно говорится о некоторых характеристиках каждого месяца и объясняется то, чем каждый месяц отличается от другого.
То, что мы представили ниже – лишь некоторая часть из многих известных высказываний, с которыми вы можете столкнуться, читая русскую литературу.
- Январь — году начало, зиме середина.
[Yan-VAR’ GO-doo na-CHA-la zee-MYE sye-rye-DEE-na]
January is the beginning of the year and the middle of the winter.
- Февраль силен метелью, а март капелью.
[Feev-RAL’ syee-LYON me-TYEL’-yoo a MART ka-PYEL’-yoo]
February is strong with blizzards and March with thawing.
- Март с водой, апрель с травой, а май с цветами.
[MART s vo-DOY ap-RYEL’ s tra-VOY a MAY s tsve-TA-mee]
March comes with water, April with grass, and May with flowers.
- В месяце апреле держи одежду ближе к телу
[V me-SYA-ce ap-RYEL-YE dze-RZHY a-dye-ZHDU blyee-ZHE k TYE-LOO]
Keep your clothes close to your body in the month of April.
- Как в мае дождь, так будет и рожь.
[Kak v MA-ye DOZHT’ tak ee BOO-det ROZH]
Rye crop depends on the rain in May.
- В июне солнце высоко, с утра до вечера далеко.
[V ee-YOO-nye soln-ce vy-sa-KO s oo-TRA do vye-che-RA da-LYE-KO]
In June, the sun is high, from morning to evening far.
[V Ee-YOO-lye na dvo-RYE poo-STO a v po-LYE goos-TA]
In July, the yard is empty, and in the field is dense.
- Август-батюшка заботой-работой мужика тешит.
[AV-goost BA-tyoosh-ka za-BO-tay ra-BO-tay moo-zhee-KA TYE-sheet]
Father-August keeps a man busy with jobs and things to take care of.
- В сентябре лето кончается, осень начинается.
[V seen-tyab-REE LYE-ta kan-CHA-eet-sya O-syen’ na-chee-NA-yet-sya]
In September summer is over and autumn begins.
- В октябре ни на колесах, ни на санях.
[V ak-tyab-RYE nee na ka-LYO-sah nee na sa-NYAH]
In October you can neither move on wheels, nor sledges.
[V na-yab-RYE zee-MA s O-seen’yoo BO-ryet-sya]
In November winter is fighting with autumn.
- Декабрь снежный и холодный — будет и год плодородный.
[Dee-KABR’ SNYEZH-niy ee ha-LOD-niy – BOO-deet ee GOT pla-da-ROD-niy]
If December is cold and snowy, the year will be rich with crops.
Надеемся вам понравился сегодняшний урок. Если у вас есть какие-либо вопросы или предложения, вы можете оставить комментарий ниже. Мы всегда будем рады вас выслушать!
You may be interested
News and interesting facts
Why do people speak Russian in Daugavpils?
Learn more
As it seems to us, Daugavpils is the best place to learn Russian now, because our city is situated in the EU and NATO, but at the same time 90% of the city’s population speak Russian at home.
Learn more
Research publications
ЭТЮД О ДВИНСКЕ
Learn more
Etude on Dvinsk by F.Fedorov
The Baltic region is one of the most catastrophe prone regions of the 2nd millennium, especially its second part; it is the centre of attraction of ‘geopolitical’ interests of the European world. Probably the most tragic fate has befallen to the eastern part of the present Latvia and its multi-titled town of Dinaburg – Dvinsk – Daugavpils. During its 730 years long history, the town went through five rather autonomous periods of development, five different lives (German, Polish, Russian, Latvian, Soviet), and at the beginning of the 1990s it entered into the 6th period.
The history of Dinaburg – Dvinsk – Daugavpils is the history of five attempts by the town to begin its life anew; and this is determined not only by the fact that the town was four times burned down and had to start life from scratch, but first and foremost because each of these periods was characterized by a total change of ethnos and the socio-cultural field.
The present article deals with the cultural space of the town in one of the most efficient periods of its development – from the 1860s till World War I.
Таймеры-счетчики. Прерывания
Сегодня мы узнаем, что такое таймеры-счётчики в микроконтроллерах и для чего они нужны, а также что такое прерывания и для чего они тоже нужны.
Таймеры-счётчики — это такие устройства или модули в микроконтроллере, которые, как видно из названия, постоянно что-то считают. Считают они либо до определённой величины, либо до такой величины, сколько они битности. Считают они постоянно с одной скоростью, со скоростью тактовой частоты микроконтроллера, поправленной на делители частоты, которые мы будем конфигурировать в определённых регистрах.
И вот эти таймеры-счётчики постоянно считают, если мы их инициализируем.
Таймеров в МК Atmega8 три.
Два из них — это восьмибитные таймеры, то есть такие, которые могут максимально досчитать только до 255. Данной величины нам будет маловато. Даже если мы применим максимальный делитель частоты, то мы не то что секунду не отсчитаем, мы даже полсекунды не сможем посчитать. А у нас задача именно такая, чтобы досчитывать до 1 секунды, чтобы управлять наращиванием счёта светодиодного индикатора. Можно конечно применить ещё наращивание переменной до определенной величины, но хотелось бы полностью аппаратного счёта.
Но есть ещё один таймер — это полноправный 16-битный таймер. Он не только 16-битный, но есть в нём ещё определённые прелести, которых нет у других таймеров. С данными опциями мы познакомимся позже.
Вот этот 16-битный таймер мы и будем сегодня изучать и использовать. Также, познакомившись с данным таймером, вам ничего не будет стоить самостоятельно изучить работу двух других, так как они значительно проще. Но тем не менее 8-битные таймеры в дальнейшем мы также будем рассматривать, так как для достижения более сложных задач нам одного таймера будет недостаточно.
Теперь коротко о прерываниях.
Прерывания (Interrupts) — это такие механизмы, которые прерывают код в зависимости от определённых условий или определённой обстановки, которые будут диктовать некоторые устройства, модули и шины, находящиеся в микроконтроллере.
В нашем контроллере Atmega8 существует 19 видов прерываний. Вот они все находятся в таблице в технической документации на контроллер
Какого типа могут быть условия? В нашем случае, например, досчитал таймер до определённой величины, либо например в какую-нибудь шину пришёл байт и другие условия.
На данный момент мы будем обрабатывать прерывание, которое находится в таблице, размещённой выше на 7 позиции — TIMER1 COMPA, вызываемое по адресу 0x006.
Теперь давайте рассмотрим наш 16-битный таймер или TIMER1.
Вот его структурная схема
Мы видим там регистр TCNTn, в котором постоянно меняется число, то есть оно постоянно наращивается. Практически это и есть счётчик. То есть данный регистр и хранит число, до которого и досчитал таймер.
А в регистры OCRnA и OCRnB (буквы n — это номер таймера, в нашем случае будет 1) — это регистры, в которые мы заносим число, с которым будет сравниваться чило в регистре TCNTn.
Например, занесли мы какое-нибудь число в регистр OCRnA и как только данное число совпало со значением в регистре счёта, то возникнет прерывание и мы его сможем обработать. Таймеры с прерываниями очень похожи на обычную задержку в коде, только когда мы находимся в задержке, то мы в это время не можем выполнять никакой код (ну опять же образно «мы», на самом деле АЛУ). А когда считает таймер, то весь код нашей программы в это время спокойно выполняется. Так что мы выигрываем колоссально, не давая простаивать огромным ресурсам контроллера по секунде или даже по полсекунды. В это время мы можем обрабатывать нажатия кнопок, которые мы также можем обрабатывать в таймере и многое другое.
Есть также регистр TCCR. Данный регистр — это регистр управления. Там настраиваются определенные биты, отвечающие за конфигурацию таймера.
Также у таймера существует несколько режимов, с которыми мы также познакомимся немного позденее.
Он состоит из двух половинок, так как у нас конотроллер 8-битный и в нем не может быть 16-битных регистров. Поэтому в одной половинке регистра (а физически в одном регистре) хранится старшая часть регистра, а в другом — младшая. Можно также назвать это регистровой парой, состоящей из двух отдельных регистров TCCR1A и TCCR1B. Цифра 1 означает то, что регистр принадлежит именно таймеру 1.
Даный регист TCCR отвечает за установку делителя, чтобы таймер не так быстро считал, также он отвечает (вернее его определённые биты) за установку определённого режима.
За установку режима отвечают биты WGM
Мы видим здесь очень много разновидностей режимов.
Normal — это обычный режим, таймер считает до конца.
PWM — это ШИМ только разные разновидности, то есть таймер может играть роль широтно-импульсного модулятора. С данной технологией мы будем знакомиться в более поздних занятиях.
CTC — это сброс по совпадению, как раз то что нам будет нужно. Здесь то и сравнивются регистры TCNT и OCR. Таких режима два, нам нужен первый, второй работает с другим регистром.
Все разновидности режимов мы в данном занятии изучать не будем. Когда нам эти режимы потребуются, тогда и разберёмся.
Ну давайте не будем томить себя документацией и наконец-то попробуем что-то в какие-нибудь регистры занести.
Код, как всегда, был создан из прошлого проекта. Для протеуса также код был скопирован и переименован с прошлого занятия, также в свойствах контроллера был указан путь к новой прошивке. Проекты мы назовем Test07.
Попробуем как всегда скомпилировать код и запустить его в протеусе. Если всё нормально работает, то начинаем добавлять новый код.
Добавим ещё одну функцию, благо добавлять функции мы на прошлом занятии научились. Код функции разместим после функции segchar и до функции main. После из-за того, что мы будем внутри нашей новой функции вызывать функцию segchar.
Мало того, мы создадим не одну функцию, а целых две. В одну функцию мы разместим весь код инициализации нашего таймеру, а другая функция будет являться обработчиком прерывания от таймера, а такие функции они специфичны и вызывать их не требуется. Когда возникнет необходимость, они вызовутся сами в зависимости от определённых условий, которые были оговорены выше.
Поэтому первую функцию мы назвовём timer_ini
void timer_ini ( void )
Также давайте наши функции, а также какие-то законченные блоки с объявлением глобальных переменных, с прототипами функций будем отделять друг от друга вот такими чёрточками, которые за счет наличия двух слешей впереди компилятор обрабатывать не будет и примет их за комментарии. За счёт этих отчерчиваний мы будем видеть, где заканчивается одна функция и начинается другая.
Данная функция, как мы видим не имеет ни каких аргументов — ни входных, не возвращаемых. Давайте сразу данную функцию вызовем в функции main()
unsigned char butcount=0, butstate=0;
timer_ini ();
Теперь мы данную функцию начнём потихонечку наполнять кодом.
Начнем с регистра управления таймером, например с TCCR1B. Используя нашу любимую операцию «ИЛИ», мы в определённый бит регистра занесём единичку
void timer_ini ( void )
Из комментария мы видим, что мы работает с битами режима, и установим мы из них только бит WGM12, остальные оставим нули. Исходя из этого мы сконфигурировали вот такой режим:
Также у таймера существует ещё вот такой регистр — TIMSK. Данный регистр отвечает за маски прерываний — Interrupt Mask. Доступен данный регистр для всех таймеров, не только для первого, он общий. В данном регистре мы установим бит OCIE1A, который включит нужный нам тип прерывания TIMER1 COMPA
Теперь давайте поиграемся с самими регистрами сравнения OCR1A(H и L). Для этого придётся немного посчитать. Регистр OCR1AH хранит старшую часть числа для сравнения, а регистр OCR1AL — младшую.
Но прежде чем посчитать, давайте пока напишем код с любыми значениями данного регистра и потом поправим, так как дальше мы будем инициализировать делитель и он тоже будет учавствовать в расчёте требуемого времени счёта. Без делителя таймер будет слишком быстро считать.
OCR1AH = 0b10000000; //записываем в регистр число для сравнения
OCR1AL = 0b00000000;
TCCR1B |= ( ); //установим делитель.
Пока никакой делитель не устанавливаем, так как мы его ещё не посчитали. Давайте мы этим и займёмся.
Пока у нас в регистре OCR1A находится число 0b1000000000000000, что соответствует десятичному числу 32768.
Микроконтроллер у нас работает, как мы договорились, на частоте 8000000 Гц.
Разделим 8000000 на 32768, получим приблизительно 244,14. Вот с такой частотой в герцах и будет работать наш таймер, если мы не применим делитель. То есть цифры наши будут меняться 244 раза в секунду, поэтому мы их даже не увидим. Поэтому нужно будет применить делитель частоты таймера. Выберем делитель на 256. Он нам как раз подойдёт, а ровно до 1 Гц мы скорректируем затем числом сравнения.
Вот какие существуют делители для 1 таймера
Я выделил в таблице требуемый нам делитель. Мы видим, что нам требуется установить только бит CS12.
Так как делитель частоты у нас 256, то на этот делитель мы поделим 8000000, получится 31250, вот такое вот мы и должны занести число в TCNT. До такого числа и будет считать наш таймер, чтобы досчитать до 1 секунды. Число 31250 — это в двоичном представлении 0b0111101000010010. Занесём данное число в регистровую пару, и также применим делитель
OCR1AH = 0b01111010; //записываем в регистр число для сравнения
OCR1AL = 0b00010010;
С данной функцией всё.
Теперь следующая функция — обработчик прерывания от таймера по совпадению. Пишется она вот так
ISR ( TIMER1_COMPA_vect )
И тело этой функции будет выполняться само по факту наступления совпадения чисел.
Нам нужна будет переменная. Объявим её глобально, в начале файла
unsigned char i ;
Соответственно, из кода в функции main() мы такую же переменную уберём
unsigned char i ;
Также закомментируем весь код в бесконечном цикле. Его роль теперь у нас будет выполнять таймер, и, я думаю, он с этим справится не хуже, а даже лучше, «никому» при этом не мешая.
while (1)
// while (butstate==0)
// if (!(PINB&0b00000001))
// butcount++;
// else
// i=0;
// butstate=1;
// else
// if(butcount > 0)
// butcount—;
// else
// butstate=1;
// segchar(i);
// _delay_ms(500);
// butstate=0;
Теперь, собственно, тело функции-обработчика. Здесь мы будем вызывать функцию segchar. Затем будем наращивать на 1 переменную i. И чтобы она не ушла за пределы однозначного числа, будем её обнулять при данном условии
if ( i >9) i =0;
segchar ( i );
i ++;
Теперь немного исправим код вначале функции main(). Порт D, отвечающий за состояние сегментов, забьём единичками, чтобы при включении у нас не светился индикатор, так как он с общим анодом. Затем мы здесь занесём число 0 в глобавльную переменную i, просто для порядка. Вообще, как правило, при старте в неициализированных переменных и так всегда нули. Но мы всё же проинициализируем её. И, самое главное, чтобы прерывание от таймера работало, её недостаточно включить в инициализации таймера. Также вообще для работы всех прерываний необходимо разрешить глобальные прерывания. Для этого существует специальная функция sei() — Set Interrupt.
Теперь код будет вот таким
PORTD = 0b11111111;
i =0;
sei ();
Также ещё мы обязаны подключить файл библиотеки прерываний вначале файла
Также переменные для кнопки нам пока не потребуются, так как с кнопкой мы сегодня работать не будем. Закомментируем их
//unsigned char butcount=0, butstate=0;
Соберём наш код и проверим его работоспособность сначала в протеусе. Если всё нормально работает, то проверим также в живой схеме
Всё у нас работает. Отлично!
Вот такой вот получился секундомер. Но так как у нас даже нет кварцевого резонатора, то данный секундомер нельзя назвать точным.
Тем не менее сегодня мы с вами много чему научились. Мы узнали о прерываниях, также научились их обрабатывать, Научились работать с таймерами, конфигурировать несколько новых регистров микроконтроллера, до этого мы работали только с регистрами портов. Также за счёт всего этого мы значительно разгрузили арифметическо-логическое устройство нашего микроконтроллера.
Купить программатор можно здесь (продавец надёжный) USBASP USBISP 2.0