Или не переводится (ср. "вычесть все цифры в числе").
Компактно - сдвигами в цикле.
Быстро - по таблице.
Для любой хотелки должна быть специальная кнопка в AVR studio 4, надо найти её в ней - хм...
Код: Выделить всё
======== r16 - регистр с байтом
CLR R18
CLR R19
LDI R20,1
write_bit:
SBRC R16,0
EOR R19,R20
ROR R16
INC R18
CPI R18,8
BRNE write_bit
;=========== в регистре R19 - результат
Код: Выделить всё
.def MyByte = R16
.def OnesCounter = R17
.def BitCounter = R18 ; программа должна быть читаемой, а не шифрованной! кульксакеп-стайл
ldi BitCounter, 8 ; такие счётчики практичнее вычитать, чем прибавлять - цикл так и эдак заканчивается по условию brne, но вычитание само по себе ставит флаг Z, без дополнительных сравнений
nextbit:
rol MyByte ; или ror, нам без разницы, с какой стороны начинать считать единицы (или нули, по сути то же самое) - интересует только их общее количество... можно даже lsl или lsr
brcc pc + 2 ; или brcs, по сути получится то же самое, но наоборот
inc OnesCounter
dec BitCounter
brne nextbit
; OnesCounter = количество единиц в MyByte (или нулей, по сути то же самое)
; в нечётном числе младший бит =1, в чётном =0
; отдельный вопрос - нужен ли нам дальше исходный MyByte... в реальной ситуации скорее нет, чем даКод: Выделить всё
ldi ZH, high(Table * 2)
ldi ZL, low(Table * 2)
add ZL, MyByte
brcc pc + 2
inc ZH
lpm OnesCounter, Z
Table:
.db 0 ; количество единиц в числе 0b00000000
.db 1 ; количество единиц в числе 0b00000001
.db 1 ; количество единиц в числе 0b00000010
.db 2 ; количество единиц в числе 0b00000011
.db 1 ; количество единиц в числе 0b00000100
...Код: Выделить всё
.nolist
.include "m168def.inc"
.list
.equ XTAL = 20000
.equ BAUD = 9600
.equ NB = ((10000*XTAL)/(16*BAUD)-5)/10
; ========= Interrupts =================
.cseg
.org $0000
JMP RESET ; (RESET)
; .ORG $002
; RETI ; (INT0) External Interrupt Request 0
; .ORG $004
; RETI ; (INT1) External Interrupt Request 1
; .ORG $006
; RETI ; (PCINT0) Pin Change Interrupt Request 0
; .ORG $008
; RETI ; (PCINT1) Pin Change Interrupt Request 1
; .ORG $00A
; RETI ; (PCINT2) Pin Change Interrupt Request 2
; .ORG $00C
; RETI ; (WDT) Watchdog Time-out Interrupt
; .ORG $00E
; RETI ; (TIMER2 COMPA) Timer/Counter2 Compare Match A
; .ORG $010
; RETI ; (TIMER2 COMPB) Timer/Counter2 Compare Match B
; .ORG $012
; RETI ; (TIMER2 OVF) Timer/Counter2 Overflow
; .ORG $014
; RETI ; (TIMER1 CAPT) Timer/Counter1 Capture Event
; .ORG $016
; RETI ; (TIMER1 COMPA) Timer/Counter1 Compare Match A
; .ORG $018
; RETI ; (TIMER1 COMPB) Timer/Coutner1 Compare Match B
; .ORG $01A
; RETI ; (TIMER1 OVF) Timer/Counter1 Overflow
; .ORG $01C
; RETI ; (TIMER0 COMPA) Timer/Counter0 Compare Match A
; .ORG $01E
; RETI ; (TIMER0 COMPB) Timer/Counter0 Compare Match B
; .ORG $020
; RETI ; (TIMER0 OVF) Timer/Counter0 Overflow
; .ORG $022
; RETI ; (SPI, STC SPI) Serial Transfer Complete
.ORG $024
JMP RX_RS232 ; (USART, RX USART) Rx Complete
; .ORG $026
; RETI ; (USART, UDRE USART), Data Register Empty
; .ORG $028
; RETI ; (USART, TX USART), Tx Complete
; .ORG $02A
; RETI ; (ADC) ADC Conversion Complete
; .ORG $02C
; RETI ; (EE READY) EEPROM Ready
; .ORG $02E
; RETI ; (ANALOG COMP) Analog Comparator
; .ORG $030
; RETI ; (TWI) 2-wire Serial Interface
; .ORG $032
; RETI ; (SPM READY) Store Program Memory Ready
.ORG INT_VECTORS_SIZE ; Êîíåö òàáëèöû ïðåðûâàíèé
; ========= END Interrupts =================
RESET:
LDI R16,low(RAMEND)
STS SPL,R16
LDI R16,high(RAMEND)
STS SPH,R16
CLR R16
STS UBRR0H,R16
LDI R16,NB
STS UBRR0L,R16
LDI R16,(1<<RXEN0)|(0<<TXEN0)|(1<<RXCIE0)|(0<<TXCIE0)|(0<<UDRIE0)
STS UCSR0B,R16
LDI R16,(1<<UCSZ00)|(1<<UCSZ01)
STS UCSR0C,R16
;===========
LDI R16,(1<<PB3)
OUT DDRB, R16
SBI PORTB,3
;=========
SEI
JMP MAIN
RETI
RX_RS232:
LDS R16,UDR0
cbi portb,3
RETI
Main:
NOP
NOP
JMP Main
RETI
Код: Выделить всё
.include "m168def.inc"
; ========= Interrupts =================
.cseg
.org $0000
RJMP RESET ; (RESET)
.ORG $002
RETI ; (INT0) External Interrupt Request 0
; .ORG $004
; RETI ; (INT1) External Interrupt Request 1
; .ORG $006
; RETI ; (PCINT0) Pin Change Interrupt Request 0
; .ORG $008
; RETI ; (PCINT1) Pin Change Interrupt Request 1
; .ORG $00A
; RETI ; (PCINT2) Pin Change Interrupt Request 2
; .ORG $00C
; RETI ; (WDT) Watchdog Time-out Interrupt
; .ORG $00E
; RETI ; (TIMER2 COMPA) Timer/Counter2 Compare Match A
; .ORG $010
; RETI ; (TIMER2 COMPB) Timer/Counter2 Compare Match B
; .ORG $012
; RETI ; (TIMER2 OVF) Timer/Counter2 Overflow
; .ORG $014
; RETI ; (TIMER1 CAPT) Timer/Counter1 Capture Event
; .ORG $016
; RETI ; (TIMER1 COMPA) Timer/Counter1 Compare Match A
; .ORG $018
; RETI ; (TIMER1 COMPB) Timer/Coutner1 Compare Match B
; .ORG $01A
; RETI ; (TIMER1 OVF) Timer/Counter1 Overflow
; .ORG $01C
; RETI ; (TIMER0 COMPA) Timer/Counter0 Compare Match A
; .ORG $01E
; RETI ; (TIMER0 COMPB) Timer/Counter0 Compare Match B
; .ORG $020
; RETI ; (TIMER0 OVF) Timer/Counter0 Overflow
; .ORG $022
; RETI ; (SPI, STC SPI) Serial Transfer Complete
.ORG $024
JMP RX_RS232 ; (USART, RX USART) Rx Complete
; .ORG $026
; RETI ; (USART, UDRE USART), Data Register Empty
; .ORG $028
; RETI ; (USART, TX USART), Tx Complete
; .ORG $02A
; RETI ; (ADC) ADC Conversion Complete
; .ORG $02C
; RETI ; (EE READY) EEPROM Ready
; .ORG $02E
; RETI ; (ANALOG COMP) Analog Comparator
; .ORG $030
; RETI ; (TWI) 2-wire Serial Interface
; .ORG $032
; RETI ; (SPM READY) Store Program Memory Ready
; ========= END Interrupts =================
RESET:
LDI R16,low(RAMEND)
STS SPL,R16
LDI R16,high(RAMEND)
STS SPH,R16
CLR R16
SEI
Main:
NOP
NOP
JMP Main
RETI
RX_RS232:
RETI
LDI R16,low(RAMEND)
OUT SPL,R16
LDI R16,high(RAMEND)
OUT SPH,R16
Код: Выделить всё
STACKINIT // Инициализация стека
RAMFLUSH // Очистка ОЗУ
GPRFLUSH // Очистка РОН (Регистров Общего Назначения)Лучше, хуже...философия...НАПАЛМ писал(а):Именно поэтому лучше юзать библиотеку макроопределений.
Я так понял, что он не прописывался из-за команды STS, я правельно понял&?Kavka писал(а): Сам то понял в чём была проблема с инициализацией стека у Kill17?
Код: Выделить всё
LDI R16, low(RAMEND)
STS SPL + 0x20, R16
LDI R16, 0x20 + high(RAMEND)
STS SPH + 0x20, R16Код: Выделить всё
.MACRO STORE ;параметры: адрес, регистр
.if @0>0x3F
sts @0, @1
.else
out @0, @1
.endif
.ENDMACRO
.MACRO LOAD ;параметры: адрес, регистр
.if @1>0x3F
lds @0, @1
.else
in @0, @1
.endif
.ENDMACROНафига вот это делать?НАПАЛМ писал(а):Код: Выделить всё
RAMFLUSH // Очистка ОЗУ GPRFLUSH // Очистка РОН (Регистров Общего Назначения)
Так а зачем их инициализировать? В программе всё равно идёт ПРИСВОЕНИЕ значения, без разницы что там было до этого.nirq писал(а):Сам по себе переход на адрес "ресет" их не инициализировал бы.
Да, я прогонял у себя программу, хотел написать, гляжу, а тут уже и сам он ответил.Kavka писал(а):Задал вопрос, сам нашёл ответ! Kill17, круто!
Лучше, хуже...философия...НАПАЛМ писал(а):Именно поэтому лучше юзать библиотеку макроопределений.Сам то понял в чём была проблема с инициализацией стека у Kill17?
РОНы обнуляются вместе со всей периферией по любым сигналам сброса