1 Востаннє редагувалося Ярослав (21.12.2013 09:12:00)

Тема: Рішення деяких задач мовою A51 середовища keil

Завдання: Зберегти вміст поточного банку регістрів в ЗПД з адреси C200h

XSEG    AT     0С200h    ; визначаємо абсолютний сегмент пам'яті 
                         ; в зовнішній пам'яті даних (XDATA)
        ORG    0С200h    ; переміщуємо лічильник розташування на комірку 0C200h
ARR1:   DS     08h       ; помітимо цю комірку міткою ARR1 і зарезервуємо 8 комірок

CSEG    AT     0С000h    ; визначаємо абсолютний сегмент пам'яті 
                         ; в пам'яті програм (CODE)
        ORG    0С000h    ; переміщуємо лічильник розташування на комірку 0C000h

        MOV    R0, #0    ; Заповнимо чимось регістри
        MOV    R1, #1
        MOV    R2, #2
        MOV    R3, #3
        MOV    R4, #4
        MOV    R5, #5
        MOV    R6, #6
        MOV    R7, #7

        MOV    DPTR, #ARR1        ; перемістимо в DPTR адресу першої комірки в ЗПД
        MOV    PSW, #00001000b    ; оберемо перший банк регістрів
        MOV    R0, #00h           ; завантажимо в R0 адресу R0 із нульового банку
        MOV    R1, #08h           ; визначимо кількість кроків для циклу

LABEL:  MOV    A, @R0        ; переміщуємо в регістр A 
                             ; значення регістру із нульового банку
        MOVX   @DPTR, A      ; переміщуємо в ЗПД значення акумулятора
        INC    DPTR          ; збільшемо значення DPTR на 1, 
                             ; таким чином помістимо в нього адресу наступної комірки
        INC    R0            ; збільшимо значення R0 на 1,
                             ; таким чином помістимо в нього адресу наступного регістру
        DJNZ   R1, LABEL     ; віднімаємо від R1 1 і якщо R1 не дорівнює нулю,
                             ; то переходимо на мітку LABEL

        JMP    $             ; нескінченний цикл
END

Далі буде...

2

Re: Рішення деяких задач мовою A51 середовища keil

Завдання: Поміняти місцями половинки масиву

SIZE    EQU     10         ; Кількість елементів масиву

DSEG    AT      40h        ; Абсолютний сегмент пам'яті
                           ; у внутрішній пам'яті даних
        ORG     40h        ; Переміщуємо лічильник
                           ; розташування на комірку
                           ; 40h
ARRAY:  DS      SIZE       ; Позначимо цю комірку
                           ; міткою ARRAY і
                           ; зарезервуємо місце для
                           ; масиву
NUMB:   DS      1          ; наступну комірку позначимо
                           ; NUMB і зарезервуємо цю
                           ; комірку
CSEG    AT      0c000h     ; Абсолютний сегмент пам'яті
                           ; у пам'яті кодів
        ORG     0c000h     ; Переміщуємо лічильник
                           ; розташування на комірку
                           ; 0С000h

        MOV     R0, #ARRAY ; R0 <- адреса першого
                           ; елемента масиву
        MOV     R1, #1     ; заповнимо масив починаючи
                           ; з 1
        MOV     R2, #SIZE  ; Лічильник для циклу

L1:     MOV     A, R1      ; A <- R1
        MOV     @R0, A     ; Перемістимо число в 
                           ; комірку
        INC     R0         ; Пересунимо покажчик на
                           ; наступну вільну комірку
        INC     R1         ; Збільшимо число на 1
        DJNZ    R2, L1     ; Цикл

        MOV     A, #SIZE   ; Знайдемо кількість
                           ; елементів
        MOV     B, #2      ; половини масиву
        DIV     AB         ; і помістимо її в А
        MOV     R2, A      ; кількість елементів в
                           ; половині масиву
        MOV     NUMB, A    ; Збережемо її на майбутнє
        MOV     A, B       ; Якщо в B 1 - то кількість
                           ; елементів непарна
        JNZ     ODD        ; перестрибнути на код,
                           ; який сортує непарні масиви
        MOV     A, NUMB    ; Кількість елементів
                           ; половини масиву
; Сортування парного масиву
        MOV     R0, #ARRAY ; Адреса першого елемента
        MOV     R2, A      ; R2 <- A
        ADD     A, #ARRAY  ; Адреса першого елемента
                           ; другої половини масиву
        MOV     R1, A      ; R1 <- A

EVEN:   MOV     A, @R0     ; A <- елемент
                           ; першої половини масиву
        MOV     NUMB, A    ; NUMB <- A
        MOV     A, @R1     ; A <- елемент
                           ; другої половини масиву
        MOV     @R0, A     ; переміщуємо елемент
                           ; другої половини масиву
                           ; на місце елемента 
                           ; першої половини
        MOV     A, NUMB    ; A <- збережений елемент
                           ; першої половини масиву
        MOV     @R1, A     ; Переміщуємо збережений
                           ; елемент першої половини 
                           ; масиву на місце елемента 
                           ; другої половини
        INC     R0         ; Покажчик на наступний
                           ; елемент першої половини
        INC     R1         ; Покажчик на наступний
                           ; елемент другої половини
        DJNZ    R2, EVEN   ; Цикл
        JMP $              ; Зациклити програму
