WinAvr в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение ARV »

я тут :) однако, я уже устал вещать прописные истины - вы можете вдоволь начитаться их на этом форуме при помощи поиска: все переменные для прерываний должны быть volatile, о том, как делать динамическую индикацию на 7-сегментниках я писал на своем сайте и здесь не один раз, преобразование чисел в символы индикатора - то же самое, код написан тяп-ляп... короче, ковыряться в этом нет желания, извините... чего стоит только это (а там и остального хватает):

Код: Выделить всё

ISR (ADC_vect)
{
adc[n]=ADCW;
switch(n) // преобразование согласно номера канала, переход к 0 каналу после 4-го
   {
   case 0x00: fbin[n]=adc[n]*1000/1024; n++; ADMUX=ADMUX+1; break;
   case 0x01: fbin[n]=adc[n]*1000/1024; n++; ADMUX=ADMUX+1; break;
   case 0x02: fbin[n]=adc[n]*100*5/1024;n++; ADMUX=ADMUX+1; break;
   case 0x03: fbin[n]=adc[n]*10*5*6/1024;n=0;ADMUX=0b01000000; break;
   default: break;
   }
ADCSRA=0xFF;
}
когда это должно делаться примерно как-то так:

Код: Выделить всё

ISR (ADC_vect){
   static uint8_t n = 0;   // номер канала
   adc[n] = ADC;
   fbin[n] = adc[n] * koefficient[n]; // коэффициенты по каналам в отдельном массиве
   if(++n >= 4) n = 0;  // выбор следующего номера канала
   ADMUX = REFS | n;  // включение канала. REFS - константа выбора опорника
   ADCSRA |= _BV(ADSC); // запуск очередного измерения
}
и даже в этом случае оптимальнее коэффициенты хранить во FLASH, чтобы ОЗУ не тратить напрасно; массив fbin заполнять в основном цикле, т.к. длительность прерывания должна быть минимальной, а необходимости именно в прерывании делать вычисления - нет.

короче, разберитесь с формой, а потом поговорим о содержании. обычно протеус достаточно качественно работает с подобными простыми алгоритмами, так что скорее всего ваш код неверен - и неудивительно: алгоритм вы четко не продумали, и явно где-то плюха.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
dns
Открыл глаза
Сообщения: 53
Зарегистрирован: Пн фев 09, 2009 10:16:27

Re: WinAvr в вопросах и ответах

Сообщение dns »

Доброго времени суток! Подскажите,друзья, как правильно сделать ассемблерную вставку, чтобы в ней обрабатывалась переменная из основного сишного кода?
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение ARV »

dns писал(а):Доброго времени суток! Подскажите,друзья, как правильно сделать ассемблерную вставку, чтобы в ней обрабатывалась переменная из основного сишного кода?
если не секрет - зачем вам это? вы действительно чувствуете в себе уверенность обойти оптимизатор компилятора? или даже пяток тактов экномии вам важен?

дело в том, что руководство (далеко не полное!) по ассемблерным вставкам - это 9 страниц А4 текста... а ограничиться просто какой-то выдержкой из него - вряд ли вы сумеете воспользоваться этим...

если очень важно быстродействие, может, лучше задуматься о реализации целых функций на ассемблере? подключение ассемблерных файлов к сишному проекту (как и сам ассемблер из GCC) намного проще и удобнее...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
dns
Открыл глаза
Сообщения: 53
Зарегистрирован: Пн фев 09, 2009 10:16:27

Re: WinAvr в вопросах и ответах

Сообщение dns »

Оптимизатор мне конечно не обойти, но кое-что за ним прибрать могу. Вообще оптимизатор является оптимизатором только для матерых эмбедеров, а у остальных программистов си-код становиться весьма ветвистым в асме.

Попробую поработать с подключаемыми файлами, спасибо за совет.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение ARV »

dns писал(а):Вообще оптимизатор является оптимизатором только для матерых эмбедеров, а у остальных программистов си-код становиться весьма ветвистым в асме.
ничего не понял
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
dns
Открыл глаза
Сообщения: 53
Зарегистрирован: Пн фев 09, 2009 10:16:27

