Приложение А. Листинг управляющей программы
.include "m16def.inc";Включить определения для контроллера Atmega16 .def scancode=r13 .def key=r14 .def pointer=r15; используется для ввода данных .equ entercode=0xD7;код клавиши ввода .DSEG; резервирование памяти status:.BYTE 1;байт статуса weight:.BYTE 2;вес price:.BYTE 2;цена cost:.BYTE 2;стоимость key_table.BYTE 10;таблица сканкодов dysplay_table:.BYTE 16;выделить 16 байт как буфер дисплея .CSEG ; перед началом выполнения программы контроллер проверяет векторы прерываний rjmp RESET; Reset Handler nop reti EXT_INT0; INT0 Handler nop reti EXT_INT1; INT1 Handler nop reti TIM2_COMP; Timer2 Compare Handler nop reti;TIM2_OVF; Timer2 Overflow Handler nop reti;TIM1_CAPT; Timer1 Capture Handler nop reti;TIM1_COMPA; Timer1 CompareA Handler nop reti;TIM1_COMPB; Timer1 CompareB Handler nop reti;TIM1_OVF; Timer1 Overflow Handler nop reti;TIM0_OVF; Timer0 Overflow Handler nop reti;SPI_STC; SPI Transfer Complete Handler nop reti;USART_RXC; USART0 RX Complete Handler nop reti;USART_DRE; USART0,UDR Empty Handler nop reti;USART_TXC; USART0 TX Complete Handler nop reti;ADC; ADC Conversion Complete Handler nop reti;EE_RDY; EEPROM Ready Handler nop reti;ANA_COMP; Analog Comparator Handler nop reti;TWI; Two-wire Serial Interface Interrupt Handler nop reti;TIM0_COMP; Timer0 Compare Handler nop reti;EXT_INT2; INT2 Handler nop reti;SPM_RDY; SPM Ready Handler nop ;инициализация reset: out DDRB, 0xF0; Старшая тетрада порта PB настраивается на вывод, младшая – на ввод out DDRС, 0xFF; Порты PC и PB настраиваются на вывод out DDRD, 0xFF; out ADMUX, 0x40; АЦП работает с внешним опорным сигналом, канал 0. out SFIOR, 0x00; АЦП работает автоматического обновления данных. out ADCSRA, 0xC0; Запуск АЦП. ldi r26,low(key_table);заполнение таблицы скан-кодов ldi r27,high(key_table) ldi r16,0xE7; клавиша «0» st X+,r16 ldi r16,0xEE; клавиша «1» st X+,r16 ldi r16,0xDE; клавиша «2» st X+,r16 ldi r16,0xBE; клавиша «3» st X+,r16 ldi r16,0xED; клавиша «4» st X+,r16 ldi r16,0xDD; клавиша «5» st X+,r16 ldi r16,0xBD; клавиша «6» st X+,r16 ldi r16,0xEB; клавиша «7» st X+,r16 ldi r16,0xDB; клавиша «8» st X+,r16 ldi r16,0xBB; клавиша «9» st X+,r16 ;опрос клавиатуры begin: ldi scancode,0xFF ldi r19,0x00; обнуление счетчика антидребезгового цикла
l3: ldi r16,0x01; задается опрашиваемая линия l1: mov r17,temp1; номер опрашиваемой линии преобразуется для обнуления neg r17; соответствующего вывода out PORTB,r17 in r17, PINB; чтение сканкода ori r17,0x80 cpi r17,0xFF;если клавиша нажата, то запомнить ее сканкод для breq l4; обработки в антидребезговом цикле mov r18,r17 l4: lsl r16;следующая линия cpi r16,0x10 brne l1;если опрошены все линии, переходим к следующему шагу cpi r19,0x00 breq l2 cp r18,scancode brne l5;если текущий скан-код не равен предыдущему, то нажатие случайное l2: mov scancode,r18 inc r19 cpi r19,0x03;антидребезговый цикл brne l3 ;опрос режима l5: ldi r26,low(status) ldi r27,high(status) ld r16,X; загружается адрес байта состояния cpi r16,0x01 breq l6;если status=1, то перейти к вводу данных cpi scancode,entercode; если не нажат «Ввод», brne l7; то перейти пересчету данных ldi r16,0x01; иначе войти в режим ввода данных st X,r16 ldi r16,0 move pointer,r16 jmp display ;пересчет данных l7: in r16,low(ADC);чтение АЦП in r17,high(ADC) ;пересчет единиц АЦП в реальный вес. Вес равен 1000*ADC/1024, операции умножения и деления на константу реализованы путем операций сдвига и вычитания mov r18,r16 mov r19,r17 lsl r16 rol r17 lsl r16 rol r17 lsl r16 rol r17 lsl r16 rol r17 lsl r16 rol r17 lsl r16 rol r17 sub r16,r18 sbc r17,r19 sub r16,r18 sbc r17,r19 sub r16,r18 sbc r17,r19 lsr r17 ror r16 lsr r17 ror r16 lsr r17 ror r16 lsr r17 ror r16 lsr r17 ror r16 lsr r17 ror r16 ldi r26,low(weight) ldi r27,high(weight) st X+,r16 st X+,r17 ;расчет стоимости ld X+,r18;загрузка значения цены из памяти ld X+,r19;загрузка значения цены из памяти ldi r20,0 ldi r21,0 ldi r22,0 ldi r23,0 ldi r24,0 ldi r25,0 ldi r0,0 ldi r2,0 ldi r3,0 ;умножение цены на вес l11: add r20,weight_l adc r21,weight_h adc r22,r0 adc r23,r3 inc r24 adc r25,r0 cp r24,r18 cpc r25,r19 brne l11 ;деление на тысячу l12: ldi r24,0xE8 ldi r25,0x03 cp r20,r24 cpc r21,r25 ldi r24,0 cpc r22,r24 cpc r23,r24 brne l13 ldi r24,0xE8 sub r20,r24 sbc r21,r25 sbc r22,r0 sbc r23,r0 ldi r24 add r2,r24 adc r3,r0 rjmp l12 l13: st X+,r20;загрузка стоимости в память st X+,r21 ;преобразование чисел в символы ldi R26,low(dysplay_table); загрузка начального адреса буфера ldi R27,high(dysplay_table); дисплея в регистр X. ldi r16,0; заполнение буфера нулевыми символами ldi r17,0 cpi r16,16
brlo l14 st X,r17 inc к16 l14: ldi r28,low(weight) ldi r29,high(weight) ld Y+,r16; загрузка веса из памяти ld Y+,r17 rjmp IntToStr ldi r26,low(dysplay_table+4); загрузка начального адреса буфера ldi r27,high(dysplay_table+4); дисплея в регистр X. ld Y+,r16; загрузка цены из памяти ld Y+,r17 rjmp IntToStr ldi r26,low(dysplay_table+8); загрузка начального адреса буфера ldi r27,high(dysplay_table+8); дисплея в регистр X. ld Y+,r16; загрузка стоимости из памяти ld Y+,r17 rjmp IntToStr rjmp display ;считывание данных с клавиатуры l6: ldi r26,low(key_table); загрузка начального адреса ldi r27,high(key_table); таблицы скан-кодов lde r17,0 l15: ld r16,X+ cp r16,scancode; расшифровка скан-кода breq l16; если нужный скан-код найден, переход к заполнению данных inc r17 cpi r17,11 breq l18 rjmp l15 l18: cpi scancode,0xD7; обработка нажатия ввода brne display ldi r20,0 ldi r28,low(dysplay_table +3); загрузка конечного адреса ldi r29,high(dysplay_table +3); символов, отображающих цену ;перевод данных из строкового вида в числовой l19: ld r16,Y- ldi r17,0 mov r18,r16 mov r19,r17 lsl r16 rsl r17 lsl r16 rsl r17 lsl r16 rsl r17 lsl r16 rsl r17 add r16,r18 adc r17,r19 add r16,r18 adc r17,r19 ld r18,Y ldi r19,0 add r16,r18 adc r17,r19 inc r20 cpi r20,3 brne l19 ldi r28,low(price); загрузка конечного адреса ldi r29,high(dysplay_table +3); символов, отображающих цену st Y+,r16 st Y+,r17 jmp display l16: mov key,r17 mov r17,pointer cpi r17,0 brne l18 ; если заполнение начато заново, обнуляется вся строка ldi r28,low(dysplay_table); загрузка начального адреса символов, ldi r29,high(dysplay_table); отображающих цену ldi r16,0 st Y+,r16 st Y+,r16 st Y+,r16 st Y+,r16 ldi r26,low(dysplay_table +7); загрузка адреса конца строки, ldi r27,high(dysplay_table +7); отображающей цену ldi r28,low(dysplay_table +6); загрузка адреса предпоследнего ldi r29,high(dysplay_table +6); символа строки, отображающей цену ld r16,Y- st X-,R16 ld r16,Y- st X-,R16 ld r16,Y- st X-,R16 st Y,key; запись символа ldi r16,1 add r17,r16 cpi r17,4 brlo l17 ldi r17,0 l17: mov pointer,r17 ;отображение на дисплее display: ldi r26,low(dysplay_table); загрузка начального адреса буфера ldi r27,high(dysplay_table); дисплея в регистр X. ldi r16,0x00; r16 используется для адресации индикатора l8: ld r17,X+; r17 используется для временного хранения кода символа andi r16,0x0F lsl r17;формирование байта для отправки на дисплей lsl r17 lsl r17 lsl r17 add r17,r16 out PORTC,r17 cpi r16,0x01 breq l9 cpi r16,0x05 breq l9 cpi r16,0x0A breq l9 out PORTD,0x01; гашение запятой rjmp l10 l9: out PORTD,0x00; отображение запятой l10: cpi r16,0x0F brne l8 ;подпрограмма преобразования числа в строку IntToStr: ldi r20,10 ldi r21,0 ITS4: cp r16,r20 cpc r17,r21 brlo ITS1 mov r18,r16 mov r19,r16 ldi r16,0 ldi r17,0 ITS2: cp r18,r20 cpc r19,r21 brlo ITS3
sub r18,r20 sbs r19,r21 inc r16 adc r17,r19 rjmp ITS2 ITS3: ld X+,r16 rjmp ITS4 ITS1: ld X+,r16 reti
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|