У автора получился вариант с PORTx |= (1<<bit) самым быстрым. Вдвое быстрее чем запись в PINx.
WinAvr в вопросах и ответах
Забавно... Прогуглив этот вопрос наткнулся на одно своего рода исследование:
У автора получился вариант с PORTx |= (1<<bit) самым быстрым. Вдвое быстрее чем запись в PINx.
У автора получился вариант с PORTx |= (1<<bit) самым быстрым. Вдвое быстрее чем запись в PINx.
- Реклама
автор делал не запись PINх, а модификацию, т.е. использовал лишние операции считывания значения регистра и изменения значения, хотя на самом деле нужно было делать именно запись единицы в нужный разрядWiseLord писал(а):Забавно... Прогуглив этот вопрос наткнулся на одно своего рода исследование:
У автора получился вариант с PORTx |= (1<<bit) самым быстрым. Вдвое быстрее чем запись в PINx.
Код: Выделить всё
PINB = _BV(PB0);если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Да, похоже, Вы правы.
Но только всё равно интересно, работает ли это на популярных ATmega8/16/32(A). В их даташитах такая фича не описана. У ATmega48/88/168, ATtiny2313 - описана.
Но только всё равно интересно, работает ли это на популярных ATmega8/16/32(A). В их даташитах такая фича не описана. У ATmega48/88/168, ATtiny2313 - описана.
WiseLord, спецификация на то она и есть, чтобы описывать то что есть.
Чего нет - в ней не описывают.
Чего нет - в ней не описывают.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
- Сообщения: 134
- Зарегистрирован: Вс авг 01, 2010 16:05:25
Доброго времени суток,помогите с кодом. Есть две функции,одна шифратор и дешифратор
Конечно очень мудрёный код,по крайне мере для меня, так вот на функцию шифратора компилятор ругается, а на дешифратора нет. Вроде код почти одинаковый. Что не так подскажите? А это WinAvr выдаёт ошибку
Код: Выделить всё
#define KeeLoq_NLF 0x3A5C742E
#define bit(x,n) (((x)>>(n))&1)
#define g5(x,a,b,c,d,e) (bit(x,a)+bit(x,b)*2+bit(x,c)*4+bit(x,d)*8+bit(x,e)*16)
/// шифрование
uint32_t KeeLoq_Encrypt (uint32_t dattta,uint64_t key){ //uint32_t data, uint64_t key
uint32_t x = dattta, r;
for (r = 0; r < 528; r++){
x = (x>>1)^((bit(x,0)^bit(x,16)^( uint32_t)bit(key,r&63)^bit(KeeLoq_NLF,g5(x,0,9,20,26,31)))<<31);
}
return x;
}
/// дешифровка
uint32_t KeeLoq_Decrypt ( uint32_t dattta, uint64_t key){
uint32_t x = dattta, r;
for (r = 0; r < 528; r++)
x = (x<<1)^bit(x,31)^bit(x,15)^( uint32_t)bit(key,(15-r)&63)^bit(KeeLoq_NLF,g5(x,0,8,19,25,30));
return x;
}Make_data.c:26: error: unable to find a register to spill in class 'POINTER_REGS'
Make_data.c:26: error: this is the insn:
(insn 52 50 53 3 Make_data.c:22 (set (reg:SI 24 r24 [63])
(and:SI (subreg:SI (reg:DI 62 [+1 ]) 0)
(const_int 1 [0x1]))) 43 {andsi3} (nil))
Make_data.c:26: confused by earlier errors, bailing out
- Реклама
Вероятно выражение получилось слишком большим для разбора для данного компилятора и на каком-то этапе не хватило регистров... За что я не люблю такие "краткие" записи выражений, что их фиг потом разберешь даже вручную.
- Сообщения: 134
- Зарегистрирован: Вс авг 01, 2010 16:05:25
Значит дешифратор получается короче,т.е. если это выражение разложить может всё заработает. Спасибо, буду пробовать.Alexeyslav писал(а):Вероятно выражение получилось слишком большим для разбора для данного компилятора и на каком-то этапе не хватило регистров...
- Сообщения: 422
- Зарегистрирован: Ср дек 26, 2007 18:33:00
День добрый всем, подскажите плз, что-то совсем запутался.
Есть функция, копирует символ из массива ascii, в массив дисплея display_buffer, первый символ массива ascii у меня "!", т.е. номер 0х20 в НЕХ.
Если вместо data1 в функции пишу 0,1,2 , т.е. display_buffer = ascii_5x7[i+((0)*5)] , то символ отображается нормально, т.е. восклицательный знак и далее символы ascii.
Но если передаю эти данные через функцию Load_Data (0) в программе, то какая-то билиберда выходит на дисплее. Т.е. копирование происходит уже как-то не так. Подозреваю, что что-то совсем простое я упустил...
Есть функция, копирует символ из массива ascii, в массив дисплея display_buffer, первый символ массива ascii у меня "!", т.е. номер 0х20 в НЕХ.
Код: Выделить всё
const char ascii_5x7[] = {
0x00, 0x00, 0xF2, 0x00, 0x00,
0x00, 0xE0, 0x00, 0xE0, 0x00,
0x28, 0xFE, 0x28, 0xFE, 0x28,
};
void Load_Data (unsigned char data1){
for(char i=0; i<0x05; i++){
display_buffer[i] = ascii_5x7[i+((data1)*5)];
}
}
Но если передаю эти данные через функцию Load_Data (0) в программе, то какая-то билиберда выходит на дисплее. Т.е. копирование происходит уже как-то не так. Подозреваю, что что-то совсем простое я упустил...
- Сообщения: 422
- Зарегистрирован: Ср дек 26, 2007 18:33:00
Вопрос снят, таблица ascii занимала всю память МК (в моём верхнем примере я её укоротил) и display_buffer не помещался, подправил-уменьшил таблицу ascii и все заработало.
Подскажите-ка, товарищи, немного туплю сам.
Решил немножко переписать код своего проекта в том стиле, чтобы подключать кнопки/дисплеи и т.п. можно было бы к любым портам в любом порядке.
Т.е. что-то типа #define DISPLAY_DATA_DDR DDRA с жёстким требованием подключения 8 портов данных дисплея к одному порту МК в том же порядке, превратилось в отдельные определения DISPLAY_DATA_0, DISPLAY_DATA_1, .. DISPLAY_DATA_7, которые можно было бы подключать уже к любым портам МК.
Код в новом варианте вместовыглядит уже так:
Функции переписаны под новый вариант, и всё работает. Но мне интересно, можно ли как-то упростить эти однотипные записи во втором варианте до однострочных (содержащих в аргументах , например, префикс KS0108_RES и номер 7), чтобы уже препроцессор развернул их до четырёх определений каждую?
Решил немножко переписать код своего проекта в том стиле, чтобы подключать кнопки/дисплеи и т.п. можно было бы к любым портам в любом порядке.
Т.е. что-то типа #define DISPLAY_DATA_DDR DDRA с жёстким требованием подключения 8 портов данных дисплея к одному порту МК в том же порядке, превратилось в отдельные определения DISPLAY_DATA_0, DISPLAY_DATA_1, .. DISPLAY_DATA_7, которые можно было бы подключать уже к любым портам МК.
Код в новом варианте вместо
Спойлер
Код: Выделить всё
#define KS0108_CTRL_PORT PORTA
#define KS0108_CTRL_DDR DDRA
#define KS0108_DI (1<<PA2)
#define KS0108_RW (1<<PA3)
#define KS0108_E (1<<PA4)
#define KS0108_CS1 (1<<PA5)
#define KS0108_CS2 (1<<PA6)
#define KS0108_RES (1<<PA7)
Спойлер
Код: Выделить всё
#define KS0108_DI_DDR DDRA
#define KS0108_DI_PORT PORTA
#define KS0108_DI_PIN PINA
#define KS0108_DI (1<<PA2)
#define KS0108_RW_DDR DDRA
#define KS0108_RW_PORT PORTA
#define KS0108_RW_PIN PINA
#define KS0108_RW (1<<PA3)
#define KS0108_E_DDR DDRA
#define KS0108_E_PORT PORTA
#define KS0108_E_PIN PINA
#define KS0108_E (1<<PA4)
#define KS0108_CS1_DDR DDRA
#define KS0108_CS1_PORT PORTA
#define KS0108_CS1_PIN PINA
#define KS0108_CS1 (1<<PA5)
#define KS0108_CS2_DDR DDRA
#define KS0108_CS2_PORT PORTA
#define KS0108_CS2_PIN PINA
#define KS0108_CS2 (1<<PA6)
#define KS0108_RES_DDR DDRA
#define KS0108_RES_PORT PORTA
#define KS0108_RES_PIN PINA
#define KS0108_RES (1<<PA7)
я сделал (и периодически пополняю его) файлик с полезными макросами (прилагаю).
и в вашем случае сделал бы с его помощью определил бы макросом только БУКВУ порта и номер ножки для каждой линии дисплея
а уже в тех местах, где конкретно нужно обращаться к регистрам порта, использовал бы макросы
и так далее.
то есть свести описательную часть дефайнов только к необходимомому минимуму, а остальное перенести в часть реализации. ну, если вам совсем невмоготу, можно и дополнить в вашем стиле:
и в вашем случае сделал бы с его помощью определил бы макросом только БУКВУ порта и номер ножки для каждой линии дисплея
Код: Выделить всё
#define DI_PORT A
#define RW_PORT B
#define DI_PIN 4
#define RW_PIN 6Код: Выделить всё
PORT(DI_PORT) |= _BV(DI_PIN); // выдать единицу в DI
DDR(RW_PORT) |= _BV(RW_PIN); // настроить линию ввода-вывода
uint8_t tmp = PIN(DI_PORT) & _BV(DI_PIN); // считать состояние линии DIто есть свести описательную часть дефайнов только к необходимомому минимуму, а остальное перенести в часть реализации. ну, если вам совсем невмоготу, можно и дополнить в вашем стиле:
Код: Выделить всё
#define KS0108_RS_PIN PIN(RS_PORT)- Вложения
-
- avr_helper.h
- (4.95 КБ) 223 скачивания
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Да, так, пожалуй, короче будет.
Можешь ещё вот это посмотреть.
http://radiokot.ru/forum/viewtopic.php? ... 3#p1576663
Выбирай что понравиться - на вкус и цвет, как говориться...
http://radiokot.ru/forum/viewtopic.php? ... 3#p1576663
Выбирай что понравиться - на вкус и цвет, как говориться...
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Реализовал в итоге так определения, а так - работу с портом.
Код, конечно, немножко вырос в размере. Но совсем немножко, и это небольшая плата за то, что сейчас проект можно легко портировать на любую другую достаточную для него AVR-ку не заморачиваясь потом с разводкой платы.
Код, конечно, немножко вырос в размере. Но совсем немножко, и это небольшая плата за то, что сейчас проект можно легко портировать на любую другую достаточную для него AVR-ку не заморачиваясь потом с разводкой платы.
- Сообщения: 882
- Зарегистрирован: Ср фев 22, 2012 01:25:21
Код: Выделить всё
static void st7920SetPort(uint8_t data)
{
if (data & (1<<0)) PORT(ST7920_D0) |= ST7920_D0_PIN; else PORT(ST7920_D0) &= ~ST7920_D0_PIN;
if (data & (1<<1)) PORT(ST7920_D1) |= ST7920_D1_PIN; else PORT(ST7920_D1) &= ~ST7920_D1_PIN;
if (data & (1<<2)) PORT(ST7920_D2) |= ST7920_D2_PIN; else PORT(ST7920_D2) &= ~ST7920_D2_PIN;
if (data & (1<<3)) PORT(ST7920_D3) |= ST7920_D3_PIN; else PORT(ST7920_D3) &= ~ST7920_D3_PIN;
if (data & (1<<4)) PORT(ST7920_D4) |= ST7920_D4_PIN; else PORT(ST7920_D4) &= ~ST7920_D4_PIN;
if (data & (1<<5)) PORT(ST7920_D5) |= ST7920_D5_PIN; else PORT(ST7920_D5) &= ~ST7920_D5_PIN;
if (data & (1<<6)) PORT(ST7920_D6) |= ST7920_D6_PIN; else PORT(ST7920_D6) &= ~ST7920_D6_PIN;
if (data & (1<<7)) PORT(ST7920_D7) |= ST7920_D7_PIN; else PORT(ST7920_D7) &= ~ST7920_D7_PIN;
return;
}
Только порт и линию называю по другому... вот так - ST7920_PORT0, ST7920_DDR0, ST7920_PIN0, ST7920_LINE0... вроде все однотипно, никаких лишних макросов (я их не долюбливаю), записи получаются - короче некуда, и сразу понятно что за операция... в общем - я балдю со своего стиля
Код: Выделить всё
static void st7920SetPort(uint8_t data)
{
if (data & (1<<0)) ST7920_PORT0 |= ST7920_LINE0; else ST7920_PORT0 &= ~ST7920_LINE0;
if (data & (1<<1)) ST7920_PORT1 |= ST7920_LINE1; else ST7920_PORT1 &= ~ST7920_LINE1;
if (data & (1<<2)) ST7920_PORT2 |= ST7920_LINE2; else ST7920_PORT2 &= ~ST7920_LINE2;
if (data & (1<<3)) ST7920_PORT3 |= ST7920_LINE3; else ST7920_PORT3 &= ~ST7920_LINE3;
if (data & (1<<4)) ST7920_PORT4 |= ST7920_LINE4; else ST7920_PORT4 &= ~ST7920_LINE4;
if (data & (1<<5)) ST7920_PORT5 |= ST7920_LINE5; else ST7920_PORT5 &= ~ST7920_LINE5;
if (data & (1<<6)) ST7920_PORT6 |= ST7920_LINE6; else ST7920_PORT6 &= ~ST7920_LINE6;
if (data & (1<<7)) ST7920_PORT7 |= ST7920_LINE7; else ST7920_PORT7 &= ~ST7920_LINE7;
return;
}
Код: Выделить всё
data = 0;
if (ST7920_PIN0 & ST7920_LINE0) data | (1<<0);
if (ST7920_PIN1 & ST7920_LINE1) data | (1<<1);
if (ST7920_PIN2 & ST7920_LINE2) data | (1<<2);
if (ST7920_PIN3 & ST7920_LINE3) data | (1<<3);
if (ST7920_PIN4 & ST7920_LINE4) data | (1<<4);
if (ST7920_PIN5 & ST7920_LINE5) data | (1<<5);
if (ST7920_PIN6 & ST7920_LINE6) data | (1<<6);
if (ST7920_PIN7 & ST7920_LINE7) data | (1<<7);
Спойлер
Код: Выделить всё
//настройки портов
#define OUTD_CLK_PORT PORTC
#define OUTD_CLK_DDR DDRC
#define OUTD_CLK_LINE (1<<1)//линия тактирования
#define OUTD_DATA_PORT PORTB
#define OUTD_DATA_DDR DDRB
#define OUTD_DATA_LINE (1<<5)//линия данных
#define OUTD_STROBE_PORT PORTB
#define OUTD_STROBE_DDR DDRB
#define OUTD_STROBE_LINE (1<<4)//линия стробирования
#define OUTD_ACTIVE_PORT PORTC
#define OUTD_ACTIVE_DDR DDRC
#define OUTD_ACTIVE_LINE (1<<0)//перевод выходов сдвиговых регистров из 3-го состоян в активное
Спойлер
Код: Выделить всё
//-----------------------------------------------------------------------------------------------------------------------
//Определения портов
#define IND_PORT0 PORTB
#define IND_PIN0 PINB
#define IND_LINE0 (1<<2)
#define IND_PORT1 PORTB
#define IND_PIN1 PINB
#define IND_LINE1 (1<<1)
#define IND_PORT2 PORTB
#define IND_PIN2 PINB
#define IND_LINE2 (1<<0)
#define IND_PORT3 PORTD
#define IND_PIN3 PIND
#define IND_LINE3 (1<<7)
#define IND_PORT4 PORTD
#define IND_PIN4 PIND
#define IND_LINE4 (1<<6)
#define IND_PORT5 PORTD
#define IND_PIN5 PIND
#define IND_LINE5 (1<<5)
#define IND_PORT6 PORTB
#define IND_PIN6 PINB
#define IND_LINE6 (1<<7)
#define IND_PORT7 PORTB
#define IND_PIN7 PINB
#define IND_LINE7 (1<<6)
#define IND_PORT8 PORTD
#define IND_PIN8 PIND
#define IND_LINE8 (1<<4)
#define IND_PORT9 PORTD
#define IND_PIN9 PIND
#define IND_LINE9 (1<<3)
#define IND_PORT10 PORTD
#define IND_PIN10 PIND
#define IND_LINE10 (1<<1)
#define IND_PORT11 PORTD
#define IND_PIN11 PIND
#define IND_LINE11 (1<<0)
#define IND_PORT12 PORTC
#define IND_PIN12 PINC
#define IND_LINE12 (1<<5)
#define IND_PORT13 PORTC
#define IND_PIN13 PINC
#define IND_LINE13 (1<<4)
#define IND_PORT14 PORTC
#define IND_PIN14 PINC
#define IND_LINE14 (1<<3)
#define IND_PORT15 PORTC
#define IND_PIN15 PINC
#define IND_LINE15 (1<<2)
//-----------------------------------------------------------------------------------------------------------------------
//инициализация библиотеки
void InDataInit (void)
{
/* //включить подтяжку
IN_DATA_PORT0 |= IN_DATA_LINE0; IN_DATA_PORT1 |= IN_DATA_LINE1;
IN_DATA_PORT2 |= IN_DATA_LINE2; IN_DATA_PORT3 |= IN_DATA_LINE3;
IN_DATA_PORT4 |= IN_DATA_LINE4; IN_DATA_PORT5 |= IN_DATA_LINE5;
IN_DATA_PORT6 |= IN_DATA_LINE6; IN_DATA_PORT7 |= IN_DATA_LINE7;
IN_DATA_PORT8 |= IN_DATA_LINE8; IN_DATA_PORT9 |= IN_DATA_LINE9;
IN_DATA_PORT10 |= IN_DATA_LINE10; IN_DATA_PORT11 |= IN_DATA_LINE11;
IN_DATA_PORT12 |= IN_DATA_LINE12; IN_DATA_PORT13 |= IN_DATA_LINE13;
IN_DATA_PORT14 |= IN_DATA_LINE14; IN_DATA_PORT15 |= IN_DATA_LINE15;
*/}
//-----------------------------------------------------------------------------------------------------------------------
//функция чтения данных из параллельного порта
uint16_t InDataGet (char negative)
{
uint16_t temp = 0;
//чтение данных сенсоров
if (IND_PIN0 & IND_LINE0) temp |= 0x0001;
if (IND_PIN1 & IND_LINE1) temp |= 0x0002;
if (IND_PIN2 & IND_LINE2) temp |= 0x0004;
if (IND_PIN3 & IND_LINE3) temp |= 0x0008;
if (IND_PIN4 & IND_LINE4) temp |= 0x0010;
if (IND_PIN5 & IND_LINE5) temp |= 0x0020;
if (IND_PIN6 & IND_LINE6) temp |= 0x0040;
if (IND_PIN7 & IND_LINE7) temp |= 0x0080;
if (IND_PIN8 & IND_LINE8) temp |= 0x0100;
if (IND_PIN9 & IND_LINE9) temp |= 0x0200;
if (IND_PIN10 & IND_LINE10) temp |= 0x0400;
if (IND_PIN11 & IND_LINE11) temp |= 0x0800;
if (IND_PIN12 & IND_LINE12) temp |= 0x1000;
if (IND_PIN13 & IND_LINE13) temp |= 0x2000;
if (IND_PIN14 & IND_LINE14) temp |= 0x4000;
if (IND_PIN15 & IND_LINE15) temp |= 0x8000;
if (negative)
return temp;
return ~temp;
}
//-----------------------------------------------------------------------------------------------------------------------Я, вообще, тоже. Но тут просто решил в данном конкретном случае всё вынести в одно место для более лёгкого возможного портирования.shads писал(а):Я решение такое же применяю, единственное что я определения не в одном месте описываю
LINE - это хороший вариант. Я никак всё не мог придумать синоним, так и оставил PIN, что, действительно, создаёт некоторую путаницу. Но вот насчёт остального - в том-то и был смысл, чтобы заменить три необходимых для вашего случая определенияshads писал(а): вот так - ST7920_PORT0, ST7920_DDR0, ST7920_PIN0, ST7920_LINE0
Код: Выделить всё
#define ST7920_PORT0 PORTD
#define ST7920_DDR0 DDRD
#define ST7920_PIN0 PINDКод: Выделить всё
#define ST7920_D0 DА PIN в LINE я, пожалуй, действительно переименую.
- Сообщения: 882
- Зарегистрирован: Ср фев 22, 2012 01:25:21
У меня была аналогичная история, тоже подсказалиWiseLord писал(а):Я никак всё не мог придумать синоним, так и оставил PIN, что, действительно, создаёт некоторую путаницу.
http://radiokot.ru/forum/viewtopic.php? ... 9#p1381879
ВинАВР и 4-я студия отказались компилировать файл для 10-й Тиньки!
Какая ему нах вообще разница под какой МК компилить?
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Чем они это мотивировали? если по-русски то... какая ошибка высветилась?
А в этой тиньке ОЗУ вообще есть? Проблемы будут у Си, если ОЗУ отсутствует, как класс...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!