Re: WinAvr в вопросах и ответах

Сообщение dns »

я в том смысле, что неграмотно написаный код на си в асме превращается в сплошные дебри.
Конкретно сейчас я привожу к жизни чужую программу, которая не работала именно по причине неуспевания некоторых функций. Просто заменив 5 раз
PORTС|=1<<PIN_STROB; на
asm("SBI 0x15,2"); удалось ускорить программу на 20% (!)
но это, конечно, грубый подход, не хватает мне опыта, а некоторые опытные сишники в своих оптимизациях доходят вообще до непонятных вещей
uint8_t i;
uint32_t counter;

тогда операции типа

i = (uint8_t) counter;

лучше писать в виде

i = *(uint8_t *) &counter;

Утверждается, что экономится 6 тактов процессора. Так что оптимизатор, как и любой инструмент, приносит пользу только когда им правильно пользоваться.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение ARV »

я могу утверждать с полной уверенностью, что ваш пример с PORTC компилировался БЕЗ оптимизатора, так как с включением оптимизатора (-Os) оператор PORTB |= 1<<PB2; компилируется в одну ассемблерную команду:

Код: Выделить всё

   PORTB |= 1<<PB2;
  32:   c2 9a          sbi   0x18, 2   ; 24


под оптимизатором я имел ввиду исключительно работу компилятора, а не извращения программиста типа обмана компилятора указателеями и т.п. оптимизатор неплохо справляется и без таких изголений.

на счет второго вашего примера - это также чушь. при включенной оптимизации (-Os) эффект наблюдается прямо противоположный заявленному:

Код: Выделить всё

uint32_t counter;
uint8_t i,n;

int main(void) {
   i = counter;
   n = (uint8_t *)&counter;   
}
а вот результат компиляции:

Код: Выделить всё

   i = counter;
  32:   80 91 62 00    lds   r24, 0x0062
  36:   80 93 61 00    sts   0x0061, r24
   n = (uint8_t *)&counter;   
  3a:   82 e6          ldi   r24, 0x62   ; 98
  3c:   90 e0          ldi   r25, 0x00   ; 0
  3e:   80 93 60 00    sts   0x0060, r24
как видите, первый оператор скомпилировался в 2 команды ассемблера, а второй - в три :)))

хотя без оптимизации (-O0) второй вариант на 2 команды короче:

Код: Выделить всё

   i = counter;
  3a:   80 91 62 00    lds   r24, 0x0062
  3e:   90 91 63 00    lds   r25, 0x0063
  42:   a0 91 64 00    lds   r26, 0x0064
  46:   b0 91 65 00    lds   r27, 0x0065
  4a:   80 93 61 00    sts   0x0061, r24
   n = (uint8_t *)&counter;   
  4e:   82 e6          ldi   r24, 0x62   ; 98
  50:   90 e0          ldi   r25, 0x00   ; 0
  52:   80 93 60 00    sts   0x0060, r24


я настоятельно рекомендую вам не заниматься ерундой, а включить оптимизатор и просто писать программы (желательно, аккуратно и без ошибок) :)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
1exa
Встал на лапы
Сообщения: 106
Зарегистрирован: Ср дек 09, 2009 00:58:22
Откуда: Киев

Re: WinAvr в вопросах и ответах

Сообщение 1exa »

А как в WinAvr прошивать фьюзы?
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение ARV »

1exa писал(а):А как в WinAvr прошивать фьюзы?
WinAVR не занимается прошивкой МК - это компилятор, а не программатор. в комплекте есть и утилита для прошивки avrdude, однако работать с ней начинающему сложновато.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
1exa
Встал на лапы
Сообщения: 106
Зарегистрирован: Ср дек 09, 2009 00:58:22
Откуда: Киев

Re: WinAvr в вопросах и ответах

Сообщение 1exa »

В винавр можно автоматом заливать прошивку если зделать мейк фаил но как таким образом фьюзы выставлять ? Аврдуо использовал с граф оболочкой.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение ARV »