; Сортування непарного масиву
ODD:    MOV     A, NUMB    ; Кількість елементів
                           ; половини масиву
        ADD     A, #ARRAY  ; Адреса наступного елементу
                           ; після першої половини
                           ; масиву
        MOV     R0, A      ; Покажчик на наступний 
                           ; елемент після першої
                           ; половини масиву
        MOV     A, #ARRAY  ; Адреса першого елементу
                           ; першої половини масиву
        ADD     A, #SIZE   ; A = A + SIZE
        DEC     A, #1      ; A = A - 1
        MOV     R1, A      ; Останній елемент масиву

        MOV     A, @R0     ; A <- наступний елемент
                           ; після першої половини
                           ; масиву
        MOV     NUMB, A    ; Збережемо цей елемент
                           ; в NUMB
L2:     MOV     A, @R1     ; A <- елемент другої
                           ; половини масиву
        MOV     @R0, A     ; (R0) <- Елемент другої
                           ; половини масиву 
        DEC     R0         ; R0 на попередній 
                           ; елемент масиву
        MOV     A, @R0     ; A <- (R0)
        MOV     @R1, A     ; (R1) <- A
        DEC     R1         ; R1 на попередній
                           ; елемент масиву
        DJNZ    R2, L2     ; Цикл
        MOV     @R0, NUMB  ; (R0) <- збережений
                           ; елемент
        JMP     $          ; Зациклити програму

END

3

Re: Рішення деяких задач мовою A51 середовища keil

Завдання: Написати програму, яка вираховує n чисел Фібоначчі.

Примітка: Максимальне число - FFFFh = 65535. Числа записуються в два байти: старший і молодший.

DSEG        AT     40h
            ORG    40h
NUMCOUNT:   DS     1
            ORG    41h
TEMPBYTE:   DS     1
            ORG    42h
TEMPCARRY:  DS     1
            ORG    50h
FIRSTNUM:   DS     40

;  0,  1,   1,   2,   3,   5,   8,    13,   21,   34,
; 55, 89, 144, 233, 377, 610, 987,  1597, 2584, 4181

CSEG   AT    0c000h
       ORG    0c000h

       MOV    R0, #FIRSTNUM
       MOV    R1, #FIRSTNUM+2

L1:    MOV    A, #16        
       MOV    NUMCOUNT, #16    
       SUBB   A, NUMCOUNT    
       JC     L1        

       MOV    R2, NUMCOUNT
       MOV    @R0, #00h
       MOV    @R1, #01h

L2:    MOV    A, @R0         ; A <- молодший байт ПЕРШОГО числа
       ADD    A, @R1         ; A + молодший байт ДРУГОГО числа
       MOV    TEMPBYTE, A    ; збережемо вміст акумулятора
       CLR    A              ; A <- 0
       ORL    A, PSW         ; A <- PSW
       ANL    A, #10000000b  ; A = 40h, якщо carry = 1
       JNC    L3
       CLR    C
       SUBB   A, #07Fh        ; A = 40h - 3Fh = 01h
L3:    MOV    TEMPCARRY, A    ; TEMPCARRY <- A
       MOV    A, #4h          ; A <- крок для того, 
                              ; щоб перенести покажчик на молодший байт
                              ; НАСТУПНОГО числа
       ADD    A, R0           ; A <- адреса молодшого байту НАСТУПНОГО числа
       MOV    R0, A           ; R1 <- A
       MOV    @R0, TEMPBYTE   ; молодший байт НАСТУПНОГО числа <- результат
                              ; додавання молодших байтів
       MOV    A, R0 
       SUBB   A, #3h          ; A <- крок для того,
                              ; щоб перенести покажчик на старший байт
                              ; ПЕРШОГО числа
       MOV    R0, A           ; перенести покажчик на старший байт
                              ; ПЕРШОГО числа
       INC    R1              ; пересунути покажчик на старший байт 
                              ; ДРУГОГО числа

       MOV    A, #0h
       MOV    TEMPBYTE, #0h
       MOV    A, @R0            ; A <- старший байт першого числа
       ADD    A, @R1            ; A + старший байт другого числа
       ADD    A, TEMPCARRY      ; A + TEMPCARRY
       MOV    TEMPBYTE, A       ; TEMPBYTE <- A
       MOV    A, #4h            ; A <- крок для того, 
                                ; щоб перенести покажчик на старший байт
                                ; НАСТУПНОГО числа
       ADD    A, R0             ; A <- адреса старшого байту НАСТУПНОГО числа
       MOV    R0, A             ; R0 <- A
       MOV    @R0, TEMPBYTE     ; старший байт НАСТУПНОГО числа <- результат
                                ; додавання старших байтів
       MOV    A, R0        
       SUBB   A, #3h            ; A <- крок для того,
                                ; щоб перенести покажчик 
                                ; на старший байт ПЕРШОГО числа
       MOV    R0, A             ; перенести покажчик на старший байт
                                ; ПЕРШОГО числа
       INC    R1

       DJNZ    R2, L2

       SETB    P3.5
       JMP     $

END

4 Востаннє редагувалося Ярослав (24.01.2014 17:43:32)

