ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Суббота
4 мая
137908 Топик полностью
mavpsk (07.11.2008 21:40, просмотров: 1) ответил MBedder на Дай сюда весь без исключения код - найдем глюку сообща
Вот. Кстати, спасибо - 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