 |
|
|
|
| Благодарности и т.д. |
| Ветка полезна ... буду почитывать |
|
100% |
[ 9 ] |
| Уберите это безобразие! |
|
0% |
[ 0 ] |
|
| Всего проголосовало : 9 |
|
| Автор |
Сообщение |
AndryG Модератор
Зарегистрирован: 24.07.2006 Сообщения: 411 Откуда: Helios-3
|
Добавлено: 17 Апр 2007, 10:03 Заголовок сообщения: "Хитрости кода" ... |
|
|
Доброго времени суток.
Каждый во время творения находил и узнавал нечто новое для себя ... возможно это был велосипед - не важно - для Вас это было новое и интересное ... и Вы думали: "Надо запомнить - удачный код получился"
Предлагаю в этой ветке собирать подобные "изюминки".
Повторюсь еще разок ... многим покажется, что это "свалка велосипедов" ... но ведь есть люди, которые такой модели двухколесного чуда еще не видели! Поделитесь?
Организационные вопросы
Не бросайте просто куски кода - от них толку мало ... тем паче асм - без объяснений "не видавший велосипедов" не разберется.
Помните о разметке текста - намного удобней и красивей.
Если сделали ошибку - не пишите новый пост "там ошибка" -- отредактируйте ошибочный пост.
Минимум дискуссий ... Если так хочется обсудить кусок кода -- создайте новую тему и поставьте на нее ссылку... а потом, по результатам обсуждения, отредактируйте уже первоначальный пост.
Оставляю за собой право безжалостно рубить пустотрепство. _________________ AndryG
Последний раз редактировалось: AndryG (05 Июл 2007, 17:05), всего редактировалось 3 раз(а) |
|
| Вернуться к началу |
|
 |
AndryG Модератор
Зарегистрирован: 24.07.2006 Сообщения: 411 Откуда: Helios-3
|
Добавлено: 17 Апр 2007, 10:18 Заголовок сообщения: |
|
|
Код не мой, но хочу поделится!
Взято с поста г-на umup на electronix.ru
Датчик DS18B20 возвращает температуру с фиксированной запятой ... 4 знака после запятой.
Таким образом ... для получения температуры с точностью 0.1 градуса нам нужно возвращаемое значение умножить на 0.625
| Код: |
value = (value>>1) + (value>>3);
|
Как всё просто! И никаких дробей и т.д.
Как работает ...
Сдвиг вправо на один бит -- это деление на два
Сдвиг вправо на три бита -- это деление на восемь
Перепишем...
| Код: |
value = value*(1/2) + value* (1/8) = value*(4/8) + value * (1/8) = value * (5/8) = value* 0.625
|
Напоследок весь код функции: (Полное его объяснение не входит в мою задачу ... смотрите даташит на датчик)
Преобразования в формат с фиксированной запятой (1 знак после запятой):
| Код: |
int16_t ds1w_12bit_to_celsius(uint16_t value)
{uint8_t uc1;
uc1 = (value>>8) & 0x80; //запомнить знак числа
if (uc1) value = 0-value; //если нужно, проинвертировать
value = (value>>1) + (value>>3); //скорректировать
if (uc1) value = 0-value; //восстановить знак
return(value);
}
|
Небольшая цитата с http://pro-radio.ru/controllers/3196/
Замечательная статейка! _________________ AndryG
Последний раз редактировалось: AndryG (03 Май 2007, 11:09), всего редактировалось 1 раз |
|
| Вернуться к началу |
|
 |
AndryG Модератор
Зарегистрирован: 24.07.2006 Сообщения: 411 Откуда: Helios-3
|
Добавлено: 03 Май 2007, 10:27 Заголовок сообщения: |
|
|
Частенько бывает такая заморочка:
| Цитата: |
объявляем переменную размером в слово (2 байта), а потом нужно получить доступ к каждому байту слова как к отдельным переменным.
|
Мне в свое время предложили такой вариант:
| Код: |
/*Два макроса служат для доступа к младшему и старшему байту
переменной размером не менее двух байтов*/
#define LOBYTE(x) (*(unsigned char*)&x)
#define HIBYTE(x) (*(((unsigned char*)&x)+1))
//ПРИМЕР!!!
unsigned int big_var = 0x1234;
#define big_var_low LOBYTE(big_var)
$define big_var_hi HIBYTE(big_var)
putchar(big_var_low); // OUT 0x34
putchar(big_var_hi); // OUT 0x12
// Ну или просто ... просто ... без define
putchar(LOBYTE(big_var)); // OUT 0x34
putchar(HIBYTE(big_var)); // OUT 0x12
|
Если нужно "добираться" не только к нулевому и первому байту (например структура или еще там какой замудренный формат данных), то можно сотворить универсальным макрос:
| Код: |
#define BYTENO(x,n) (*(((unsigned char*)&x)+n))
// n - номер байта, который Вас интересует.
|
_________________ AndryG |
|
| Вернуться к началу |
|
 |