Re: Рішення деяких задач мовою A51 середовища keil

Завдання: Скласти програму на основі арифметичних операцій, яка буде вираховувати вираз Y = A – C / B.

DSEG    AT      40h ; Визначаємо абсолютний сегмент пам'яті
                    ;   у внутрішній пам'яті даних (DATA)
        ORG     40h ; Переміщуємо лічильник розташування 
                    ;   на комірку 40h
VAR_A:  DS      1   ; Резервуємо пам'ять для змінних, по 1 байту
VAR_B:  DS      1
VAR_C:  DS      1
RESULT: DS      1

CSEG    AT      0c000h ; Визначаємо абсолютний сегмент пам'яті
                       ;   у внутрішній пам'яті кодів (CODE)
        ORG     0c000h ; Переміщуємо лічильник розташування 
                       ;   на комірку 0c000h

        MOV     VAR_A, #14 ; Переміщуємо число 14 в комірку з ім'ям VAR_A
        MOV     VAR_B, #2  ; VAR_B <- 2
        MOV     VAR_C, #4  ; VAR_C <- 4

        MOV     A, VAR_C   ; A <- VAR_C
        MOV     B, VAR_B   ; B <- VAR_B
        DIV     AB         ; Розділимо A на B, результат ділення збережеться в A,
                           ;   остача від ділення - в B
        MOV     RESULT, A  ; RESULT <- A
        MOV     A, VAR_A   ; A <- VAR_A
        SUBB    A, RESULT  ; Віднімаємо від A значення RESULT і значення C
        MOV     RESULT, A  ; RESULT <- A

        SETB    P3.5       ; Запалюємо світлодіод
        JMP     $          ; Зациклюємо програму
END

5

Re: Рішення деяких задач мовою A51 середовища keil

Ярославе, дякую за ваш доробок, поясніть докладніше нащо потрібний наступний код:

CSEG AT 0c000h ; Визначаємо абсолютний сегмент пам'яті
; у внутрішній пам'яті кодів (CODE)
ORG 0c000h ; Переміщуємо лічильник розташування
; на комірку 0c000h

Хіба пам’ять кодів починається з 0c000h, а до того суцільне провалля? Це процедури чи закінчені самодостатні програми? З якої комірки починає роботу 8051 мікроконтроллер?

6 Востаннє редагувалося Ярослав (14.03.2014 16:30:47)

Re: Рішення деяких задач мовою A51 середовища keil

Вибачте, що довго не відповідав.
В ВНЗ ми практикуємось на 8051 мікроконтролері в середовищі Keil, адреса 0c000h визначається для симулятора, а коли треба працювати із платою, то всюди 0c000h заміняється на 00000h =)

З приводу другого запитання - то це вирішення лабораторних робіт, повноцінними програмами їх навряд чи назвеш, але при завантаженні в пам'ять відладочної плати і виконанні "на борту" працюють =)
Приблизно так, я іще уточню =) Дякую за цікавість до теми, я планую іще завантажувати сюди деякі коди =)

7

Re: Рішення деяких задач мовою A51 середовища keil

Тепер я точно знаю, чому використовується адреса 0C000h.
В симуляторі ми працюємо із адресою 00000h, але в безкоштовній версії Keil діє обмеження на код (2К), тому на плату код можна завантажити тільки з комірки 0C000h, всі переривання і т. д. запрограмовані відповідно до цього обмеження на нашому стенді (напр. INT - це 0C013h).

8

Re: Рішення деяких задач мовою A51 середовища keil

Вивести на світлодіоди комбінацію тумблерів.

TCOMB   EQU   20h    ; V tsey bait my budemo zapysuvaty 
                     ; potochne znachennya kombinacii tumbleriv
                     ; Zapysuyemo v try ostanny biti, tobto
                     ; 20h.2, 20h.1, 20h.0 abo TCOMB.2, TCOMB.1, TCOMB.0

CSEG    AT    00000h ; 0c000h for hardware
        ORG   00000h ; Vstanovluyemo lichilnik komand na komirku 00000h
                     ; Yakscho my vikoristovuyemo vidladochnu platu, to
                     ; ci ryadky treba zaminyty na:
                     ; CSEG    AT    0C000h
                     ;         ORG   0C000h
; Spershu ochystymo bity vsih tumbleriv     
MAIN:   CLR   P3.2         ; Pershyi tumbler 
        CLR   P1.4         ; Druhyi tumbler
        CLR   P1.3         ; Tretii tumbler
; Teper vymknemo vsi svitlodiody
PREL:   SETB  P3.3         ;         ( ) Pravyi
        CLR   P3.4         ;     ( )     Serednyi
        CLR   P3.5         ; ( )         Livyi
; Registr R2 vykorystovuyemo, shcob sberigaty 
; kilkist odnochasno vkluchenyh tumbleriv
LOOP:   MOV   R2, #0         ; Vvashaemo sho ne vklucheno zhodnoho tumblera
        
        MOV   C, P3.2        ; Zchytuemo znachennya pershogo tumblera
                             ; I perenosymo yogo v Carry (c)
        MOV   TCOMB.2, C     ; Potim zapysuyemo ce znachennya v TCOMB.2
                             ; TCOMB(o o o o o V o o) <- C
        JNC   L1             ; Propuskayemo dodavannya do R2 odynyci
                             ; yakshco pershyi tumbler vymknenyi
        INC   R2             ; Dodayemo do R2 odynycu, yakscho
                             ; pershyi tumbler vvimknenyi
                           
