123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- ;---------------------------------------;
- ; ;
- ; Подпрограмки, которые я успел наваять ;
- ; ;
- ;---------------------------------------;
- LSB (Least Significant Bit) - младший значащий бит,
- MSB (Most Significant Bit) - старший значащий бит.
- ; байты для вывода 0-9A-F на индикаторы, без точки, общий катод
- LEDnd: .DB 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71
- ; байты для вывода 0-9A-F на индикаторы, с точкой
- ledwd: .DB 0xf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0xf7,0xfc,0xb9,0xde,0xf9,0xf1
- "A" - 0x77
- "b" - 0x7C
- "c" - 0x58, "C" - 0x39
- "d" - 0x5E
- "E" - 0x79
- "F" - 0x71
- "r" - 0x50
- "h" - 0x56, "H" - 0x76
- "i" - 0x04, "I" - 0x06
- "J" - 0x1E
- "L" - 0x38
- "P" - 0x73
- "u" - 0x1C, "U" - 0x3E
- "Y" - 0x6E
- ;*******************************************************************
- ; вывод в компорт байт в HEX-виде
- ; исходный байт а r17, портим r16
- OUTHEX: push r17
- andi r17,0b11110000 ; старший полубайт
- swap r17
- rcall TOASCII
- mov r16,r17
- rcall USART_TX ; выводим старший байт
- pop r17
- andi r17,0b00001111 ; младший полубайт
- mov r16,r17
- rcall TOASCII
- mov r16,r17
- rcall USART_TX ; выводим младший байт
- ret
- ;*******************************************************************
- ; переводит младший полубайт в ASCII-код символа
- ; исходный и итоговый байт в r16
- TOASCII:
- andi R16,0x0F ; очищаем ненужные биты
- cpi R16,0x0A
- brsh ADDA
- subi R16,-0x30 ; ASCII '0'
- ret
- ADDA: subi R16,-0x37 ; + 0x0A = ASCII 'A'
- ret
- ;*******************************************************************
- ; вывод байта в уарт (не моё, из мануала :-)
- USART_TX:
- sbis UCSRA,UDRE ; Wait for empty transmit buffer
- rjmp USART_TX
- out UDR,r16 ; Put data (r16) into buffer, sends the data
- ret
- ;*******************************************************************
- ; работа с EEPROM
- ;в ZH:ZL - адрес EEPROM куда писать
- ;в temp - записываемый байт
- WriteEEP:
- sbic EECR,EEWE ; ждем очистки бита
- rjmp WriteEEP ; разрешения записи EEWE
- cli ; запрещаем прерывания
- out EEARH,ZH ; старший байт адреса
- out EEARL,ZL ; младший байт адреса
- out EEDR,temp ; данные
- sbi EECR,EEMWE ; взводим предохранитель
- sbi EECR,EEWE ; записываем байт
- sei ; разрешаем прерывания
- ret ; (конец WriteEEP)
- ; в ZH:ZL - адрес откуда читать
- ; возврат temp - прочтенный байт
- ReadEEP:
- sbic EECR,EEWE ; ожидание очистки флага записи
- rjmp ReadEEP
- out EEARH,ZH ; старший адреса
- out EEARL,ZL ; младший адреса
- sbi EECR,EERE ; бит чтения
- in temp,EEDR ; чтение
- ret ; конец ReadEEP
- ;*******************************************************************
- ; sleep
- SPIM: ldi temp,(1<<SE) ; ко сну
- out MCUCR,temp
- sleep ; спим. тупой идл
- clr temp
- out MCUCR,temp ; со сна
- ret
- ;*******************************************************************
- ; маленький, простенький диспетчер :-)
- ; если delay > 0 -- будем спать, пока обработчик прерываний не доведёт
- ; счётчик до 0. по флагам можем вызывать разные подпрограммы
- ; минимальный шаг задержки == периоду таймера
- DISPATCHER:
- PUSHF
- sbrc flags,SADC ; сброшен - простой сон
- rcall MEASURE
- outi MCUCR,1<<SE ; простой режим сна
- SLL: sleep ; спим.
- tst delay ; если сч не 0
- brne SLL ; спим до сл. прерывания
- outi MCUCR,0 ; со сна
- POPF
- ret
- ; и в обработчике прерываний от таймера:
- tst delay ; сч пустой?
- breq PC+2 ; да, не трогаем
- dec delay ; иначе - уменьшаем
- ;*******************************************************************
- ; ADC Noise Reduction Mode
- ADCNR: ldi temp,1<<SE|1<<SM0
- out MCUCR,temp
- sleep ; пока проц спит, АЦП меряет сигнал
- clr temp
- out MCUCR,temp ; со сна
- ret
- ;*******************************************************************
- ;запись через SPI. посылаемый байт в data_out
- ; этот конкрентный случай - для регистров 595
- RW_SPI: ldi temp,8 ; счетчик бит
- SPIL: cbi PORTB,SCK ; выдали строб
- lsl data_out ; старший бит в перенос
- brcc PUT_0 ; если в переносе 0 — перейти
- sbi PORTB,MOSI ; выдали 1
- rjmp SPIE
- PUT_0: cbi PORTB,MOSI
- nop ; задержка на один такт
- SPIE: sbi PORTB,sck ; защёлкнули строб
- dec temp
- brne SPIL
- ret
- ; пример использования:
- cbi PORTB,LCH
- ldi data_out,0x3f
- rcall RW_SPI
- ldi data_out,0x06
- rcall RW_SPI
- sbi PORTB,LCH ; регистры - на экран!
- ;***************************************************************************
- ;* "bin2BCD24" - 24-bit Binary to 8xBCD conversion
- ;*
- ;* This subroutine converts a 24-bit number (fbinH:fbinL) to a 8-digit
- ;* packed BCD number represented by 4 bytes (tBCD3:tBCD2:tBCD1:tBCD0).
- ;* MSD of the 8-digit number is placed in the lowermost nibble of tBCD3.
- ;*
- ;* Low registers used :4 (tBCD0,tBCD1,tBCD2,tBCD3)
- ;* High registers used :4 (fbinL,fbinM,fbinH,tmp1,temp)
- ;* Pointers used :Z
- ;* портим: temp, tmp1
- ;***************************************************************************
- .equ AtBCD0 = 0
- .equ AtBCD3 = 3
- .def tBCD0 = r0 ;BCD value digits 0 and 1
- .def tBCD1 = r1 ;BCD value digits 2 and 3
- .def tBCD2 = r2 ;BCD value digits 4 and 5
- .def tBCD3 = r3 ;BCD value digits 6 and 7
- .def fbinH = r10 ;binary value High byte
- .def fbinH = r11 ;binary value Middle byte
- .def fbinL = r12 ;binary value Low byte
- ; ZL, ZH
- bin2BCD24:
- ldi tmp1,24 ; Init loop counter
- clr tBCD3 ; clear result (4 bytes)
- clr tBCD2
- clr tBCD1
- clr tBCD0
- clr ZH ; clear ZH (not needed for AT90Sxx0x)
- bBCDx_1:lsl fbinL ; shift input value
- rol fbinM ;
- rol fbinH ; through all bytes
- rol tBCD0
- rol tBCD1
- rol tBCD2
- rol tBCD3
- dec tmp1 ; decrement loop counter
- brne bBCDx_2 ; if counter not zero
- ret ; return
- bBCDx_2:ldi r30,AtBCD3+1 ; Z points to result MSB + 1
- bBCDx_3:
- ld temp,-Z ; get (Z) with pre-decrement
- subi temp,-$03 ; add 0x03
- sbrc temp,3 ; if bit 3 not clear
- st Z,temp ; store back
- ld temp,Z ; get (Z)
- subi temp,-$30 ; add 0x30
- sbrc temp,7 ; if bit 7 not clear
- st Z,temp ; store back
- cpi ZL,AtBCD0 ; done all three?
- brne bBCDx_3 ; loop again if not
- rjmp bBCDx_1
- ;***************************************************************************
- ; Исправленная процедура из 204-го аппнота
- ; родная нормально преобразовывает только числа от 0 до 99
- ; входное число в R16, выход: R17(сотни) и R16(десятки и единицы)
- ; в R17 копятся десятки, в R18 сотни, в R16 - остаток, единицы.
- ; потом R17 складывается с R16, а R18 переносится в R17
- bin2bcd8:
- push R18
- clr R18
- clr R17 ;clear result MSD
- bBCD8_1:subi R16,10 ;input = input - 10
- brcs bBCD8_2 ;abort if carry set
- subi R17,-$10 ;tBCDH = tBCDH + 10
- cpi R17,0xA0
- brlo bBCD8_1
- inc R18
- subi R17,0xA0
- rjmp bBCD8_1 ;loop again
- bBCD8_2:subi R16,-10 ;compensate extra subtraction
- add R16,R17
- mov R17,R18
- pop R18
- ret
|