原创 一条语句一条命---向汇编C的目标迈进

2006-12-30 01:25 4653 10 10 分类: MCU/ 嵌入式


一条语句一条命---向汇编C的目标迈进
mood25.gif hotpower 发表于 2005-7-15 12:49 AVR 单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖举报该贴


在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);//清除计数器溢出中断标志
}  


PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
10
关闭 站长推荐上一条 /3 下一条