Zas Знатный посетитель (>20)


Зарегистрирован: 04.02.2007 Сообщения: 44
|
Добавлено: 03 Май 2007, 12:38 Заголовок сообщения: |
|
|
Полагаю что про деление с помощью правого сдвига и умножения с помощью левого знают все.
Но многие даже не подозревают как получить остаток от деления на число степени двойки.
Так вот:
| Код: | | x mod 2^k = x and (2^k-1) |
Пример:
Остаток от деления числа 58 на число 8 (2^3):
58 mod 8 = 58 mod 2^3 = 58 and (2^3-1) = 0b0111010 and 0b0111 = 0b0010 = 2
Источник
Как-то в книге по асму увидел что остаток деления на 4 можно получить с помощью функции x and 0b0111 и до меня дошло
Все елементарно до безобразия:
При делении на 2^n мы сдвигаем число на n битов влево, собсно n битов выкидывается. Остается целая часть. А чему ещё быть дробной частью как не выкинутым битам? Теперь простой логикой выводим функцию для нахождения этих n битов:
Эта функция должна оставить все биты идущие после 2^n-го. Если учитывать что 2^n это еденица и n нулей то надо n нулей поменять на еденицы, а все остальное на нули. Собственно это выполняет функция отнимания еденицы (1000 -1 = 0111). А дальше функция and отрезает лишние еденицы.
ТАк я это понимаю для себя
А теперь мат доказательство:
Есть число представленое в двоичной системе:
b0*2^0 + b1*2^1 + b2*2^2 +... + bn*2^n
Поделим это число на 2^k. В результате получаем:
b0*2^(0-k) + b1*2^(1-k) + b2*2^(2-k) +... + bn*2^(n-k)
Целой частью деления являются все числа индекс которых >= k
Остаток числа с индексом < k
А дальше получаем остаток по методу описаному выше.
З.Ы. простите за бред  |
|
| Вернуться к началу |
|
 |
derun Знатный посетитель (>20)

Зарегистрирован: 10.04.2007 Сообщения: 32
|
Добавлено: 21 Май 2007, 13:19 Заголовок сообщения: Обмен байтами между регистрами не используя команду обмена |
|
|
Язык Ассемблер.
Обмен байтами между регистрами не используя команду обмена, например если ее нет.
Например для AVR это будет выглядить так
Обмен регистров R1,R2
| Код: |
EOR R1,R2 ;EOR-исключающее ИЛИ (XOR)
EOR R2,R1
EOR R1,R2
|
Быстрее чем использовать MOV, и не требует дополнительных регистров или стека. |
|
| Вернуться к началу |
|
 |
DL36 Живет здесь... (>100)

Зарегистрирован: 04.10.2006 Сообщения: 192 Откуда: Херсон
|
Добавлено: 21 Май 2007, 21:27 Заголовок сообщения: |
|
|
Добавлю от себя.
Очень часто надо сделать преобразование int-char.
Это я подсмотрел у AVRа которого чаще всего можно найти на сахаре и телесистемах.
Это свернутая версия atoi С стандарта ANSI но в отличие от оригинала работает быстрее.
Вызываш itoa2(5999) результат будет в asc[5]
| Код: |
unsigned char asc[5];
void itoa2(unsigned int binval)
{
int step[]={10000,1000,100,10,1};
unsigned int temp,val;
unsigned char i,atemp;
val=binval;
for (i=0; i<5; i++)
{
temp=step[i];
atemp='0';
while(val >= temp)
{
atemp++;
val-=temp;
}
asc[i]=atemp;
}
}
|
|
|
| Вернуться к началу |
|
 |
DL36 Живет здесь... (>100)

Зарегистрирован: 04.10.2006 Сообщения: 192 Откуда: Херсон
|
Добавлено: 10 Июл 2007, 9:58 Заголовок сообщения: |
|
|
Быстрая пп для подсчета единиц в байте.
Идею нашел в сети (автор Дмитрий Кирашов) но как всегда перепечатки и ошибки испортили все дело. Пп взятая в сети оказалась нерабочая. проанализировал код, поправил, что где надо.
Я ее использую при необходимости рассчитать бит паритета, но привожу в первозданном виде, при необходимости всегда можно поправить результат.
Нормально работает с PicLite от хайтека, для Picc18 нормально адаптировать, пока не удалось . См. далее в виде асм модуля.
| Код: |
unsigned char var;
void NumberBit(unsigned char j )
{
var=j;
#asm
rrf _var, w ;
andlw 0x55 ;
subwf _var, w ;
movwf _var
andlw 0x33
addwf _var,f ;
rrf _var,f
addwf _var,f
rrf _var,f
swapf _var,w
addwf _var,w
andlw 0x0f;
#endasm
}
|
результат вычисления остается в аккумуляторе.
Последний раз редактировалось: DL36 (30 Янв 2008, 21:25), всего редактировалось 1 раз |
|
| Вернуться к началу |
|
 |
