Пристрої на мікроконтролері PIC12F629 Збірник схем прошивок - ПРИСТРОЇ НА МК - radio-bes -

продається розкручений сайт недорого звертатися в личку

Ні для кого не секрет, що сучасне програмне забезпечення полегшило нелегке життя інженера. Існують тисячі програм для автоматизованого проектування електронних схем, для моделювання їх роботи, у тому числі і для мікроконтролерних систем. Одна з таких САПР - Proteus VSM, розроблена компанією Labcenter Electronics (вимагайте безкоштовну версію ознайомлення).

Отже, для вивчення мікроконтролерів нам знадобляться:

  1. бажання
  2. комп'ютер із встановленим Proteus
  3. вільний час
Для того, щоб осягнути всі секрети мікроконтролера, починати вивчення краще з прочитання документації (для мікроконтролерів PIC документацію можна завантажити на сайті виробника), а програмувати почати не на С, Pascal або навіть Basic, а на старому доброму асемблері , Що дозволить зрозуміти, як же ця залізяка насправді працює. Що можна насамперед відзначити у мікроконтролері сімейства PIC16 з погляду програміста:
  1. роздільні пам'ять програм (14 біт) та пам'ять даних (8 біт)
  2. всього 35 інструкцій
  3. більшість інструкцій (крім інструкцій переходу та перевірки умов) виконується за 1 машинний цикл (4 такти тактового генератора)
  4. один явно виражений регістр загального призначення – акумулятор
  5. звернення до будь-якого осередку оперативної пам'яті як до регістру (так звані регістрові файли)
  6. порти введення-виводу
  7. наявність переривань
  8. апаратні таймери
Створимо простий пристрій на простому мікроконтролері PIC16F84A. Для цього в Proteus знайдемо цей мікроконтролер у бібліотеці елементів, додамо до проекту та розмістимо його на робочому аркуші.

пристрої

pic12f629

Прицьому мікроконтролеру автоматично буде призначено файл із прошивкою. У загальному випадку для моделювання роботи мікроконтролеру не потрібно ніяких зовнішніх елементів, навіть джерела живлення. Але щоб пристрій не просто виконував нашу майбутню програму, а й здійснював деякі корисні функції, додамо до схеми кілька додаткових елементів і зберемо пристрій «світлофор».

пристрої

LIST p=16F84a include "P16F84A.INC" ;--------------------------------- CBLOCK 0x0C W_TEMP ;0x0C STATUS_TEMP ;0x0D FLAGS ;0x0E COUNTER ;0x0F ENDC ;------------- -------------------- TF EQU 0x00 ;Task flag ORG 0x00 goto START ORG 0x04 ;-- ------------------------------- INT movwf W_TEMP ;save W swapf STATUS, W movwf STATUS_TEMP ;save STATUS btfss INTCON, T0IF goto ENDISR bcf INTCON, T0IF ;clear flag bsf FLAGS, TF ENDISR swapf STATUS_TEMP, W movwf STATUS swapf W_TEMP, F swapf W_TEMP, W ;recover W retfie ;------------------------- -------- START clrf PORTA clrf PORTB bsf STATUS, RP0 ;Bank1 clrf TRISB ;PortB Output movlw b'11010111' movwf OPTION_REG ; Set Option_REG bcf STATUS, RP0 ;Bank0 clrf TMR0 bsf INTCON, T0IE ;Enable Timer0 interrupt bsf INTCON, GIE ;Enable interrupts movlw 0x3D movwf COUNTER ;--------------------------------- MAIN btfss FLAGS, TF goto MAIN ;If TF = 0 call OUTPUT bcf FLAGS, TF ;Clear TF goto MAIN ;------------------------ --------- OUTPUT decfsz COUNTER, F goto NOT0 movlw 0x3C movwf COUNTER NOT0 movf COUNTER, W call TAB movwf PORTB return ;--------------------------------- TAB addwf PCL, F nop retlw b'00100001' ;1 retlw b'00000001' ;2 retlw b'00100001' ;3 retlw b'00000001' ;4 retlw b'00100001' ;5 retlw b'00000001' ;6 retlw b'00100001' ;7 retlw b'00000001' ;8 retlw b'00100001' ;9 retlw b'00000001' ;10 retlw b'00100001' ;11 retlw b'00100001' ;12 retlw b'00100001' ;13 retlw b'00100001' ;14 retlw b'00100001' ;15 retlw b'00100001' ;16 retlw b'00100001' ;17 retlw b'00100001' ;18 retlw b'00100001' ;19 retlw b'00100001' ;20 retlw b'00010010' ;21 retlw b'00010010' ;22 retlw b'00010010' ;23 retlw b'00010010' ;24 retlw b'00010010' ;25 retlw b'00010010' ;26 retlw b'00010010' ;27 retlw b'00010010' ;28 retlw b'00010010' ;29 retlw b'00010010' ;30 retlw b'00010010' ;31 retlw b'00010010' ;32 retlw b'00010010' ;33 retlw b'00010010' ;34 retlw b'00010010' ;35 retlw b'00010010' ;36 retlw b'00010010' ;37 retlw b'00010010' ;38 retlw b'00010010' ;39 retlw b'00010010' ;40 retlw b'00001100' ;41 retlw b'00001000' ;42 retlw b'00001100' ;43 retlw b'00001000' ;44 retlw b'00001100' ;45 retlw b'00001000' ;46 retlw b'00001100' ;47 retlw b'00001000' ;48 retlw b'00001100' ;49 retlw b'00001000' ;50 retlw b'00001100' ;51 retlw b'00001100' ;52 retlw b'00001100' ;53 retlw b'00001100' ;54 retlw b'00001100' ;55 retlw b'00001100' ;56 retlw b'00001100' ;57 retlw b'00001100' ;58 retlw b'00001100' ;59 retlw b'00001100' ;60 ;-------------------------- ------- КІНЕЦЬ