L1:     MOV   C, P1.4        ; Zchytuemo znachennya druhoho tumblera
                             ; I perenosymo yogo v Carry (c)
        MOV   TCOMB.1, C     ; Potim zapysuyemo ce znachennya v TCOMB.1
                             ; TCOMB(o o o o o o V o) <- C
        JNC   L2             ; Propuskayemo dodavannya do R2 odynyci
                             ; yakshco druhyi tumbler vymknenyi
        INC   R2             ; Dodayemo do R2 odynycu, yakscho
                             ; druhyi tumbler vvimknenyi
                           
L2:     MOV   C, P1.3        ; Zchytuemo znachennya tretoho tumblera
                             ; I perenosymo yogo v Carry (c)
        MOV   TCOMB.0, C     ; Potim zapysuyemo ce znachennya v TCOMB.0
                             ; TCOMB(o o o o o o o V) <- C
        JNC   L3             ; Propuskayemo dodavannya do R2 odynyci
                             ; yakshco tretii tumbler vymknenyi
        INC   R2             ; Dodayemo do R2 odynycu, yakscho
                             ; tretii tumbler vvimknenyi
                           
L3:     CLR   C              ; Ochyschayemo C
        MOV   A, R2          ; A <- Kilkist vkluchenyh odnochasno tumbleriv
        JZ    PREL           ; Yakscho zhodnoho ne vkluchyly - to treba vymknuty
                             ; vsi svitlodiody, perehodymo na mitku PREL
                           
        SUBB  A, #1          ; Vidnimayemo vid znachennya A odynycu
        JZ    ONE_ENABLED    ; Yakscho vyishov nul, znachit odyn tumbler buv
                             ; vvimknenyi, pereydemo na mitku ONE_ENABLED i
                             ; diznayemos yakyi same
                           
        SUBB  A, #1          ; Vidnimayemo vid znachennya A odynycu
        JZ    MORE           ; Yakscho vyishov nul, znachit dva tumblery
                             ; bulo vvimkneno, treba pro ce 
                             ; povidomyty, idemo na mitku MORE
        SUBB  A, #1          ; Vidnimayemo vid znachennya A odynycu
        JZ    MORE           ; Yakscho vyishov nul, znachit try tumblery
                             ; bulo vvimkneno, treba pro ce 
                             ; povidomyty, idemo na mitku MORE
                           
        JMP   ERROR          ; Schos pishlo ne tak

; Odyn tumbler buv vvimknenyi 
ONE_ENABLED:    MOV    C, TCOMB.2    ; C <- TCOMB(o o o o o V o o)
                JC     FIRST         ; Yakscho ce buv pershyi tumbler
                                     ; Pereydemo na mitku FIRST
                                     
                MOV    C, TCOMB.1    ; C <- TCOMB(o o o o o o V o)
                JC     SECOND        ; Yakscho ce buv druhyi tumbler
                                     ; Pereydemo na mitku SECOND
                                     
                MOV    C, TCOMB.0    ; C <- TCOMB(o o o o o o o V)
                JC     THIRD         ; Yakscho ce buv druhyi tumbler
                                     ; Pereydemo na mitku THIRD
; Pershyi buv vvimknenyi - kombinaciya 0 1                
FIRST:          CLR    P3.3          ;         (*) Zapaluyemo pravyi svitlodiod
                CLR    P3.4          ;     ( )     I hasimo serednyi                                
                JMP    DONE          ; Vse zrobyly
; Druhyi buv vvimknenyi  - kombinaciya 1 0      
SECOND:         SETB   P3.3          ;         ( ) Hasymo pravyi svitlodiod
                SETB   P3.4          ;     (*)     Zapaluemo serednyi svitlodiod
                JMP    DONE          ; Vse zrobyly
; Tretii buv vvimknenyi  - kombinaciya 1 1                
THIRD:          CLR    P3.3          ;         (*) Zapaluyemo pravyi svitlodiod
                SETB   P3.4          ;     (*)     c
                JMP    DONE          ; Vse zrobyly
                
DONE:           CLR    P3.5          ; ( )         Hasymo livyi svitlodiod
                CLR    C             ; Ochystymo C
                JMP    LOOP          ; Znovu perevirymo tumblery

; Povidomymo pro te, scho bulo vvimneno bilshe nizh odyn tumbler 
MORE:    MOV    R1, #3       ; Try razi vkluchymo i vykluchymo svitlodiody
BLINK:   MOV    R0, #0AAh    ; R0 <- Chyslo, yake vidpovidaye zatrymci
         CLR    P3.3         ;         (*) Zapaluyemo pravyi svitlodiod
         SETB   P3.4         ;     (*)     Zapaluyemo serednii svitlodiod
         SETB   P3.5         ; (*)         Zapaluyemo livyi svitlodiod
         DJNZ   R0, $        ; Zatrymka
         MOV    R0, #0AAh    ; R0 <- Chyslo, yake vidpovidaye zatrymci
         SETB   P3.3         ;         ( ) Hasymo pravii svitlodiod
         CLR    P3.4         ;     ( )     Hasymo serednyi svitlodiod
         CLR    P3.5         ; ( )         Hasymo livyi svitlodiod
         DJNZ   R0, $        ; Zatrymka
         DJNZ   R1, BLINK    ; Povtorymo ce povidomlennya R1 raziv
         JMP    LOOP         ; Znovu perevirymo tumblery

