Вот. Кстати, спасибо - 16 битное умножение взято с этого форума.
Если что-то где-то написано "плохо" или не правильно, прошу простить - только учусь, даётся нелегко. Лучше подскажите/поправьте. Например, про деление интересно было бы услышать :)
.include "m48def.inc"
.def display_step = r16 ; current display step (0-3)
.def tD = r17
.def tC = r18
.def tmp = r19
.def dig1 = r20
.def dig2 = r21
.def dig3 = r22
.def dig4 = r23
.def cur_temp = r28 ; and r29
.def cur_temp_h = r29
.def adc_count = r24
.def input_counter = r25 ; counter, timeout after key pressing
;.def input_flags = r26
.def key = r26
.equ step0 = 0b00001011
.equ step1 = 0b00000111
.equ step2 = 0b00001101
.equ step3 = 0b00001110
.equ num0 = 0b10000000
.equ num1 = 0b11010011
.equ num2 = 0b01001000
.equ num3 = 0b01000010
.equ num4 = 0b00010011
.equ num5 = 0b00100010
.equ num6 = 0b00100000
.equ num7 = 0b11010010
.equ num8 = 0b00000000
.equ num9 = 0b00000010
.equ numC = 0b10101000
.equ numP = 0b00011000
.equ num_ = 0b11111011
.equ numS = 0b00100010
.equ numA = 0b00010000
.equ numF = 0b00111000
.equ numE = 0b00101000
.equ numR = 0b01111001
;Port B pins (keyboard)
.equ ROW1 =0 ;keypad input rows
.equ ROW2 =7
.equ ROW3 =6
.equ COL1 =5 ;keypad output columns
.equ COL2 =4
.equ COL3 =3
.equ COL4 =2
.equ RowsMask = 0b11000001
.equ ColsMask = 0b00111100
.eseg ;EEPROM segment
.db 1,2,3,10,4,5,6,11,7,8,9,0
.cseg
.org 0
rjmp reset
reti ;rjmp on_key
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
reti
rjmp on_clock ;TIMER0A_COMPARE
reti
reti
reti
reti
reti
reti
rjmp on_adc ;ADC conversion complete
reset:
cli
ldi tmp,low(RAMEND)
out spl,tmp
ldi tmp,high(RAMEND)
out sph,tmp
; initialize watchdog
ldi tmp, (1<<WDE | 1<<WDP1 | 1<<WDP0) ; System reset mode, timeout = 0.125 s
sts WDTCSR,tmp
wdr
; initialize ports
ldi tmp,0xFB ; initialize port D as Out (Bits except bit3 (will be INT0 input))
out DDRD,tmp
ldi tmp,0x0F ;initialize port C as Out (Bits 0, 1, 2 and 3)
out DDRC,tmp
ldi tmp,(1<<1) ;initialize port B as Out (Bit 1 for PWM)
out DDRB,tmp
ldi tmp,(1<<SE) ;turn on sleep mode
out SMCR,tmp ;
; initialize ADC
ldi tmp, (1<<REFS0 | 1<<MUX2 | 1<<MUX0)
sts ADMUX,tmp
ldi tmp, (1<<ADEN | 1<<ADIE | 0b100)
sts ADCSRA, tmp
; initialize Timer0A
ldi tmp,0x0 ;Disable timer0 interrupt
sts TIMSK0,tmp
ldi tmp,0x0 ; Timer 0 config reset (to be able to change ORC2)
out TCCR0A,tmp
ldi tmp,0x90 ; At next counter cicle (40 decimal) interrupt "on_clock" will occur. (97.5 герц на сегменте при clk=4MHz)
out OCR0A,tmp
ldi tmp,(1<<WGM01)
out TCCR0A,tmp
ldi tmp,(1<<CS02) ; clk/256 (результирующую частоту смотри выше)
out TCCR0B,tmp
ldi tmp,(1<<OCIE0A) ;Enable timer0A interrupt
sts TIMSK0,tmp
; initialize Timer1A as PWM driver
ldi ZH,high(0)
ldi ZL,low(0)
sts OCR1AH,ZH
sts OCR1AL,ZL
ldi tmp,(1<<COM1A1 | 1<<WGM11 | 1<<WGM10)
sts TCCR1A,tmp
ldi tmp,(1<<CS10 | 1<<CS11 | 1<<WGM12)
sts TCCR1B,tmp
; initialize INT0
; etc.
ldi display_step,0x00
ldi dig1,numS
ldi dig2,numA
ldi dig3,numF
ldi dig4,numE
ldi adc_count,1
main:
sei
sleep
rjmp main
on_clock:
cli
; watchdog reset
wdr
; keyboard
ldi tmp,0
out PORTB,tmp
ldi tmp,(1<<1 | ColsMask)
out DDRB,tmp
ldi tmp,RowsMask
out PORTB,tmp
rcall port_settle
ldi key,0
sbis PINB,ROW1 ;find row of keypress
ldi key,1
sbis PINB,ROW2
ldi key,5
sbis PINB,ROW3
ldi key,9
ldi tmp,0
out PORTB,tmp
ldi tmp,(1<<1 | RowsMask)
out DDRB,tmp
ldi tmp,ColsMask
out PORTB,tmp
rcall port_settle
ldi tmp,0
sbis PINB,COL1 ;find column of keypress
ldi tmp,0
sbis PINB,COL2
ldi tmp,1
sbis PINB,COL3
ldi tmp,2
sbis PINB,COL4
ldi tmp,3
add key,tmp
cpi key,0
breq display
dec key
out EEARL,key ;address EEPROM
sbi EECR,EERE ;strobe EEPROM
;Глюк микроконтроллера. Эти нопы похоже на дырке в памяти (Задержка в цикле не спасает):
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
in tmp,EEDR
lsl tmp
rcall get_symbol
mov dig1,tmp
ldi dig2,num_
ldi dig3,num_
ldi dig4,num_
display:
; display
inc display_step
cbr display_step,0b11111100
mov tmp, display_step
lsl tmp ; multiply 2
lsl tmp ; multiply 2
rcall step_rt
cbr tD, 0b00000100
out PORTD, tD
out PORTC, tC
adc_work:
dec adc_count
brne skip_adc
lds tmp,ADCSRA
sbr tmp,(1<<ADEN); conversion starts automatically on sleep entering in main
sts ADCSRA,tmp
skip_adc:
reti
step_rt:
ldi ZL,low(step_jump)
ldi ZH,high(step_jump)
add ZL,tmp ; jump to adr (step_jump + step# * 4)
ijmp
step_jump:
mov tD,dig1
ldi tC,step0
nop
ret
mov tD,dig2
ldi tC,step1
nop
ret
mov tD,dig3
ldi tC,step2
nop
ret
mov tD,dig4
ldi tC,step3
nop
ret
; без оптимизации, наколдовал как смог. Нужно обдумать (отсюда и до конца):
on_adc:
cli
; Calculations to celsius, line dependence (y=kx+b); b=15, k=0.718
; r15:r14 = ADC data
; tD:tC = "k" from line formula
; r11:r10:r9:r8 = result
lds r14, ADCL
lds r15, ADCH
ldi tD, low(47055)
ldi tC, high(47055)
mul r15, tC
movw r10, r0
mul r14, tD
mov r9, r1
mul r15, tD
add r9, r0
adc r10, r1
adc r11, r2
mul tC, r14
add r9, r0
adc r10, r1
adc r11, r2
ldi tmp, 15 ; "b" from line formula
add r10, tmp
movw cur_temp, r10
mov tC, cur_temp_h
mov tD, cur_temp
rcall div100
mov cur_temp, tmp
mov tmp, r0
cpi tmp, 0
brne ne1
ldi tmp,10
ne1:
lsl tmp
rcall get_symbol
mov dig1,tmp
mov tmp, cur_temp
rcall div10
mov cur_temp, tmp
mov tmp, r0
cpi tmp, 0
brne ne2
cpi dig1, num_
brne ne2
ldi tmp,10
ne2:
lsl tmp
rcall get_symbol
mov dig2,tmp
mov tmp, cur_temp
lsl tmp
rcall get_symbol
mov dig3,tmp
ldi dig4,numC
ldi adc_count,200
;disable adc (for preventing auto noice-reduced execution on next sleep command in main)
lds tmp,ADCSRA
cbr tmp,(1<<ADEN)
sts ADCSRA,tmp
reti
;================================================================
div10:
clr R0
div10_loop:
cpi tmp, 10
brlo div10_exit
subi tmp, 10
inc R0
rjmp div10_loop
div10_exit:
ret
div100: ; 16 bit division
clr R0
div100_loop:
cpi tD, 100
brlo div100_lo
subi tD, 100
inc R0
rjmp div100_loop
div100_lo:
cpi tC, 0
breq div100_exit
ldi tmp,0xFF
sub tmp,tD
mov tD,tmp
dec tC
inc R0
rjmp div100_loop
div100_exit:
mov tmp,tD
ret
;================================================================
get_symbol:
cpi tmp,20
brsh symbol_blank
ldi ZL,low(symbol_jump)
ldi ZH,high(symbol_jump)
add ZL,tmp ; jump to adr (symbol_jump + step# * 2)
ijmp
symbol_jump:
ldi tmp,num0
ret
ldi tmp,num1
ret
ldi tmp,num2
ret
ldi tmp,num3
ret
ldi tmp,num4
ret
ldi tmp,num5
ret
ldi tmp,num6
ret
ldi tmp,num7
ret
ldi tmp,num8
ret
ldi tmp,num9
ret
symbol_blank:
ldi tmp,num_
ret
; Settling time delay for port to stabilise
port_settle:
ldi tmp,255
tagain:
dec tmp
brne tagain
ret
-
- Глюк найден. Вопрос решен. Всем спасибо и прошу прощения. mavpsk(557 знак., 07.11.2008 22:36, )
- В программах для PIC16 я всегда заставлял ассемблер проверять, что таблица не пересекает границу 256 байт. Проверка на этапе компиляции дешевле, чем пересылка байтов на этапе выполнения. - Сергей Борщ(08.11.2008 20:32)
- А надо всегда индекс задавать/модифицировать полностью, а не только zl MBedder(408 знак., 07.11.2008 23:36)
- Да да. Это я и имел в виду. :) - mavpsk(07.11.2008 23:49, )
- Справедливости ради решил передвинуть нопы как писал раньше (изначально ошибся на строчку)... Всё работает правильно... Решил подвигать до тех пор пока перестанет работать (метод научного тыка так сказать)... Ну и пошло поехало. В итоге я ими допрыгал до mavpsk(219 знак., 07.11.2008 22:15, )
- См. выше - MBedder(07.11.2008 23:37)
- Глюк найден. Вопрос решен. Всем спасибо и прошу прощения. mavpsk(557 знак., 07.11.2008 22:36, )