|
Вычисления на ATmega88 |
|
|
|
Dec 2 2008, 14:00
|
Профессионал
    
Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061

|
Здравствуйте! Использую WinAVR, ATmega88, сигнал синхронизации - внтутренняя RC-цепь (частота 8 МГц). Необходимо как можно быстрее вычислить значение следующего выражения: C = Y * C' / 255. Причём: C, Y, C' - unsigned char, т. е., действительные числа мне не нужны... В данный момент вычисления производятся приблизительно за 92 мкс (в программе три выражения подряд). Можно, конечно, кварц поставить на большую частоту, но хотелось бы пока без него  Фрагмент программы: Код ... OCR0A = n_red * dmx[0] / 255; OCR0B = n_green * dmx[0] / 255; OCR2B = n_blue * dmx[0] / 255; ... Спасибо заранее!
--------------------
Благодарю заранее!
|
|
|
|
|
 |
Ответов
|
Dec 12 2008, 23:29
|
Местный
  
Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017

|
Цитата(n_bogoyavlensky @ Dec 12 2008, 22:39)  Вот ещё одна задача. Как аналогичным образом целочисленно поделить одно 8-битное число на другое 8-битное число? Более конкретно - деление на 10. Для диапазона A=[0..255): (unsigned char)(А+1)*51>>9 Для диапазона A=[0..255] ((unsigned char)(А*51) + 51)>>9 или на асме соответственно Код ldi temp,51 inc A mul A,temp lsr R1
и ldi temp,51 mul A,temp add R0,temp adc R1,zero lsr R1
|
|
|
|
|
Dec 13 2008, 11:33
|
Профессионал
    
Группа: Участник
Сообщений: 1 040
Регистрация: 3-01-07
Пользователь №: 24 061

|
Цитата Для диапазона A=[0..255): (unsigned char)(А+1)*51>>9
Для диапазона A=[0..255] ((unsigned char)(А*51) + 51)>>9 Спасибо!  Кстати, откуда вы с такой лёгкостью извлекаете эти волшебные выражения?  Они где-то перечислены или их можно достаточно просто придумать самому? Каков принцип? А для диапазона A=[0..65535]? Цитата(singlskv @ Dec 13 2008, 01:13)  Дык все точно так же, умножте на 26(~256/10) или на 6554(~65536/10) ну и если нужно скоректируйте... Всмысле? Что умножить и как скорректировать?
--------------------
Благодарю заранее!
|
|
|
|
|
Dec 13 2008, 12:06
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(n_bogoyavlensky @ Dec 13 2008, 14:33)  Всмысле? Что умножить и как скорректировать? Именно так как в посте №21 51 ~= 256 * 2 / 10 + 51 корректировка
|
|
|
|
|
Dec 13 2008, 12:56
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(n_bogoyavlensky @ Dec 13 2008, 15:16)  Всё равно пока не пойму каков принцип?  x/10 ~= x*51/512 = (x*51)>>9 или x/10 ~= x*26/256 = (x*26)>>8 или ... подберите что-нибудь, устраивающее по точности. Для корректного целочисленного округления все-таки д.б. ((x*51)+51/2)>>9 ~= ((x*51)+26)>>9
|
|
|
|
|
Dec 13 2008, 20:41
|
    
Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731

