2014-06-29 2 views
0

Я пишу программу на микроконтроллерах AVR. Он должен проверить фактическую температуру и показать ее на 7-сегментном дисплее. И эта проблема, которая у меня есть: я создал структуру со всеми переменными, относящимися к температуре (температура, положение указателя, знак и единица) и увидел, что время выполнения, например, деление на 10 или mod 10 намного больше, чем когда я использую обычную локальную переменную. Я не знаю, почему. Я использую Atmel Studio 6.2.различное время выполнения между локальной переменной и статической структурой

struct dane 
{ 
    int32_t temperature; 
    int8_t pointer; 
    int8_t sign; 
    int8_t unit; 
}; 
//************************************ 
//inside function of timer interrupt 
static struct dane present; 

//***************************** 
//tested operations: 
present.temperature % 10; //execution time: ~380 processor's cycles, on normal local variable ~4 cycles. 
present.temperature /= 10; //execution time: ~611 cycles 

Я даю вам эту функцию, когда я использую его и немного ассемблера.

ISR(TIMER0_OVF_vect) 
{ 
    static int8_t i = 4; 
    static struct dane present; 

    if(i == 4 && (TCCR0 & (1 << CS01))) 
    { 
     i = 0; 
     present = current; 
     if(present.temperature < 0) 
      present.temperature = -present.temperature;   
    } 

    if((TCCR0 & ((1 << CS00) | (1 << CS02))) && i != 0) 
    { 
     i = 0; 
    } 
    if(present.unit == current.unit) //time between here and fist instruction in function print equals about 300 cycles. 
    { 
     print((i * present.sign == 3 && present_temperature % 10 == 0) ? 16 : present_temperature % 10, displays[i], i == present.pointer); 
    } 
    else 
    { 
     print(current.unit, displays[i],0); 
     if(i == 4) 
     { 
      i = 3; 
      TCCR0 = (1 << CS01); 
      present.unit = current.unit; 
     } 
    } 

    present.temperature /= 10; 
    i++; 
} 

И код сборки для одного до последней инструкции:

present.temperature /= 10; 
0000021F LDI R28,0x7D  Load immediate 
00000220 LDI R29,0x00  Load immediate 
00000221 LDD R22,Y+0  Load indirect with displacement 
00000222 LDD R23,Y+1  Load indirect with displacement 
00000223 LDD R24,Y+2  Load indirect with displacement 
00000224 LDD R25,Y+3  Load indirect with displacement 
00000225 LDI R18,0x0A  Load immediate 
00000226 LDI R19,0x00  Load immediate 
00000227 LDI R20,0x00  Load immediate 
00000228 LDI R21,0x00  Load immediate 
00000229 RCALL PC+0x01AC  Relative call subroutine 
0000022A STD Y+0,R18  Store indirect with displacement 
0000022B STD Y+1,R19  Store indirect with displacement 
0000022C STD Y+2,R20  Store indirect with displacement 
0000022D STD Y+3,R21  Store indirect with displacement 

Я не могу использовать int16_t для температуры, потому что я использовать ту же самую структуру внутри функции, которая кроющая температуру от датчика, и оно проще работать с числом с десятичной запятой, когда я умножаю его на 10, используя подходящее число.

+0

Каковы параметры оптимизации компилятора вашего дела? –

+0

Уровень оптимизации -O1 – legier

ответ

0

Там должно быть что-то не так с вашими таймингов:

present.temperature % 10; //execution time: ~380 processor's cycles, on normal local variable ~4 cycles. 
present.temperature /= 10; //execution time: ~611 cycles 

операция по модулю 10 для 32-битного значения никогда не будет происходить в 4 такта с AVR. 380 циклов звучат много, но это более реалистично для операции 32:32 деления. Я боюсь, что даже целочисленное разделение на AVR займет много времени с длинными целыми числами.

Совершенно естественно, что операции с статическими переменными модуля занимают немного больше времени, поскольку их нужно извлекать и хранить в ОЗУ. Это занимает, возможно, 10 дополнительных тактовых циклов на байт по сравнению с переменными регистра (локальные переменные часто находятся в регистре. Переменная, находящаяся в структуре, не должна вообще изменять тайминги в таком случае (с указателями на структуры, которые могут иметь эффект).

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

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


Если вы заинтересованный в том, чтобы сделать ваш код быстрее, я предлагаю вам попробовать использовать int16_t для температуры. Ваш динамический диапазон при измерении температуры составляет чуть более 12 бит (это должно быть, например, 0,1 ° C для температур от -100 ° C до + 300 ° C), так что должно быть достаточно 16-разрядных цепей.

+0

Скорость первого примера может быть вызвана тем, что операция не действует. Вероятно, компилятор оптимизировал его. (Использование '% =' вместо этого может показывать разные результаты.) – UncleO

+0

@UncleO: Хорошая точка! Но почему тогда 4 цикла и 380 циклов? С линией, как сейчас, она должна быть 0/0 ... Во всяком случае, не видя более полного кода, это довольно сложно проанализировать. – DrV

Смежные вопросы