Ви не увійшли.
#define out1_on PORTA &=~(1UL<<0);
#define out2_on PORTA &=~(1UL<<1);
#define out3_on PORTA &=~(1UL<<2);
#define out4_on PORTA &=~(1UL<<4);
#define out5_on PORTA &=~(1UL<<3);
#define out6_on PORTA &=~(1UL<<5);
#define out7_on PORTA &=~(1UL<<6);
#define out8_on PORTA &=~(1UL<<7);
#define out9_on PORTG &=~(1UL<<2);
#define out10_on PORTC &=~(1UL<<7);
#define out11_on PORTC &=~(1UL<<6);
#define out12_on PORTC &=~(1UL<<5);
#define out13_on PORTC &=~(1UL<<4);
#define out14_on PORTC &=~(1UL<<3);
#define out15_on PORTC &=~(1UL<<2);
#define out16_on PORTC &=~(1UL<<1);
#define out17_on PORTC &=~(1UL<<0);
#define out18_on PORTG &=~(1UL<<0);
#define out19_on PORTG &=~(1UL<<1);
#define out20_on PORTD &=~(1UL<<7);
Всем привет, помогите "запихнуть" эти макроопределения в массив, структуру или смесь что бы можно было работать как с массивом. Спасибо. Я написал макроопределение таким образом:
#define out_on(x) PORTC &=~(1UL << port_out[x]);
но порты то разные.
Неактивний
Если вам нужно адресовать порты по переменной то одними макросами вы это не сделаете, нужно что-то вроде этого:
void out_on(uint8_t n)
{
*pin[n].port &= pin[n].bitmask;
}
Неактивний
У меня это пришло из программы управление сдвиговым регистром, при помощи 32 битной переменной я мог управлять 4 микросхемами.
Передовая в функцию которая вызывалась по таймеру номер бита и "номер операции" я мог управлять "портами". Но тут все по другому. Неужели нет ни чего такого что бы с моими портами вывода можно было работать также. Или подскажите как передавать и хранить эти макроопределения в массиве
uint32_t out_shift = 0;
uint8_t Bufer_set_res[32];
#define Out_on(x) out_shift |=(1UL << x)
#define Out_off(x) out_shift &=~ (1UL << x)
void on_off(uint8_t bit_n, uint8_t set_res)
{
if(set_res == 0)
out_shift &= ~(1UL << Bufer_bit[Count_t1]); // сброс.
else if(set_res == 1)
out_shift |= (1UL << Bufer_bit[Count_t1]); // установка бита.
else ifset_res == 2)
out_shift ^= (1UL << Bufer_bit[Count_t1]); // инверсия бита.
}
Неактивний
Если вам нужно адресовать порты по переменной то одними макросами вы это не сделаете, нужно что-то вроде этого:
void out_on(uint8_t n) { *pin[n].port &= pin[n].bitmask; }
Здесь у вас используется массив и структура? В который нужно поместить номер порта а в структуру его название?
Остання редакція goodspeedmen (2018-06-29 17:30:36)
Неактивний
Макроопределения в массиве хранить невозможно.
Неактивний
Здесь у вас используется массив и структура? В который нужно поместить номер порта а в структуру его название?
Массив структур. Указатель на порт, и маску бита порта. Я думаю вы сами сможете описать массив констант. Чем вас не устраивает digitalWrite(..) из Ардуино?
Неактивний
goodspeedmen пише:Здесь у вас используется массив и структура? В который нужно поместить номер порта а в структуру его название?
Массив структур. Указатель на порт, и маску бита порта. Я думаю вы сами сможете описать массив констант. Чем вас не устраивает digitalWrite(..) из Ардуино?
Потому что это не ардуино. Напишите пример плиз.
Неактивний
В русском языке есть слово пожалуйста а в украинском будь ласка.
const struct {
__IO uint8_t * port;
uint8_t bitmask;
}
pin[] = {{&PORTA, 0xXX}, ...};
Что-то вроде этого. Смотрите в заголовочных файлах точный тип порта.
Остання редакція Вячеслав Азаров (2018-06-29 18:35:59)
Неактивний
char letter[] = {'q','A','A','A','A','A','A','A','A','G','C','C','C','C','C','C','C','C','G','G','D'};
uint8_t pin[] = {9,0,1,2,3,4,5,6,7,2,7,6,5,4,3,2,1,0,0,1,7};
#define out_on(x) port ## letter[x] &= ~(1u << pin[x]);
#define out_off(x) port ## letter[x] |= (1u << pin[x]);
Но как я понял компилятор объединяет 'portletter' как две строки а не как значение массива
Неактивний
goodspeedmen, вы методом тыка язык не освоите, слишком много тыкать придется. Нужно читать учебники, справочники и документацию на компилятор.
Неактивний
Решил проблему так, вместо битовой операции был применен оператор switch. Конечно это не самое оригинальное решение но все же.
void port_on(uint8_t potr)
{
switch(potr)
{
case 1: out1_on; break;
case 2: out2_on; break;
case 3: out3_on; break;
case 4: out4_on; break;
case 5: out5_on; break;
case 6: out6_on; break;
case 7: out7_on; break;
case 8: out8_on; break;
case 9: out9_on; break;
case 10: out10_on; break;
case 11: out11_on; break;
case 12: out12_on; break;
case 13: out13_on; break;
case 14: out14_on; break;
case 15: out15_on; break;
case 16: out16_on; break;
case 17: out17_on; break;
case 18: out18_on; break;
case 19: out19_on; break;
case 20: out20_on; break;
}
}
void port_off(uint8_t potr)
{
switch(potr)
{
case 1: out1_off; break;
case 2: out2_off; break;
case 3: out3_off; break;
case 4: out4_off; break;
case 5: out5_off; break;
case 6: out6_off; break;
case 7: out7_off; break;
case 8: out8_off; break;
case 9: out9_off; break;
case 10: out10_off; break;
case 11: out11_off; break;
case 12: out12_off; break;
case 13: out13_off; break;
case 14: out14_off; break;
case 15: out15_off; break;
case 16: out16_off; break;
case 17: out17_off; break;
case 18: out18_off; break;
case 19: out19_off; break;
case 20: out20_off; break;
}
}
Неактивний
Плохое решение. Оператор Switch будет выполнять все Case пока не найдет нужное. Эффективней что-то типа как Азаров предложил функцией. Еще лучше структуру с адресами массивов с портов с готовыми значениями что б оттранслировалось в команду с относительной адресацией. Тогда в две команды уложится.
Остання редакція Batu (2018-06-30 11:06:17)
Неактивний
Плохое решение. ...
Да, если строго, но сейчас хорошие оптимизирующие компиляторы, с преобразованием алгоритмов, способны сами построить оптимальные вычислительные структуры для локальных вычислений. Например для оператора switch(.) может выполняться переход по таблице. Так что в принципе сойдет. Однако, лучше не надеяться на искусственный ум и записывать алгоритмы прямолинейно.
Неактивний
Batu пише:Плохое решение. ...
Да, если строго, но сейчас хорошие оптимизирующие компиляторы, с преобразованием алгоритмов, способны сами построить оптимальные вычислительные структуры для локальных вычислений. Например для оператора switch(.) может выполняться переход по таблице. Так что в принципе сойдет. Однако, лучше не надеяться на искусственный ум и записывать алгоритмы прямолинейно.
Тут не получится построить переход по таблице. Операцию сравнения необходимо выполнять с разными значениями. Оптимизатор не сможет предусмотреть. Не знаю есть ли в этом языке перечислимые типы. Вот с ними можно и переход по таблице получить. Там оптимизатор поможет. А в общем случае, надо понимать как работает транслятор и как выполняются команды. Я собственно, почему внимание обратил на этот пост, потому как есть идея реализации перечислимых типов без введения отдельного понятия а просто как любой тип данных представляющий массив. Кстати, определение алфавита именно так делается.. Ибо буквы (Letter) это массив объектов, а тип Mark это ссылка на этот массив. Ну, и Switch организован как массив (или группа) событий. Тогда еще один фокус можно реализовать. Отдельно идет определение переменной тип массива событий в которой хранится состояние, и отдельно Select - переход по этой переменной. Должно вкусно получиться.
Неактивний
Тут не получится построить переход по таблице. Операцию сравнения необходимо выполнять с разными значениями. Оптимизатор не сможет предусмотреть. Не знаю есть ли в этом языке перечислимые типы. Вот с ними можно и переход по таблице получить. Там оптимизатор поможет. А в общем случае, надо понимать как работает транслятор и как выполняются команды. ...
Бату, я не буду с вами спорить, а тем более, что либо доказывать. То, что я сказал я знаю точно. А что мне надо понимать, прошу вас мне не указывать. В AVR для этого используются комманды IJMP, ICALL. На псевдооде: goto on[x]!
Неактивний
Batu пише:Тут не получится построить переход по таблице. Операцию сравнения необходимо выполнять с разными значениями. Оптимизатор не сможет предусмотреть. Не знаю есть ли в этом языке перечислимые типы. Вот с ними можно и переход по таблице получить. Там оптимизатор поможет. А в общем случае, надо понимать как работает транслятор и как выполняются команды. ...
Бату, я не буду с вами спорить, а тем более, что либо доказывать. То, что я сказал я знаю точно. А что мне надо понимать, прошу вас мне не указывать. В AVR для этого используются комманды IJMP, ICALL. На псевдооде: goto on[x]!
И где ты увидел спор, доказательства или, тем более указания? С какого перепугу меня вообще должна интересовать твоя личность? Я говорю по теме. И если тебя интересует чего-то узнать, то прочитай. Хуже не будет. Команды IJMP, ICALL выполняют переход по косвенному адресу, а здесь нужна относительная адресация. И не переход, а чтение. Тогда можно реализовать предложенную задачу красиво. Для тех кому это интересно.
P.S. Если уберешь немного самолюбия с тобой будет легче общаться. Не переоценивай значение своей персоны. Как правило она мало кого интересует. От слова вообще. У меня было к тебе предложение, но ты не потянул. Что не мешает здесь общаться. С уважением!
P.P.S. Можно на ты. Я не гордый..
Остання редакція Batu (2018-06-30 13:46:06)
Неактивний
...
Удачи.
Неактивний
В русском языке есть слово пожалуйста а в украинском будь ласка.
const struct { __IO uint8_t * port; uint8_t bitmask; } pin[] = {{&PORTA, 0xXX}, ...};
Что-то вроде этого. Смотрите в заголовочных файлах точный тип порта.
__IO Что это такое?
Неактивний
Плохое решение. Оператор Switch будет выполнять все Case пока не найдет нужное. Эффективней что-то типа как Азаров предложил функцией. Еще лучше структуру с адресами массивов с портов с готовыми значениями что б оттранслировалось в команду с относительной адресацией. Тогда в две команды уложится.
Я согласен, что это не самое лучшее решение, у меня есть готовая отлаженная программа её просто нужно перенести на новый контроллер. Вы почему то думаете что я умею читать мысли:
const struct
{
__IO uint8_t * port;
uint8_t bitmask;
}
pin[] = {{&PORTA, 0xXX}, ...};
Я не понял задумку...
Неактивний
__IO Что это такое?
Это, обычно, макро-спецификатор класса памяти портов ввода, зависящий от архитектуры ЭВМ. Разберитесь как это делается в Ардуино. Для AVR, возможно, __IO определять не нужно. Смотрите файлы arduino-1.8.5/hardware/arduino/avr/variants/standard/pins_arduino.h и arduino-1.8.5/hardware/arduino/avr/cores/arduino/wiring_digital.c, а так же их заголовки.
Неактивний
Я согласен, что это не самое лучшее решение, у меня есть готовая отлаженная программа её просто нужно перенести на новый контроллер. Вы почему то думаете что я умею читать мысли:
const struct { __IO uint8_t * port; uint8_t bitmask; } pin[] = {{&PORTA, 0xXX}, ...};
Я не понял задумку...
А она есть))
Неактивний
Плохое решение. Оператор Switch будет выполнять все Case пока не найдет нужное.
НЕТ, только не это
Оператор switch так не делает. Он делает двумя способами:
1. Если параметры идут числами подряд (0,1,2,3,4....) то строит матрицу переходов - массив с указателем для jump в нужное место. И это самый быстрый вариант.
2. Если параметры идут в разброс (0, 7, 128...) то строит бинарное дерево переходов. И это тоже очень быстро.
Ну так по крайней мере работают современные компиляторы типа gcc. И я это проверял лично смотря ассемблерный сгенерированый листинг, потому что такие утверждения сыпятся с регулярной завидностью и пахнут откровенным бредом.
Вот кто вам это говорит, покажите мне этого врага адекватного человечества? Погуглил. Похоже ноги у этого мифа растут из-за оператора break. И не понимания ассемблера/машинных инструкций. Break даже мешает просто сравнивать все подряд, из-за него бы наоборот пришлось бы дополнительные (несложные) ухищрения добавлять.
Остання редакція LynX (2018-07-01 19:00:57)
Неактивний
Batu пише:Плохое решение. Оператор Switch будет выполнять все Case пока не найдет нужное.
НЕТ, только не это
Оператор switch так не делает. Он делает двумя способами:
1. Если параметры идут числами подряд (0,1,2,3,4....) то строит матрицу переходов - массив с указателем для jump в нужное место. И это самый быстрый вариант.
2. Если параметры идут в разброс (0, 7, 128...) то строит бинарное дерево переходов. И это тоже очень быстро.Ну так по крайней мере работают современные компиляторы типа gcc. И я это проверял лично смотря ассемблерный сгенерированый листинг, потому что такие утверждения сыпятся с регулярной завидностью и пахнут откровенным бредом.
Вот кто вам это говорит, покажите мне этого врага адекватного человечества? Погуглил. Похоже ноги у этого мифа растут из-за оператора break. И не понимания ассемблера/машинных инструкций. Break даже мешает просто сравнивать все подряд, из-за него бы наоборот пришлось бы дополнительные (несложные) ухищрения добавлять.
Зачем так много слов? Сделай такой кусок "Если параметры идут в разброс (0, 7, 12)" и покажи ассемблерный листинг.
Остання редакція Batu (2018-07-01 20:30:50)
Неактивний
Потому что это не для Вас, а для юных падаванов которых еще можно спасти.
Код.
Хотел бы услышать мнение Азарова по поводу такой оптимизации. А для примера было бы достаточно и 3-х Case. Меня не переубедил. Такое решение все равно жопа для решения предложенной задачи. ИМХО
Неактивний