Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
if (phase==3) phase=0; mask=(1<<phase++);
AVR ATmega -48 -88 -168
1<<phase++
00000019 CPI R16,0x03 Compare with immediate
0000001A BRNE PC+0x02 Branch if not equal
0000001B LDI R16,0x00 Load immediate
0000001C MOV R18,R16 Copy register
0000001D LDI R24,0x01 Load immediate
0000001E ADD R24,R16 Add without carry
0000001F MOV R16,R24 Copy register
00000020 LDI R24,0x01 Load immediate
00000021 LDI R25,0x00 Load immediate
00000022 RJMP PC+0x0003 Relative jump
00000023 LSL R24 Logical Shift Left
00000024 ROL R25 Rotate Left Through Carry
00000025 DEC R18 Decrement
00000026 BRPL PC-0x03 Branch if plus
00000027 MOV R14,R24 Copy register
int t = phase;
++phase;
mask=(1<<t);
UB было бы в случае присвоения результата переменной «phase», чего здесь нет.int t = phase;
mask=(1<<t);
++phase;
++phase; mask=(1<<t); маски будут такими: 001, 010, 011,100
mask=(1<<t);++phase; маски будут такими: 000, 001, 010,011
0000001B LDI R16,0x00 Load immediate
0000001C MOV R18,R16 Copy register
0000001D LDI R24,0x01 Load immediate
0000001E ADD R24,R16 Add without carry
0000001F MOV R16,R24 Copy register
00000019 CPI R16,0x03 if (phase == 3)
0000001A BRNE PC+0x02 goto A
0000001B LDI R16,0x00 phase = 0
0000001C MOV R18,R16 A: int t = phase
0000001D LDI R24,0x01 int c = 1
0000001E ADD R24,R16 c += phase
0000001F MOV R16,R24 phase = c
00000020 LDI R24,0x01 int tmp_mask = 1
00000021 LDI R25,0x00 int k = 0
00000022 RJMP PC+0x0003 goto B
00000023 LSL R24 C: tmp_mask <<= 1
00000024 ROL R25 tmp_mask += <carry bit>
00000025 DEC R18 B: --t
00000026 BRPL PC-0x03 if (t >= 0) goto C
00000027 MOV R14,R24 mask = mask
if (++phase>3) phase=0; mask=(1<<(phase-1));
void main()
{
int phase=4;
if (++phase>3) phase=0;
printf("%d\n",phase);
}
gcc test.c -O2
./a.out
0
If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
if(connect(...) || die(...))
{
}
заменить оператор || на |, его порядок работы будет не определен, и die() может быть вызвано раньше connect().
if(connect(...) || die(...))
{
оп_xz();
}
if(connect(...))
{
оп_xz();
}
else
{
if(die(...))
{
оп_xz();
}
}
if(connect(...) | die(...))
{
оп_xz();
}
int tmp = connect(...) | die(...);
if(tmp != 0)
{
оп_xz();
}
Код на C не должен добираться до неопределенного поведения и использовать его.
if (++phase>3) phase=0; mask=(1<<(phase-1));
00000023 LSL R24 Logical Shift Left
00000024 ROL R25 Rotate Left Through Carry
00000025 DEC R18 Decrement
00000026 BRPL PC-0x03 Branch if plus
00000027 MOV R14,R24 Copy register
if (++phase>3) {
phase=0;
}
mask=(1<<(phase-1));
— это не просто плохо, это повод к применению линейки.if (++phase<3) mask-=phase; else {mask+=phase; phase=0;}
B=0b10;
if ((A==1) && B ) {} else {}
if ((A==1) & B ) {} else {}
if (A==0 || B==1 || C==2) doSomething();дают один и тот же результат, на мой взгляд, спорное. Я не нестолько знаю стандарт описания С, чтобы утверждать, что результат логической операции приводится к одной константе и так будет во всех реализациях, а если принять что всякий не 0 — истина, то последнее выражение может и не дать истины при истинных составляющих.
if ((A==0) | (B==1) | (C==2)) doSomething();
if (phase!=6)
{ mask = ((phase==1) || (phase==3)) ? (mask+phase+1) : phase; }
else (phase=0; mask=1; }
phase++;заменить на что-то вроде : mask=pphase*;
if (pphase==pphaseend) pphase=pphasestart else pphase++;и создать соответствующий массив и указатель на него, то, скорее всего, никакие оптимизации кода не потребуются и быстродействие существенно поднимется.дают один и тот же результат, на мой взгляд, спорное.
cpi r16,0x06 1
breq newp 1/2
cpi r16,0x01 1
breq nextp 1/2
cpi r16,0x03 1
breq nextp 1/2
mov r14,r16 1
rjmp nextr 2
newp:
clr r14 1
clr 16 1
nextp:
add r14,r16 1
inc r14 1
nextr:
inc r16 1Итак, считаем — длина модуля 13 слов, количество используемых регистров — 2, время исполнения для 6 — 8 тактов, для 1 — 8 тактов, для 3 — 10 тактов, для остальных — 10 тактов, среднее время 56/6 = 9 тактов (8-10).lpm r14,z+ 3
cpi zl,dataend 1
brne nextr 1/2
sbiw z,datalen 2Считаем еще раз — длина модуля 4 слова + 6 слов массива = 10 слов, количество испльзуемых регистров — 2, время исполнения для 1-5 — 6 тактов, для 6 — 7 тактов среднее время 37/6 = 6 тактов (6-7).lpm r14,z+ 3
sbiw zl,datalen 1
cpse zl,datastart 1/3
adiw z,datalen+1 3 но он чуть длиннее — 8 тактов всегда.movw r15,zl и
movw zl,r15 и проводить операции с парой (r15,r16), что увеличивает длину модуля на 2 и время исполнения на 2 такта, тогда варианты практически сравниваются по параметрам.а если принять что всякий не 0 — истина, то последнее выражение может и не дать истины при истинных составляющих.
Each of the operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false.107) The result has type int.
const uint8_t mask[] = {0, 1, 2, 3, 4, 5};
ISR(TIM0_COMPA_vect)
{
static phase = 6;
PORTB = mask[--phase];
if(!phase) phase = 6;
}
volatile uint8_t* current_mask;
current_mask = (uint8_t *)0x0A; current_mask[0]=0; // R10
current_mask[1]=0b001;current_mask[2]=0b011;current_mask[3]=0b010;current_mask[4]=0b110;current_mask[5]=0b100;current_mask[6]=0b101;
if(StartTime > EndTime) {
CalcTime = (86400 - StartTime) + EndTime;
}
Включает бойлер на 2 часа в 5 часов вечера и 5 утра.
int StartTime= (StartH*3600)+(StartM*60)+StartS;
int EndTime= (EndH*3600)+(EndM*60)+EndS;
int CalcTime;
if(StartTime > EndTime)
{
CalcTime = (86400 - StartTime) + EndTime;
}
else
{
CalcTime = EndTime - StartTime;
}
int StartTime= (StartH*3600)+(StartM*60)+StartS;
int EndTime= (EndH*3600)+(EndM*60)+EndS;
int CalcTime;
Еще один программный ШИМ или реабилитация Attiny13a при помощи Дзен