ERROR:   CLR    P3.3         ;         (*) Zapaluyemo pravyi svitlodiod
         SETB   P3.4         ;     (*)     Zapaluyemo serednii svitlodiod
         SETB   P3.5         ; (*)         Zapaluyemo livyi svitlodiod
         JMP   $      
        
END

9

Re: Рішення деяких задач мовою A51 середовища keil

Вивести на світлодіоди два останніх біти часла, яке є сумою двох комбінацій тумблерів.

; Treba vystavyty pershu kombinaciyu tumbleriv i natysnuty na knopku INT1
; Potim vystavyty druhu kombinaciyu tumbleriv i natysnuty na INT1
; Porahuyetsa suma kombinacii i dva ostannih bity sumy vivedutsa
; na livyi ta serednyi svitlodiody

TCOMB1        EQU   20h     ; TCOMB1 <- persha kombinaciya tumbleriv
TCOMB2        EQU   21h     ; TCOMB2 <- druha kombinaciya tumbleriv

DSEG          AT    40h     ; Zarezervuyemo dlya sebe pamyat v DATA segmenti
              ORG   40h     ; Vstanovymo prohramnyi lichilnik na komirku 40h
COUNTER_1:    DS    1       ; Zarezervuyemo 1 bait dlya lichilnika COUNTER_1

CSEG    AT        00000h      ; Yakscho vykorystovuyetsa symulator - to stavyty 00000h
        ORG     00000h      ; Yakscho vykorystovuyetsa plata - to stavyty 0C000h
        JMP     MAIN        ; Pereydemo na MAIN

        ORG     00013h      ; Yakscho vykorystovuyetsa symulator - to stavyty 00013h
                            ; Yakscho vykorystovuyetsa plata - to stavyty 0C013h
        JMP     ISR_SHIFT   ; Spracuvalo pereryvannya, pereydemo na ISR_SHIFT

MAIN:    SETB    IT1                       ; Pereryvannya bude vyklykatys lohichnoyu
                                       ; odynyceyu na P3.3, na vidminu vid vmukannya
                                       ; lohichnym nulem na P3.3
        SETB    EA                       ; Dozvolyaemo vsi pereryvannya
        SETB    EX1                       ; Dozvolyaemo vyklykaty pereryvannya External 1
        CLR     P3.2                   ; Vvashayemo scho vsi tumblery vymkneni
        CLR     P1.4
        CLR     P1.3
        SETB    P3.3                   ; Pohasymo usi svitlodiody
        CLR     P3.4
        CLR     P3.5
        MOV     COUNTER_1, #0          ; Pochatkove znachennya lichilnika
        
        JMP     $                      ; Chekayemo doky spracuye pereryvannya
        
; Spracuvalo pereryvannya, znachit treba pereviryty tumblery        
ISR_SHIFT:        MOV     A, COUNTER_1   ; A <- Znachennya lichilnyka
                ADD     A, #1          ; Dodamo do A odynycu
                MOV     COUNTER_1, A   ; Zapyshemo resultat v lichilnik
                
                SUBB    A, #1          ; Vidnimemo vid A odynycu
                JZ      FIRST_PUSH     ; Knopka INT1 natysnena vpershe
                                       ; Treba diznatys kombinaciyu tumbleriv
                                       ; I zapysaty yiyi v TCOMB1, 
                                       ; pereydemo na mitku FIRST_PUSH
                SUBB    A, #1          ; Vidnimemo vid a odynycu
                JZ      SECOND_PUSH    ; Knopka INT1 natysnena dvichi
                                       ; Treba diznatys kombinaciyu tumbleriv
                                       ; I zapysaty yiyi v TCOMB2, potim dodaty
                                       ; TCOMB1 do TCOMB2 i vyvesty na svitlodiody
                                       ; Pereydemo na mitku SECOND_PUSH

; Knopka INT1 natysnena vpershe
FIRST_PUSH:     MOV     C, P1.3        ;         (|) C <- Znachennya tretoho tumblera
                MOV     TCOMB1.0, C    ; TCOMB1(o o o o o o o V) <- C
                MOV     C, P1.4        ;     (|)     C <- Znachennya druhoho tumblera
                MOV     TCOMB1.1, C    ; TCOMB1(o o o o o o V o) <- C
                MOV     C, P3.2        ; (|)         C <- Znachennya tretoho tumblera
                MOV     TCOMB1.2, C    ; TCOMB1(o o o o o V o o) <- C
                JMP     DONE           ; All done
