Микроконтролери и електроника
http://mcu-bg.com/mcu_site/

Превъртащ се брояч
http://mcu-bg.com/mcu_site/viewtopic.php?f=3&t=1764
Страница 1 от 2

Автор:  Реконструктор [ Сря Фев 08, 2006 11:19 am ]
Заглавие:  Превъртащ се брояч

Дайте да видим кой как е решил този често срещан проблем. :) Имаме превъртащ се брояч, размер 1 байт, стойности от 0 до 5, примерно. При достигане на 5 трябва да се нулира. Да кажем, че сме притиснати до стената и трябва да пестим всеки машинен цикъл. :wink: Няма ли начин да стане с 2-3 аритметични операции, без да се ползват усл. оператори?

Автор:  Wise [ Сря Фев 08, 2006 11:30 am ]
Заглавие: 

Аз обикновено го броя обратно - от 5 към 0 за да се ползва breq или brne
инструкции. А при 0 го зареждам с константата.
Така се избягва compare .
С аритметични операции не виждам как ще стане.

Автор:  nickich [ Сря Фев 08, 2006 11:57 am ]
Заглавие: 

count++;
count %=5;

Автор:  bateAz [ Сря Фев 08, 2006 12:02 pm ]
Заглавие: 

nickich, знаеш ли %= за колко цикъла се изпълнява? [-X

Автор:  nickich [ Сря Фев 08, 2006 12:21 pm ]
Заглавие: 

bateAz, в интерес на истината не съм гледал какво генерира компилатора :oops:, но на С изглежда добре :lol:

Автор:  breeze [ Сря Фев 08, 2006 12:49 pm ]
Заглавие: 

В общия случай за N (но ако е допустимо броене назад вместо напред) няма по-прост начин от този, който предлага Wise. Иначе ако е задължително да се брои напред, не може да се избегне сравнението, условния преход и зареждането с по малък брой цикли. Все пак това са 3 инструкции.
Ако става дума за индекс към циркулярен буфер (най често за това ползваме такъв брояч) и ако имаме известна свобода да изберем дължина равна на точна степен на двойката, тогава ето какво е решението на Атмел (взето например от тяхната имплементация на UART управление с прекъсвания)

/* UART Buffer Defines */
#define UART_RX_BUFFER_SIZE 128 /* 2,4,8,16,32,64,128 or 256 bytes */
#define UART_TX_BUFFER_SIZE 128


#define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1 )
#if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
#error RX buffer size is not a power of 2
#endif

#define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1 )
#if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
#error TX buffer size is not a power of 2
#endif

И после вече е лесно, след инкрементиране на брояча правим counter &= UART_RX_BUFFER_MASK, което съдържа само единици. По просто от това не може.

Автор:  Реконструктор [ Сря Фев 08, 2006 1:03 pm ]
Заглавие: 

По принцип xor със себе си дава 0, ще се помъча да измисля нещо в тая насока.
Другото, което може да се използва, е възможността за директен jump към адрес при някои процесори, което в комбинация с обратното броене, предложено от Wise, също може да даде добър резултат.

Автор:  Цецо [ Сря Фев 08, 2006 1:22 pm ]
Заглавие: 

Всички процесори имат инструкция Jump при 0. Така че наистина по оптимално от броенето назад невиждам.

Автор:  Gogo [ Сря Фев 08, 2006 6:03 pm ]
Заглавие: 

Цитат:
Аз обикновено го броя обратно - от 5 към 0 за да се ползва breq или brne
инструкции. А при 0 го зареждам с константата.
Така се избягва compare .
С аритметични операции не виждам как ще стане.

Точно... По-бързо и по-малко едва ли може да стане по друг начин

Автор:  velio [ Сря Фев 08, 2006 9:55 pm ]
Заглавие: 

Ако трябва да брои напред (и ако) може да се ползва още един байт. Просто ще си брои назад по нормалния начин, а в допълнителния байт ще натрупва напред. Обаче инструкциите стават повечко.

Автор:  ToHu [ Пет Фев 10, 2006 9:46 am ]
Заглавие: 

Ами зависи от поцесора, може да с еползва ако има флаг вдигащ се при пренос от FF към 0, или ако рзултата от операцията е нула, в тоя случай зреждаш допулнението до FF, но пак губиш възможността от директно ползване на брояча, т.е. стойността му няма да е реалния брой цикли.

Автор:  Реконструктор [ Пет Фев 10, 2006 9:55 am ]
Заглавие: 

Вече почвам да си мисля, че ако някой производител на микроконтролери я направи тази екстра с брояча хардуерно, ще спечели доста пари. :D В AVR-а (а предполагам и на други места) е направено, но само за таймерите.

Автор:  bateAz [ Пет Фев 10, 2006 10:37 am ]
Заглавие: 

В i8051 има CJNE - с една инструкция: проверява дали операнд1 = операнд2 и ако не е, прави преход. Аз защо казвам, че 8051 е класика, а?

Например: CJNE R1, #5, loop_proc

Автор:  t_i_t_o [ Пет Фев 10, 2006 12:31 pm ]
Заглавие: 

bateAz написа:
В i8051 има CJNE - с една инструкция: проверява дали операнд1 = операнд2 и ако не е, прави преход. Аз защо казвам, че 8051 е класика, а?

Например: CJNE R1, #5, loop_proc


малко офтопик: присъединявам се към батето с аргумента че поне на мен това е единствения ми познат ЦПУ който може да прави "mov [addr], [addr]" с една инструкция :)

Автор:  mitko [ Пет Фев 10, 2006 1:10 pm ]
Заглавие: 

Само не разбрах памет ли се пести или скорост
ако е скорост и стойностите са само 0-5 можеш да скочиш по таблица с индекс брояча ти
в някои процесори има много бързи команди за такива преходи

Страница 1 от 2 Часовете са според зоната UTC + 2 часа [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/