в makefile в цели пишите командную строку запуска avrdude, а в его командной строке пишите параметр для зашивания фьюзов - отдельно для старшего, младшего и расширенного байтов. короче, читайте доку avrdude :)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
32768
Родился
Сообщения: 6
Зарегистрирован: Чт авг 19, 2010 20:50:02

Re: WinAvr в вопросах и ответах

Сообщение 32768 »

Начал изучать С,но не смог сделать самой простой вещи,а именно скопировать один из битов переменной в бит другой переменной или порта,не изменяя остальных битов (DATA.0->PORTC.1 например).
Как это на С делается?
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение ARV »

32768 писал(а):Начал изучать С,но не смог сделать самой простой вещи,а именно скопировать один из битов переменной в бит другой переменной или порта,не изменяя остальных битов (DATA.0->PORTC.1 например).
Как это на С делается?

как установить бит(ы) переменной, не меняя остальные биты в ней?
как узнать, установлен (или сброшен) определенный бит в переменной?
а так же некоторые другие вопросы начинающих - ответы здесь.

P.S. не привыкайте к нестандартным приемам типа PORTC.1 или DATA.2 - нет такой формы обращения к битам в языке Си.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
AI_Disable
Сверлит текстолит когтями
Сообщения: 1116
Зарегистрирован: Чт окт 15, 2009 14:16:18
Откуда: Екб
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение AI_Disable »

32768 писал(а):Начал изучать С,но не смог сделать самой простой вещи,а именно скопировать один из битов переменной в бит другой переменной или порта,не изменяя остальных битов (DATA.0->PORTC.1 например).
Как это на С делается?

Код: Выделить всё

var_1|=var_2&0b00000001; //Копируем 0-й бит из var_2 в var_1, остальные биты var_1 не изменяются
var_1|=var_2&0b10000000; //Копируем 7-й бит из var_2 в var_1, остальные биты var_1 не изменяются
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение ARV »

сдается мне, AI_Disable, вы не поняли нюанса: вопрошалось о том, как перенести бит, не совпадающий по порядковому номеру с исходным... в вашем ответе номера битов одинаковы. если с моей подсказки (и вашей) топикстартер не дотумкает, как надо поступить - придется послать его к истокам: K&R или хотя бы куда-то в википедию, что ли... короче, учить синтаксис Си :)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
AI_Disable
Сверлит текстолит когтями
Сообщения: 1116
Зарегистрирован: Чт окт 15, 2009 14:16:18
Откуда: Екб
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение AI_Disable »

ARV писал(а):сдается мне, AI_Disable, вы не поняли нюанса: вопрошалось о том, как перенести бит, не совпадающий по порядковому номеру с исходным...

Каюсь, да, не обратил должного внимания. К тому же, не учёл, что переменная, в которую копируют, не обязательна пуста. Похоже, тут не обойтись без if.
Аватара пользователя
AlexFisher
Мучитель микросхем
Сообщения: 493
Зарегистрирован: Вт апр 21, 2009 13:31:27
Откуда: Санкт-Петербург
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение AlexFisher »

1. Сделать через if - несколько громоздко, но удобочитаемо.
2. Сделать через промежуточную переменную. Непосредственно в порту делать нельзя, потому что нужный бит нужно сначала сбросить.

Код: Выделить всё