; Knopka INT1 natysnena dvichi
SECOND_PUSH:    MOV     COUNTER_1, #0  ; Ce ostannyi natusk
                MOV     C, P1.3        ;         (|) C <- Znachennya tretoho tumblera
                MOV     TCOMB2.0, C    ; TCOMB2(o o o o o o o V) <- C
                MOV     C, P1.4        ;     (|)     C <- Znachennya druhoho tumblera
                MOV     TCOMB2.1, C    ; TCOMB2(o o o o o o V o) <- C
                MOV     C, P3.2        ; (|)         C <- Znachennya tretoho tumblera
                MOV     TCOMB2.2, C    ; TCOMB1(o o o o o V o o) <- C
                 
                MOV     A, TCOMB1      ; A <- First combination
                ADD     A, TCOMB2      ; A +  Second combination
                MOV     C, ACC.0       ; C <- A(o o o o o o o V)
                MOV     P3.4, C        ;     (*) Serednii svitlodiod <- C
                MOV     C, ACC.1       ; C <- A(o o o o o o V o)
                MOV     P3.5, C        ; (*)     Livyi svitlodiod <- C
                
DONE:           CLR     C              ; Ochystymo C
                RETI                   ; Dozvolymo pereryvannya iz tym samym prioritetom
                                       ; I povernemos na misce, de bulo vyklykano pereryvannya
        
END

10 Востаннє редагувалося Ярослав (17.05.2014 11:22:44)

Re: Рішення деяких задач мовою A51 середовища keil

Для гуглу: Приклад використання таймерів, мова A51

Виводити два останніх біти певного числа на 2 світлодіоди, при кожному натисканні на кнопку INT1 виводити на два сусідніх правих світлодіоди, і так по колу. В кожному разі 1 світлодіод буде вільним, в нього вивсти стан правого тумблера.

; This program was written thanks to
; [url]http://8052.com/tuttimer.phtml[/url] tutorial

; Pry kozhnomu pyatomu perepovnenni taimeru
; Znachennya kozhnoho iz dvoh svitlodiodiv peresuvaetsa
; Na susidnyi pravyi svotlodiod
; A na vilnomu svitlodiodi vidobrashaetsa stan pravoho tumblera
DSEG    AT    40h       ; Zerezervuyemo pamyat pochynauchi iz komirky 40h
        ORG   40h       ; Vstanovymo lychilnyk komand na komirku 40h
GIVN:   DS    1         ; Zarezervuyemo odyn bait dlya zminnoyi GIVN

CSEG    AT    00000h    ; Yakscho vy vykorystovuyete platu - zaminit na 0C000h
        ORG   00000h    ; Yakscho vy vykorystovuyete platu - zaminit na 0C000h 
        JMP   MAIN      ; Perestrybuemo na MAIN


MAIN:   MOV    R0, #5           ; R0 <- Skilky raziv treba zapustyty taimer
        MOV    R1, #0           ; Lichylnik dlya rozrahunku zsuviv
        MOV    GIVN, #77h       ; Dovilne chyslo
        SETB   P3.3             ; Hasymo vsi svitlodiody
        CLR    P3.4
        CLR    P3.5
        MOV    C, P1.3          ; Zapysuyemo v C stan pravoho tumblera
        CPL    C                ; Invertuyemo dlya pravilnoho zapysu v P3.3
        MOV    P3.3, C          ; Zapaluemo abo hasymo pravyi svitlodiod v
                                ; zaleshnosti vid stanu pravoho tumbleru
        MOV    A, GIVN          ; Zapysuemo v A nashe chyslo
        MOV    C, ACC.0         ; C <- A(o o o o o o o V)
        MOV    P3.4, C          ; Zapaluemo abo hasymo serednii svitlodiod v
                                ; zaleshnosti vid znaschennya ACC.0
        MOV    C, ACC.1         ; C <- A(o o o o o o V o)
        MOV    P3.5, C          ; Zapaluemo abo hasymo livyi svitlodiod v
                                ; zaleshnosti vid znaschennya ACC.1
        CLR    C                ; Ochystymo C
; Za 1  s  prohodyt 1 000 000 mashinnyh cycliv (1MC = 12 pulsiv, Chastota 12MHz)
; Za 50 ms prohodyt    50 000 mashinnyh cycliv
; Max znachennya taimera v 16-bitovomu rezhimi - 1111 1111 1111 1111 b = 65535
; Schob proishlo 50 ms, treba zavantashyty v taimer 65 535 - 50 000 = 15 535
; I pochaty vidlik 
; 15 535 = 3C AF h
; Yakscho zapuskaty taimer 5 raziv, to proide 250 ms
TIMER_1:MOV    TH0, #03Ch       ; Vstanovymo znachennya
                                ; starshogo baytu Timer 0
                                ; rivnym 03Ch (15 360)
        MOV    TL0, #0AFh       ; Vstanovymo znachennya molodshoho
                                ; baytu Timer 0
                                ; rivnym 0AFh (175)
        MOV    TMOD, #00000001b ; TMOD (89h) SFR (rehistr specialnogo pryznachennya)
                                ; [url]http://8052.com/tuttimer.phtml[/url]
                                ; Vstanovluemo bit GATE1 rivnym 0,
                                ;    dlya toho schob Timer ne zaleshav vid INT1
                                ; Vstanovymo bit C/T1 v reshym 
                                ;    ignoruvannya podii na T1(P3.5)
                                ; Vstanovymo bit T1M1 rivnym 0, 
                                ;    tomu scho my ne vykorystovuyemo Timer1
                                ; Vstanovymo bit T1M0 rivnim 0,
                                ;    tomu scho my ne vykorystovuyemo Timer1
                                ; Vstanovymo bit GATE0 rivnym 0,
                                ;    dlya toho schob Timer ne zaleshav vid INT1
                                ; Vstanovymo bit C/T1 v reshym 
                                ;    ihnoruvannya podiy T0(P3.4)
                                ; Vstanovymo bit T0M1 rivnim 0 
                                ;          i bit TOM0 rivnim 1,
                                ;    schob obraty 16-bitnyi rezhym dlya Timer0
        SETB   TR0         ; Pochynayemo vidlik
        JNB    TF0, $      ; Chekayemo 50 ms
        CLR    TF0         ; Prygotuemos do ische odnoho vykorystannya taimera
        DJNZ   R0, TIMER_1 ; Do 5 times
