在51中,尤其是IO部分,我们可以轻松地用C写出汇编的指令条数,即"汇编级的C程序"
但在AVR中确实有点难...
我们常在小容量MCU烦恼,为几个字节郁闷...
现给出一个例子供大家参考,因为光靠优化也是不行的,也应该从程序的书写习惯开始...
void UsiObj::USI_OVERFLOW(void) { unsigned char temp;//避免编译警告 // DDRB &= ~((1 << SCL) | (1 << SDA)); //SCL设置为输入方式,SCL信号由主机提供,此语句由3条指令组成!!!(不如分开写!!!) DDRB &= ~(1 << SCL); //SCL设置为输入方式,SCL信号由主机提供(只用一条指令) DDRB &= ~(1 << SDA); //SDA设置为输入方式 (只用一条指令) //以下2种写法的编译代码(2条指令): // 3cc: b2 99 sbic 0x16, 2 ; 22//可以看出temp只是做个"桥"以说明整个while()的判断为char类型!!! // 3ce: fe cf rjmp .-4 ; 0x3cc while (temp = (PINB & (1 << SCL)));//等待SCL=0主机处理结束(只用2条指令)(用暂存器好处多多) // while (unsigned char temp = (PINB & (1 << SCL)));//等待SCL=0主机处理结束(只用2条指令)(出现讨厌的编译警告) ///////////////////////////////////////////////////////////// // while ((unsigned char)(PINB & (1 << SCL)));//无用不能优化!!! ///////////////////////////////////////////////////////////// //abc://goto写法一样只用2条指令但要被拍砖 //temp = PINB & (1 << SCL); // if (temp) goto abc; //(只用2条指令) ///////////////////////////////////////////////////////////// //以下3种写法的编译代码(10条指令): // 3cc: 86 b3 in r24, 0x16 ; 22 // 3ce: 99 27 eor r25, r25 // 3d0: 96 95 lsr r25 // 3d2: 87 95 ror r24 // 3d4: 96 95 lsr r25 // 3d6: 87 95 ror r24 // 3d8: 81 70 andi r24, 0x01 ; 1 // 3da: 90 70 andi r25, 0x00 ; 0 // 3dc: 88 23 and r24, r24 // 3de: b1 f7 brne .-20 ; 0x3cc // while ((PINB & (1 << SCL)));//等待SCL=0主机处理结束 // for(;(PINB & (1 << SCL));); //abc://不用temp暂存的“潇洒” // if (PINB & (1 << SCL)) goto abc; // if ((1 << SCL) & PINB) goto abc;//好象与次序无关!!! //以下写法的编译代码(10条指令): // 3d0: 86 b3 in r24, 0x16 ; 22 // 3d2: 99 27 eor r25, r25 // 3d4: 96 95 lsr r25 // 3d6: 87 95 ror r24 // 3d8: 96 95 lsr r25 // 3da: 87 95 ror r24 // 3dc: 82 27 eor r24, r18//搞不明白此句 // 3de: 93 27 eor r25, r19//搞不明白此句 // 3e0: 80 fd sbrc r24, 0 // 3e2: f6 cf rjmp .-20 ; 0x3d0 ///////////////////////////////////////////////////////////// // loop_until_bit_is_set(PINB, SCL); ///////////////////////////////////////////////////////////// PORTB &= ~_BV(SCL);//保持低电平 DDRB |= _BV(SCL);//SCL设置为输入方式,从机占用SCL总线,以便从机长期处理 switch(Status) { case 0: //状态TW_START,从机地址判别 break; case 1: //状态TW_MT_SLA_ACK,主发从收模式 break; case 2: //状态TW_MR_SLA_ACK或TW_MR_DATA_ACK,主收从发模式0 break; case 3: //状态主发从收模式(接收数据状态) break; case 4: //主收从发模式NOACK break; case 5: //主收从发模式(发送数据状态) break; case 6: //状态TW_MT_DATA_ACK,主发从收模式 break; case 7: //状态主发从收模式(接收数据状态) break; default: //其他状态出错 USICR &= ~_BV(USIOIE);//清除USIOIE标志,全部数据发送完毕,不发送ACK信号 // break; } DDRB &= ~_BV(SCL);//释放SCL总线 USISR |= _BV(USIOIF);//清除计数器溢出中断标志 }
|
|
文章评论(0条评论)
登录后参与讨论