DL36 Живет здесь... (>100)

Зарегистрирован: 04.10.2006 Сообщения: 192 Откуда: Херсон
|
Добавлено: 27 Янв 2008, 12:34 Заголовок сообщения: |
|
|
Решил продолжить.
Довольно частая задача, развернуть байт, для PICC-18 наиболее быстрый вариант будет так выглядеть.
| Код: |
;PSECT text0,class=CODE,local,delta=2
psect text,class=CODE,delta=1,reloc=2
global _reverseByte;
signat _reverseByte,4201
_reverseByte:
MOVWF var;
SWAPF var, w ;
XORWF var, w ;
ANDLW 0x66 ;
XORWF var, f ;
RRCF var, w ;
RRCF var, f ;
ANDLW 0x55 ;
ADDWF var, f ;
RRCF var, f ;
ADDWF var, f ;
RLNCF var, w ;
return ;
psect temp,global,class=COMRAM,space=1,ovrld
var: ds 1
|
Это надо оформить в виде отдельного файла reverseByte.as и подключить его в проект.
В проекте необходимо объявить внешнюю функцию extern unsigned char reverseByte( unsigned char var );
Во время компиляции компилятор выдает безболезненное предупреждение на последнюю строку, пока не знаю как побороть. |
|
| Вернуться к началу |
|
 |
DL36 Живет здесь... (>100)

Зарегистрирован: 04.10.2006 Сообщения: 192 Откуда: Херсон
|
Добавлено: 27 Янв 2008, 13:58 Заголовок сообщения: |
|
|
Еще до кучи.
Для PICC-18
| Код: | ;; Подпрограмма подсчитывающая количество битов установленных в 1 в байте
psect text,class=CODE,delta=1,reloc=2
global _counterBitInByte;
signat _counterBitInByte,4201
_counterBitInByte:
rrcf var, w ;
andlw 0x55 ;
subwf var, w ;
movwf var
andlw 0x33
addwf var,f ;
rrcf var,f
addwf var,f
rrcf var,f
swapf var,w
addwf var,w
andlw 0x0f;
return ;
psect temp,global,class=COMRAM,space=1,ovrld
var: ds 1 |
Это надо оформить в виде отдельного файла counterBitInByte.as и подключить его в проект.
В проекте необходимо объявить внешнюю функцию extern unsigned char counterBitInByte( unsigned char var );
Последний раз редактировалось: DL36 (30 Янв 2008, 16:50), всего редактировалось 2 раз(а) |
|
| Вернуться к началу |
|
 |
DL36 Живет здесь... (>100)

Зарегистрирован: 04.10.2006 Сообщения: 192 Откуда: Херсон
|
Добавлено: 30 Янв 2008, 17:07 Заголовок сообщения: |
|
|
Привел этот текст на микрочипе и здесь пускай хранится.
Должны быть определены так же
#define MHZ *1000L /* number of kHz in a MHz */
#define KHZ *1
| Код: |
HI-TECH Software PICC-18
;******************************************************************************
; Подпрограмма выполнения программной выдержки времени
; Входные данные:
; Переменная типа int
; файл DelayUsInt.as
; необходимо объявить extern DelayUsInt(unsigned int delay);
; При необходимости, привязать к микросекундам
; delay = (((unsigned long long)(x))*(unsigned long long)(XTAL_FREQ))
; /(unsigned long long)(12MHZ);
; Где х требуемая задержка в микросекундах
; XTAL_FREQ частота кварца, например #define XTAL_FREQ 40000KHZ
;******************************************************************************
#include <aspic18.h>
global _DelayUsInt
global ?_DelayUsInt
opt pw 80
psect text,class=CODE,delta=1,reloc=2
;signat _DelayUsInt,4200
_DelayUsInt$delay set ?_DelayUsInt
psect text
_DelayUsInt:
movlw low ?_DelayUsInt ;Грузим FSR
movwf FSR0L,c
movlw high ?_DelayUsInt
movwf FSR0H,c
movf POSTINC0,f,c ;Инкрементируем для возможности последующего входа
_DelayUsInt_1: ;Вход после проверки старшего разряда
movf POSTDEC0,f,c ;Поскольку адрес был инкрементирован для старшего разряда
_DelayUsInt_2:
decfsz INDF0,f,c ;Декремент младшей цифры
goto _DelayUsInt_2 ;Крутимся тут до нуля
movf PREINC0,f,c ;Смотрим на старшую цифру
bnz _DelayUsInt_3 ;Если ноль то выход
return
_DelayUsInt_3:
decf INDF0,f,c ;Декремент старшей цифры
goto _DelayUsInt_1
|
Последний раз редактировалось: DL36 (30 Янв 2008, 21:23), всего редактировалось 1 раз |
|
| Вернуться к началу |
|
 |
|
|
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах Вы не можете добавлять вложения в этом форуме Вы можете просматривать вложения в этом форуме
|
|