temp=PINC;
temp&=`(1 << NumBitToOut);  // сброс нужного бита
PORTC=temp | (((DATA >> NumBitFrom) & 0b11111110) << NumBitToOut);


Иначе говоря, если биты разные, то нужный бит сначала двигаем вправо до крайней позиции, маскируем остальные биты, двигаем на нужную позицию. В результате получаем маску для наложения на выходной порт.
Это ассемблерный подход, но, по моему мнению, правильный.
Имеет смысл оформить макросом или инлайновой функцией.
[i]Да здравствует всё то, благодаря чему мы не смотря ни на что![/i]
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение ARV »

AlexFisher писал(а):1. Сделать через if - несколько громоздко, но удобочитаемо.

для задачи, которая была озвучена, использование if действительно лишнее и не такое уж удобочитаемое. как вам такой вариант:

Код: Выделить всё

var |= (PORTC & _BV(PC1)) ? _BV(0) : 0;
:))) раз уж вы взялись юзать WinAVR - юзайте его на полную катушку, т.е. используйте макросы, которые за вас уже придуманы командой разработчиков (это я про _BV())
AlexFisher писал(а):2. Сделать через промежуточную переменную. Непосредственно в порту делать нельзя, потому что нужный бит нужно сначала сбросить.
не понял :( откуда вы про сброс взяли? не было об этом речи...
AlexFisher писал(а):Иначе говоря, если биты разные, то нужный бит сначала двигаем вправо до крайней позиции, маскируем остальные биты, двигаем на нужную позицию. В результате получаем маску для наложения на выходной порт.
Это ассемблерный подход, но, по моему мнению, правильный.
и в ассемблере это не правильный подход, и в Си так же. сдвиг на несколько битов - это не такая уж элементарная операция, особенно если переменные не однобайтовые, в то время как проверка состояния бита и на ассемблере 1 команда, и на Си будет скомпилирована в 1 команду. ну ладно, пусть не одна :) но все равно сдвиг на 5 битов будет хуже, чем sbrs|sbrc и sbr|cbr, а сдвиг на 12 битов тем паче :))) поэтому оптимальнее сделать именно через проверку и установку бита "в случае если..." :)))
AlexFisher писал(а):Имеет смысл оформить макросом или инлайновой функцией.
опять же, не посоветую вообще писать инлайновые функции, если вы до конца не представляете, как компилятор с ними поступает. лучше ограничиться простой static-функцией... а вот на счет макроса - вполне разумно :)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
32768
Родился
Сообщения: 6
Зарегистрирован: Чт авг 19, 2010 20:50:02

Re: WinAvr в вопросах и ответах

Сообщение 32768 »

AlexFisher писал(а):

Код: Выделить всё

temp=PINC;
temp&=`(1 << NumBitToOut);  // сброс нужного бита
PORTC=temp | (((DATA >> NumBitFrom) & 0b11111110) << NumBitToOut);



И это язык высокого уровня...
На ассемблере поменьше писанины для того же действия.
Ну ладно, будем курить дальше.
За ответы спасибо!
Аватара пользователя
AlexFisher
Мучитель микросхем
Сообщения: 493
Зарегистрирован: Вт апр 21, 2009 13:31:27
Откуда: Санкт-Петербург
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение AlexFisher »

ARV писал(а):
AlexFisher писал(а):2. Сделать через промежуточную переменную. Непосредственно в порту делать нельзя, потому что нужный бит нужно сначала сбросить.
не понял :( откуда вы про сброс взяли? не было об этом речи...
AlexFisher писал(а):Иначе говоря, если биты разные, то нужный бит сначала двигаем вправо до крайней позиции, маскируем остальные биты, двигаем на нужную позицию. В результате получаем маску для наложения на выходной порт.
Это ассемблерный подход, но, по моему мнению, правильный.
и в ассемблере это не правильный подход, и в Си так же. сдвиг на несколько битов - это не такая уж элементарная операция, особенно если переменные не однобайтовые, в то время как проверка состояния бита и на ассемблере 1 команда, и на Си будет скомпилирована в 1 команду. ну ладно, пусть не одна :) но все равно сдвиг на 5 битов будет хуже, чем sbrs|sbrc и sbr|cbr, а сдвиг на 12 битов тем паче :))) поэтому оптимальнее сделать именно через проверку и установку бита "в случае если..." :)))

Про "сбросить бит" я имел в виду то, чтобы применить к биту операцию ИЛИ, там должен быть 0, иначе мы не сможем этой операцией записать в бит 0.
Речь шла о ситуации, когда один из операндов является портом, следовательно, про 16 бит говорить, я думаю, не стоит, хотя переменная может быть любой разрядности. Если номера битов являются константами, то, конечно, не имеет смысла двигать бит туда-сюда. Нужно сразу сдвинуть в нужную сторону на разность номеров битов.
Вообще, у каждой задачи может быть множество решений. Автор выберет то, что ему будет понятней.
[i]Да здравствует всё то, благодаря чему мы не смотря ни на что![/i]
Ответить

Вернуться в «AVR»