; Koly splyne 250 ms, treba zrobyty zsuv
; Vsoho try kombinacii 
; Vyhidna kombinaciya:
; (BIT)  (BIT)  (TUMBLER)
; Zsuv #1:
; (TUMBLER)  (BIT)  (BIT)
; Zsuv #2:
; (BIT)  (TUMBLER)  (BIT)
        INC    R1               ; Zbilshuyemo lichilnyk zsuviv na 1
        MOV    A, R1            ; A <- Znachennya R1
        SUBB   A, #1            ; Vidnimayemo vid A odynycu
        JZ     FIRST            ; Zsuv #1
        SUBB   A, #1
        JZ     SECOND           ; Zsuv #2
        SUBB   A, #1
        JZ     THIRD            ; Vyhidna kombinaciya
        
FIRST:  MOV    A, GIVN          ; A <- Nashe chyslo
        MOV    C, P1.3          ; C <- Znachennya pravoho tumblera
        MOV    P3.5, C          ; (*) ( ) ( ) <- C
                                ; Zapalymo abo pohasymo livyi svitlodiod
                                ; vidpovidno do stanu pravoho tumblera
        MOV    C, ACC.1         ; C <- A(o o o o o o V o)
        MOV    P3.4, C          ; ( ) (*) ( ) <- C
                                ; Zapalymo abo pohasymo serednii svitlodiod
                                ; v zalezhnosti vid znachennya ACC.1
        MOV    C, ACC.0         ; C <- A(o o o o o o o V)
        CPL    C                ; Invertuyemo Carry dlya pravilnoho zapysu
                                ; v P3.3
        MOV    P3.3, C          ; ( ) ( ) (*) <- C
                                ; Zapalymo abo pohasymo serednii svitlodiod
                                ; v zalezhnosti vid znachennya ACC.0
        JMP    DONE             ; Vse v normi
        
SECOND: MOV    A, GIVN          ; A <- Nashe chyslo
        MOV    C, P1.3          ; C <- Znachennya pravoho tumblera
        MOV    P3.4, C          ; ( ) (*) ( ) <- C
                                ; Zapalymo abo pohasymo serednii svitlodiod
                                ; v zalezhnosti vid znachennya ACC.1
        MOV    C, ACC.1         ; C <- A(o o o o o o V o)
        CPL    C                ; Invertuyemo Carry dlya pravilnoho zapysu
                                ; v P3.3
        MOV    P3.3, C          ; ( ) ( ) (*)
        MOV    C, ACC.0         ; C <- A(o o o o o o o V)
        MOV    P3.5, C          ; (*) ( ) ( ) <- C
                                ; Zapalymo abo pohasymo livyi svitlodiod
                                ; vidpovidno do stanu pravoho tumblera
        JMP    DONE             ; Vse v normi
        
THIRD:  MOV    A, GIVN          ; A <- Nashe chyslo
        MOV    C, P1.3          ; C <- Znachennya pravoho tumblera
        CPL    C                ; Invertuyemo Carry dlya pravilnoho zapysu
                                ; v P3.3
        MOV    P3.3, C          ; ( ) ( ) (*) <- C
        MOV    C, ACC.1         ; C <- A(o o o o o o V o)
        MOV    P3.5, C          ; (*) ( ) ( ) <- C
                                ; Zapalymo abo pohasymo livyi svitlodiod
                                ; vidpovidno do stanu pravoho tumblera
        MOV    C, ACC.0         ; C <- A(o o o o o o o V)
        MOV    P3.4, C          ; ( ) (*) ( ) <- C
                                ; Zapalymo abo pohasymo serednii svitlodiod
                                ; v zalezhnosti vid znachennya ACC.1
        MOV    R1, #0           ; Pochynayemo vidlik zsuviv spochatku
        JMP    DONE             ; Vse v normi
        
DONE:   CLR    C                ; Ochystymo C
        MOV    R0, #5           ; Pidhotuyemo R0 dlya taimeru
        JMP    TIMER_1          ; Perestrybnemo na TIMER_1
END

11

Re: Рішення деяких задач мовою A51 середовища keil

Приклад використання таймеру, мова A51, архітектура 8051

; This program was written thanks to
; http://8052.com/tuttimer.phtml tutorial

CSEG    AT    00000h    ; 0C000h for Hardware
        ORG   00000h
        JMP   MAIN