Дана програма при всій своїй простоті містить майже всі елементи, присутні і більш складні програми. Рассмотрим структуру детальнее.

У коментарі вважається строка або її частина, яка починається з символом «;».

Строка «LIST p=16F84a» є директивою ассемблера, призначеної для редагуванняпараметрів компіляції та визначає тип використовуваного мікроконтролера (16F84a).

Директива include P16F84A.INC, як програмісти вже напевно здогадалися, підключає до вихідного файлу файл, що визначає параметри і набір регістрів спеціального призначення для конкретного мікроконтролера.

Директива EQU у рядку "TF EQU 0x00" визначає константу TF рівну числу 0x00.

Ініціалізація

Команда clrf призначена для обнулення вмісту регістру. Командами

clrf PORTA clrf PORTB

ми обнулимо вміст регістрів, пов'язаних з портами введення-виведення PortA та PortB. Це необхідно, оскільки при скиданні мікроконтролера можуть отримати випадкові значення. Команда «bsf» призначена для встановлення певного біта в байті регістру. Таким чином, при виконанні:

У другому банку пам'яті нас цікавить регістр TRISB, визначальний, які висновки порту PortB є входами, які виходами. Встановленням за допомогою команди «clrf TRISB» всіх бітів регістру TRISB в 0, визначаємо всі висновки PortB як виходи.

Команда bcf скидає певний біт у регістрі, таким чином за допомогою команди

ми можемо знову звертатися до банку першому банку пам'яті.

Тепер необхідно змінити значення регістрів:

  • OPTION_REG, за допомогою якого можна налаштувати таймер Timer0
  • INTCON, що визначає, які переривання дозволені в системі.

Команда «movlw b'11010111'» завантажує в акумулятор W число, за допомогою якого ми встановлюємо джерело для тактування таймера від внутрішнього генератора, підключаємо дільник до таймера а також встановлюємо коефіцієнт дільника (подробиці дивіться в документації). Командою movwf OPTION_REG ми відправляємо число з акумулятора вспеціальний регістр OPTION_REG.

Команда clrf TMR0 скидає значення таймера Timer0, далі його значення інкрементуватиметься з частотою рівною частоті циклу мікропроцесора, поділеної на обраний нами предделитель. При переповненні регістра TMR0 відбуватиметься відповідне переривання.

Для дозволу переривання від таймера в спеціальному регістрі INTCON необхідно встановити біт T0IE, а для глобального дозволу переривань необхідно встановити біт GIE, що роблять команди:

bsf INTCON, T0IE bsf INTCON, GIE

Також на етапі ініціалізації встановлюється лічильник циклів для основної програми:

movlw 0x3D movwf COUNTER

На цьому ініціалізація закінчується та починається основний цикл програми.

Основний цикл

Перевірка значення біта в регістрі здійснюється за допомогою команди btfss FLAGS, TF. Команда тестує біт у регістрі, якщо біт встановлений у «1», то наступна інструкція не виконується, а наступні 2 цикли виконується команда «nop» («немає операції»). Якщо біт має значення «0», то виконується наступна по порядку інстукція.

Оскільки наступна інструкція є командою безумовного переходу на мітку MAIN, при скинутому прапорі завдання TF триває нескінченний основний цикл програми. При встановленому прапорі завдання виконується команда виклику підпрограми "call OUTPUT", таким чином поточне значення лічильника команд (PC - "Program counter") поміщається у стек, і відбувається перехід на підпрограму з позначкою OUTPUT.

Підпрограма обробки переривань

