subroutine.asm 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. ;---------------------------------------;
  2. ; ;
  3. ; Подпрограмки, которые я успел наваять ;
  4. ; ;
  5. ;---------------------------------------;
  6. LSB (Least Significant Bit) - младший значащий бит,
  7. MSB (Most Significant Bit) - старший значащий бит.
  8. ; байты для вывода 0-9A-F на индикаторы, без точки, общий катод
  9. LEDnd: .DB 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71
  10. ; байты для вывода 0-9A-F на индикаторы, с точкой
  11. ledwd: .DB 0xf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0xf7,0xfc,0xb9,0xde,0xf9,0xf1
  12. "A" - 0x77
  13. "b" - 0x7C
  14. "c" - 0x58, "C" - 0x39
  15. "d" - 0x5E
  16. "E" - 0x79
  17. "F" - 0x71
  18. "r" - 0x50
  19. "h" - 0x56, "H" - 0x76
  20. "i" - 0x04, "I" - 0x06
  21. "J" - 0x1E
  22. "L" - 0x38
  23. "P" - 0x73
  24. "u" - 0x1C, "U" - 0x3E
  25. "Y" - 0x6E
  26. ;*******************************************************************
  27. ; вывод в компорт байт в HEX-виде
  28. ; исходный байт а r17, портим r16
  29. OUTHEX: push r17
  30. andi r17,0b11110000 ; старший полубайт
  31. swap r17
  32. rcall TOASCII
  33. mov r16,r17
  34. rcall USART_TX ; выводим старший байт
  35. pop r17
  36. andi r17,0b00001111 ; младший полубайт
  37. mov r16,r17
  38. rcall TOASCII
  39. mov r16,r17
  40. rcall USART_TX ; выводим младший байт
  41. ret
  42. ;*******************************************************************
  43. ; переводит младший полубайт в ASCII-код символа
  44. ; исходный и итоговый байт в r16
  45. TOASCII:
  46. andi R16,0x0F ; очищаем ненужные биты
  47. cpi R16,0x0A
  48. brsh ADDA
  49. subi R16,-0x30 ; ASCII '0'
  50. ret
  51. ADDA: subi R16,-0x37 ; + 0x0A = ASCII 'A'
  52. ret
  53. ;*******************************************************************
  54. ; вывод байта в уарт (не моё, из мануала :-)
  55. USART_TX:
  56. sbis UCSRA,UDRE ; Wait for empty transmit buffer
  57. rjmp USART_TX
  58. out UDR,r16 ; Put data (r16) into buffer, sends the data
  59. ret
  60. ;*******************************************************************
  61. ; работа с EEPROM
  62. ;в ZH:ZL - адрес EEPROM куда писать
  63. ;в temp - записываемый байт
  64. WriteEEP:
  65. sbic EECR,EEWE ; ждем очистки бита
  66. rjmp WriteEEP ; разрешения записи EEWE
  67. cli ; запрещаем прерывания
  68. out EEARH,ZH ; старший байт адреса
  69. out EEARL,ZL ; младший байт адреса
  70. out EEDR,temp ; данные
  71. sbi EECR,EEMWE ; взводим предохранитель
  72. sbi EECR,EEWE ; записываем байт
  73. sei ; разрешаем прерывания
  74. ret ; (конец WriteEEP)
  75. ; в ZH:ZL - адрес откуда читать
  76. ; возврат temp - прочтенный байт
  77. ReadEEP:
  78. sbic EECR,EEWE ; ожидание очистки флага записи
  79. rjmp ReadEEP
  80. out EEARH,ZH ; старший адреса
  81. out EEARL,ZL ; младший адреса
  82. sbi EECR,EERE ; бит чтения
  83. in temp,EEDR ; чтение
  84. ret ; конец ReadEEP
  85. ;*******************************************************************
  86. ; sleep
  87. SPIM: ldi temp,(1<<SE) ; ко сну
  88. out MCUCR,temp
  89. sleep ; спим. тупой идл
  90. clr temp
  91. out MCUCR,temp ; со сна
  92. ret
  93. ;*******************************************************************
  94. ; маленький, простенький диспетчер :-)
  95. ; если delay > 0 -- будем спать, пока обработчик прерываний не доведёт
  96. ; счётчик до 0. по флагам можем вызывать разные подпрограммы
  97. ; минимальный шаг задержки == периоду таймера
  98. DISPATCHER:
  99. PUSHF
  100. sbrc flags,SADC ; сброшен - простой сон
  101. rcall MEASURE
  102. outi MCUCR,1<<SE ; простой режим сна
  103. SLL: sleep ; спим.
  104. tst delay ; если сч не 0
  105. brne SLL ; спим до сл. прерывания
  106. outi MCUCR,0 ; со сна
  107. POPF
  108. ret
  109. ; и в обработчике прерываний от таймера:
  110. tst delay ; сч пустой?
  111. breq PC+2 ; да, не трогаем
  112. dec delay ; иначе - уменьшаем
  113. ;*******************************************************************
  114. ; ADC Noise Reduction Mode
  115. ADCNR: ldi temp,1<<SE|1<<SM0
  116. out MCUCR,temp
  117. sleep ; пока проц спит, АЦП меряет сигнал
  118. clr temp
  119. out MCUCR,temp ; со сна
  120. ret
  121. ;*******************************************************************
  122. ;запись через SPI. посылаемый байт в data_out
  123. ; этот конкрентный случай - для регистров 595
  124. RW_SPI: ldi temp,8 ; счетчик бит
  125. SPIL: cbi PORTB,SCK ; выдали строб
  126. lsl data_out ; старший бит в перенос
  127. brcc PUT_0 ; если в переносе 0 — перейти
  128. sbi PORTB,MOSI ; выдали 1
  129. rjmp SPIE
  130. PUT_0: cbi PORTB,MOSI
  131. nop ; задержка на один такт
  132. SPIE: sbi PORTB,sck ; защёлкнули строб
  133. dec temp
  134. brne SPIL
  135. ret
  136. ; пример использования:
  137. cbi PORTB,LCH
  138. ldi data_out,0x3f
  139. rcall RW_SPI
  140. ldi data_out,0x06
  141. rcall RW_SPI
  142. sbi PORTB,LCH ; регистры - на экран!
  143. ;***************************************************************************
  144. ;* "bin2BCD24" - 24-bit Binary to 8xBCD conversion
  145. ;*
  146. ;* This subroutine converts a 24-bit number (fbinH:fbinL) to a 8-digit
  147. ;* packed BCD number represented by 4 bytes (tBCD3:tBCD2:tBCD1:tBCD0).
  148. ;* MSD of the 8-digit number is placed in the lowermost nibble of tBCD3.
  149. ;*
  150. ;* Low registers used :4 (tBCD0,tBCD1,tBCD2,tBCD3)
  151. ;* High registers used :4 (fbinL,fbinM,fbinH,tmp1,temp)
  152. ;* Pointers used :Z
  153. ;* портим: temp, tmp1
  154. ;***************************************************************************
  155. .equ AtBCD0 = 0
  156. .equ AtBCD3 = 3
  157. .def tBCD0 = r0 ;BCD value digits 0 and 1
  158. .def tBCD1 = r1 ;BCD value digits 2 and 3
  159. .def tBCD2 = r2 ;BCD value digits 4 and 5
  160. .def tBCD3 = r3 ;BCD value digits 6 and 7
  161. .def fbinH = r10 ;binary value High byte
  162. .def fbinH = r11 ;binary value Middle byte
  163. .def fbinL = r12 ;binary value Low byte
  164. ; ZL, ZH
  165. bin2BCD24:
  166. ldi tmp1,24 ; Init loop counter
  167. clr tBCD3 ; clear result (4 bytes)
  168. clr tBCD2
  169. clr tBCD1
  170. clr tBCD0
  171. clr ZH ; clear ZH (not needed for AT90Sxx0x)
  172. bBCDx_1:lsl fbinL ; shift input value
  173. rol fbinM ;
  174. rol fbinH ; through all bytes
  175. rol tBCD0
  176. rol tBCD1
  177. rol tBCD2
  178. rol tBCD3
  179. dec tmp1 ; decrement loop counter
  180. brne bBCDx_2 ; if counter not zero
  181. ret ; return
  182. bBCDx_2:ldi r30,AtBCD3+1 ; Z points to result MSB + 1
  183. bBCDx_3:
  184. ld temp,-Z ; get (Z) with pre-decrement
  185. subi temp,-$03 ; add 0x03
  186. sbrc temp,3 ; if bit 3 not clear
  187. st Z,temp ; store back
  188. ld temp,Z ; get (Z)
  189. subi temp,-$30 ; add 0x30
  190. sbrc temp,7 ; if bit 7 not clear
  191. st Z,temp ; store back
  192. cpi ZL,AtBCD0 ; done all three?
  193. brne bBCDx_3 ; loop again if not
  194. rjmp bBCDx_1
  195. ;***************************************************************************
  196. ; Исправленная процедура из 204-го аппнота
  197. ; родная нормально преобразовывает только числа от 0 до 99
  198. ; входное число в R16, выход: R17(сотни) и R16(десятки и единицы)
  199. ; в R17 копятся десятки, в R18 сотни, в R16 - остаток, единицы.
  200. ; потом R17 складывается с R16, а R18 переносится в R17
  201. bin2bcd8:
  202. push R18
  203. clr R18
  204. clr R17 ;clear result MSD
  205. bBCD8_1:subi R16,10 ;input = input - 10
  206. brcs bBCD8_2 ;abort if carry set
  207. subi R17,-$10 ;tBCDH = tBCDH + 10
  208. cpi R17,0xA0
  209. brlo bBCD8_1
  210. inc R18
  211. subi R17,0xA0
  212. rjmp bBCD8_1 ;loop again
  213. bBCD8_2:subi R16,-10 ;compensate extra subtraction
  214. add R16,R17
  215. mov R17,R18
  216. pop R18
  217. ret