|
Цитата(n_bogoyavlensky @ Dec 13 2008, 21:34)  С делением теперь понятно. Спасибо  С округлением до ближайшего целого не понятно... Спасибо, был неправ. Вместо ((x*51) + 51/2) >> 9 ~= ((x*51)+26)>>9 читать ((x*51) + 1<<8) >> 9 = (x*51)>>9 + 0.5 Правила округления до целого предполагают, что (н-р, применительно к десятичной системе счисления) если дробная часть = [0.0..0.4(9)], то число округляется "вниз" (дробная часть просто отбрасывается), если дробная часть = [0.5..0.9(9)], то число округляется "вверх" (дробная часть отбрасывается, к целой части добавляется 1). Контроллер при целочисленных операциях может только отбросить дробную часть. Чтобы заставить его округлять "по-человечески", нужно перед целочисленными операциями с потерей точности (типа деление/сдвиг) добавить к операнду половину разряда, который станет младшим значащим разрядом после выполнения операции (== половину делителя). Округляем до целого в десятичной системе: половина значащего разряда = 0.5 trunc(31.49 + 0.5) = 31 trunc(31.5 + 0.5) = 32 Округляем до целого в двоичной системе: пусть 0b10100101 (= 165 дес.) хочется сдвинуть вправо на 3 разряда половина делителя = 1 << (3 - 1) = 0b100 0b10100101 >> 3 = 0b10100 (= 20 дес.) (0b10100101 + 0b100) >> 3 = 0b10101 (= 21 дес.) 165/8 = 20.625 ~= 21
|
|
|
|
|
Dec 13 2008, 21:33
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(xemul @ Dec 13 2008, 23:41)  Спасибо, был неправ. Вместо ((x*51) + 51/2) >> 9 ~= ((x*51)+26)>>9 читать ((x*51) + 1<<8) >> 9 = (x*51)>>9 + 0.5 на самом деле рассчет коррекции проще всего делать так: - пример с домножением на 51 - пусть коррекция = A, те ((x * 51) + A) / 512 ~= x / 10 - тогда д.б.: 1.) 0 * 51 +A >= 0 2.) 9 * 51 +A < 1 * 512 3.) 10 * 51 + A >= 1 * 512 4.)250 * 51 + A >= 25 * 512 5.)255 * 51 + A < 26 * 512 - преобразуем 1.) A >= 0 2.) A < 53 3.) A >= 2 4.) A >= 50 5.) A < 307 -итого: 50<= A < 53 то есть нам подойдут 50, 51, 52 выбор чисел 0, 9, 10, 250, 255 надеюсь понятен
|
|
|
|
Сообщений в этой теме
n_bogoyavlensky Вычисления на ATmega88 Dec 2 2008, 14:00 Непомнящий Евгений а если поделить на 256? Компилер должен превратить... Dec 2 2008, 14:12 Арк К А надо делить именно на 255? не на 256?
тогда было... Dec 2 2008, 14:16 Непомнящий Евгений Цитата(Арк К @ Dec 2 2008, 17:16) Критичн... Dec 2 2008, 14:24 n_bogoyavlensky Цитата(Арк К @ Dec 2 2008, 18:16) А надо ... Dec 3 2008, 08:26  _Pasha Цитата(n_bogoyavlensky @ Dec 3 2008, 12:2... Dec 3 2008, 08:55   n_bogoyavlensky ЦитатаВ догонку.
Деление на 255 в данном случае мо... Dec 3 2008, 09:46 _Pasha Цитата(n_bogoyavlensky @ Dec 2 2008, 18:0... Dec 2 2008, 14:24 Непомнящий Евгений Цитата(_Pasha @ Dec 2 2008, 17:24) Исполь... Dec 2 2008, 15:14  _Pasha Цитата(Непомнящий Евгений @ Dec 2 2008, 19... Dec 2 2008, 15:20  =GM= Цитата(Непомнящий Евгений @ Dec 2 2008, 15... Dec 2 2008, 16:53   Непомнящий Евгений Цитата(=GM= @ Dec 2 2008, 19:53) Вот здес... Dec 3 2008, 05:26    =GM= Цитата(Непомнящий Евгений @ Dec 3 2008, 05... Dec 3 2008, 11:00 =GM= Цитата(n_bogoyavlensky @ Dec 2 2008, 14:0... Dec 2 2008, 14:52 Непомнящий Евгений Цитата(=GM= @ Dec 2 2008, 17:52) C=(Y*C1*... Dec 2 2008, 15:00  =GM= Цитата(Непомнящий Евгений @ Dec 2 2008, 15... Dec 2 2008, 15:05 LordVader Вот что нагуглилось: http://www.sharpthinking.net/... Dec 2 2008, 16:48 VDG Человек скорее всего управляет RGB-светодиодом, а ... Dec 2 2008, 22:02         xemul Цитата(singlskv @ Dec 14 2008, 00:33) на ... Dec 13 2008, 22:41         Александр Куличок Цитата(singlskv @ Dec 13 2008, 23:33) -ит... Dec 13 2008, 23:35     SSerge Цитата(n_bogoyavlensky @ Dec 13 2008, 18... Dec 13 2008, 13:00 singlskv Дык все точно так же,
умножте на 26(~256/10) или н... Dec 12 2008, 21:13 ae_ x/10 = x*(1/10) = x*(205/2048) = (x*205)>>11... Dec 13 2008, 12:56 ae_ Так, что бы во всём диапазоне 0...255 / 10 выполня... Dec 14 2008, 11:51 n_bogoyavlensky Кстати, а что за метод в 11 посте?
Там логика друг... Dec 15 2008, 09:59 SSerge Цитата(n_bogoyavlensky @ Dec 15 2008, 15... Dec 15 2008, 11:33
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|