; 50 ms timer
; Uses 16-bit timer mode, so max value of timer is 65535
; There are 1 000 000 machine cycles in 1 second
; For 50 ms there are 50 000 machine cycles
; 65 535 - 10 000 = 55 535 = 3CAFh this is startup value for timer
; After timer overflows after 50 ms will pass
MAIN:   MOV    R0, #4
        CPL    P3.3
        CPL    P3.4
        CPL    P3.5
TIMER_1:MOV    TH0, #03Ch       ; Set the value of
                                ; Timer 0 high byte to
                                ; 03Ch (15 360)
        MOV    TL0, #0AFh       ; Set the value of
                                ; Timer 0 low byte to
                                ; 0AFh (175)
        MOV    TMOD, #00000001b ; TMOD (89h) SFR 
                                ; http://8052.com/tuttimer.phtml
                                ; Set GATE1 to 0, for independence of INT1
                                ; Set C/T1 for turn off counting events on T1(P3.5)
                                ; Set T1M1 to 0, becouse we are not using Timer1
                                ; Set T1M0 to 0, becouse we are not using Timer1
                                ; Set GATE0 to 0, for independence of INT0
                                ; Set C/T1 for turn off counting events on T0(P3.4)
                                ; Set T0M1 to 0 and TOM0 to 1 
                                ; to choose 16-bit mode of Timer0
        SETB   TR0         ; Starts the timer T0
        JNB    TF0, $      ; Wait up 50 ms
        CLR    TF0         ; Prepare for next use
        DJNZ   R0, TIMER_1 ; Do 4 times
        JMP    MAIN        ; Jump to MAIN point
END

12

Re: Рішення деяких задач мовою A51 середовища keil

Динамік

; Prohrama yaka vmukaye dynamik na chastoti,
; scho zadayetsa tumbleramy

BIT1    EQU   20h    ; Budemo zapysuvaty stan tumbleriv
                     ; v 20h.2, 20h.1, 20h.0, tobto BIT1.2, BIT1.1, BIT1.0

DSEG    AT    40h    ; Zareservuemo segment pamyati v pamyati DATA
        ORG   40h    ; Vstanovymo lichylnyk komand na komirku 40h
VAR1:   DS    1      ; Zareservuemo odyn bayt dlya zminnoyi VAR1
VAR2:   DS    1      ; Zareservuemo odyn bayt dlya zminnoyi VAR2

CSEG    AT    00000h       ; Yakscho vy vykorystovuyete platu - 
                           ;   to zminit na 0C000h
        ORG   00000h       ; Yakscho vy vykorystovuyete platu - 
                           ;   to zminit na 0C000h
        JMP   MAIN         ; Strubayemo na MAIN
        ORG   00013h       ; Yakscho vy vykorystovuyete platu - to zminit na 0C013h
        JMP   SWITCH_CHECK ; Treba pereviryty kombinaciyu tumbleriv
                           ; Strybayemo na SWITCH_CHECK
        
MAIN:   SETB    IT1                       ; Pereryvannya bude vyklykatys lohichnoyu
                                       ; odynyceyu na P3.3, na vidminu vid vmukannya
                                       ; lohichnym nulem na P3.3
        SETB    EA                       ; Dozvolyaemo vsi pereryvannya
        SETB    EX1                       ; Dozvolyaemo vyklykaty pereryvannya External 1
     
        CLR   P3.2         ; Vymknemo usi tumblery
        CLR   P1.4
        CLR   P1.3
        CLR   P3.5         ; Vymknemo dynamik
        MOV   VAR1, #20    ; Chyslo dlya obchyslennya chastoty, ne bilshe 36
        MOV   VAR2, #20    ; Tut bude zberihatys znachennya dlya zatrymky
       
PLAY:   SETB  P3.5       ; Vmykayemo zvuk
        MOV   R0, VAR2   ; Hotuyemo novu zatrymku
        DJNZ  R0, $      ; Robymo zatrymku
        CLR   P3.5       ; Vymykayemo zvuk
        MOV   R0, VAR2   ; Hotuyemo novu zatrymku
        DJNZ  R0, $      ; Robymo zatrymku
        JMP   PLAY       ; Zacykluemo
        
SWITCH_CHECK:    MOV   C, P1.3    ; C <- Stan tretoho tumblera
                 MOV   BIT1.2, C  ; BIT1(o o o o o V o o) <- C
                 MOV   C, P1.4    ; C <- Stan druhoho tumblera
                 MOV   BIT1.1, C  ; BIT1(o o o o o o V o) <- C
                 MOV   C, P3.2    ; C <- Stan pershoho tumblera
                 MOV   BIT1.0, C  ; BIT1(o o o o o o o V) <- C
        
                 MOV   A, BIT1    ; Rozrahovuyemo zatrymku
                 JNZ   NEXT       
                 MOV   A, #1      ; Yakscho vsi tumblery vymkneni,
                                  ;   to vykorystaty chyslo 1                 
NEXT:            MOV   B, VAR1    ; B <- Nashe chyslo
                 MUL   AB         ; Pomnoshymo A na B
                 MOV   VAR2, A    ; Zbereshemo resultat
                 RETI             ; Dozvolymo pereryvannya i povernemos
                                  ; v misce pryzupynennya
        
END