Вміст акумулятора просто поміщається в заздалегідь виділену комірку пам'яті командою "movwf W_TEMP". Регістр STATUS може змінювати своє значення під час виконання ряду інструкцій, тому застосовується маленькахитрість. Вміст регістру поміщається в акумулятор з перестановкою ніблів (напівбайтів) командою swapf STATUS, W, а звідти поміщається в заздалегідь виділену комірку пам'яті командою movwf STATUS_TEMP.

Відновлення вмісту W та STATUS в кінці підпрограми відбувається у зворотному порядку. Вміст комірки пам'яті, що зберігає вміст регістру STATUS, поміщається в акумулятор з перестановкою ніблів командою «swapf STATUS_TEMP, W», і з акумулятора переноситься безпосередньо в регістр STATUS командою «movwf STATUS». Для запобігання випадковій модифікації регістру STATUS при розміщенні невідомого заздалегідь значення з тимчасової комірки пам'яті в акумулятор, відновлення акумулятора здійснюється двома командами з перестановкою ніблів:

swapf W_TEMP, F swapf W_TEMP, W

Таке застосування команди swapf пояснюється тим, що вона не впливає на прапори в регістрі STATUS.

Сам обробник переривання перевіряє, що викликало переривання (т.к. можливі кілька джерел переривання, якщо вони будуть дозволені) шляхом перевірки відповідних бітів регістра INTCON. Оскільки у нас дозволено лише одне переривання, можна було б не робити такої перевірки, але перевіримо біт T0IF (встановлюється при виникненні переривання від таймера):

btfss INTCON, T0IF goto ENDISR bcf INTCON, T0IF bsf FLAGS, TF

Якщо біт не встановлений, відбудеться перехід до інструкцій відновлення вмісту W і STATUS на позначку ENDISR. Якщо біт встановлено то ми його скинемо вручну командою bcf INTCON, T0IF і встановимо прапор завдання командою bsf FLAGS, TF. Далі виконуються інструкції відновлення вмісту W та STATUS. Вихід із підпрограми обробки переривань відбувається під час виконання інструкції «retfie». Вмістлічильник команд відновлюється з стека, а переривання автоматично дозволяються шляхом установки біта GIE регістра INTCON в «1».

Підпрограма OUTPUT

У цій підпрограмі виконуються всі «корисні» дії, якими ми можемо будувати висновки про функціонуванні микроконтроллерного пристрою. Нам необхідно отримати на виході таку функцію:

пристрої

Стан виходів у дискретні моменти часу, що визначаються установкою прапора завдання TF, отримаємо табличним методом, для цього в пам'ять програм помістимо таблицю відповідних значень. Таблична реалізація різних обчислень у мікроконтролері характеризується максимальною швидкодією, але потребує багато місця у пам'яті програм. Наприклад, у разі треба задати 60 значень, що вимагає 60 осередків пам'яті.

Підпрограма містить інструкції:

OUTPUT decfsz COUNTER, F goto NOT0 movlw 0x3C movwf COUNTER NOT0 movf COUNTER, W call TAB movwf PORTB return

Інструкція "decfsz" призначена для організації циклів. Вона декрементує вміст регістру COUNTER, якщо результат не дорівнює нулю, виконується наступна по порядку інструкція (переходимо на мітку NOT0), інакше протягом 2 циклів виконується порожня інструкція «nop», а потім у регістр COUNTER поміщається початкове значення 0x3C (зауважте, тому що декремент регістру здійснюється до використання значення цього регістру в програмі, при ініціалізації ми задали значення на 1 більше).

Значення регістру COUNTER міститься в акумуляторі W, після чого здійснюється читання з таблиці шляхом виклику підпрограми інструкцією «call TAB». При поверненні з таблиці W міститься необхідне нам значення стану виходів. Це значення записується в регістр PORTB, чим здійснюється висновоксигналів із мікроконтролера. Далі відбувається повернення із підпрограми командою «return».

Таблиця значень

Таблиця містить кілька сервісних інструкцій і, власне, самі 60 значень, що нам потрібні: TAB addwf PCL, F nop retlw b'00100001' ;1 retlw b'00000001' ;2 ……… retlw b'00001100' ;60

Таким чином, в результаті повернення з таблиці, ми маємо у W необхідне значення.

Інструкція «nop» застосована для вирівнювання значень таблиці, т.к. таблиця не викликається за W=0. Слід зазначити необхідність контролю вмісту акумулятора W під час виклику таблиць, щоб не стався перехід за межі програми.

У підсумку, проект готовий, а асемблер виявився не такою вже й страшною мовою. Тепер можна запускати програму на виконання та відловлювати помилки, якщо вони були допущені. Але про це у наступній статті