u_you
驱动中牛
驱动中牛
  • 注册日期2002-04-11
  • 最后登录2010-03-05
  • 粉丝0
  • 关注0
  • 积分19分
  • 威望3点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:880回复:3

Franklin的陷井

楼主#
更多 发布于:2002-11-03 20:38
问题的提出:

让我们先看一段程序:

这是一段摸拟I2C总路线写的程序,
#define Byte unsigned char

sbit SCL = 0x80;
sbit SDA = 0x81;

void WaitForACK(void);

void I2CWrite(Byte _Data)
{
char i;
for(i = 0; i < 8; i++){
if(_Data & 0x80)
SDA = 1;
else
SDA = 0;
SCL = 1;
SCL = 0;
_Data <<= 1;
}
WaitForACK();
}

你认为它能正确的把的所给的数传送出去吗?

在将它烧到IC上之前,我一直以为这不会有任何问题。
可是,系统就是不能正常工作。
拿示波器一量,在SCL的前8个脉冲期间,SDA从来就没变化,要么高,要么低。也不能等到任何ACK。

又把程序检查了N遍,没办法,只能检查LIST文件了。
一看,豁然开朗:
stmt level    source
   1          #define Byte unsigned char
   2          
   3          sbit SCL = 0x80;
   4          sbit SDA = 0x81;
   5          
   6          void WaitForACK(void);
   7          
   8          void I2CWrite(Byte _Data)
   9          {
  10   1       char i;
  11   1       for(i = 0; i < 8; i++){
  12   2       if(_Data & 0x80)
  13   2       SDA = 1;
  14   2       else
  15   2       SDA = 0;
  16   2       SCL = 1;
  17   2       SCL = 0;
  18   2       _Data <<= 1;
  19   2       }
  20   1       WaitForACK();
  21   1      }
  22          
C51 COMPILER V6.11.28,  I2C                       11/02/102  19:10:55  PAGE  2

ASSEMBLY LISTING OF GENERATED OBJECT CODE

            ; FUNCTION _I2CWrite (BEGIN)
              ; Register R7 is assigned to parameter _Data
              ; R6 is assigned to i
                                           ; SOURCE LINE # 11
0000 7E00           MOV    R6,#000H
0002         ?FOR1:
                                           ; SOURCE LINE # 12
0002 EF             MOV    A,R7
0003 30E704         JNB    ACC.7,?ELSE1
                                           ; SOURCE LINE # 13
0006 D281           SETB   SDA
0008 8002           SJMP   ?NXT5
000A         ?ELSE1:
                                           ; SOURCE LINE # 15
000A C281           CLR    SDA
000C         ?NXT5:
                                           ; SOURCE LINE # 16
000C D280           SETB   SCL
                                           ; SOURCE LINE # 17
000E C280           CLR    SCL
                                           ; SOURCE LINE # 18
0010 EF             MOV    A,R7
0011 C3             CLR    C
0012 33             RLC    A
                                           ; SOURCE LINE # 11
0013 0E             INC    R6
0014 BE08EB         CJNE   R6,#008H,?FOR1
                                           ; SOURCE LINE # 20
0017 120000  R      LCALL  WaitForACK
001A 22             RET    

且看:
                                           ; SOURCE LINE # 18
0010 EF             MOV    A,R7
0011 C3             CLR    C
0012 33             RLC    A
少了一行
MOV R7,A
也就是说
_Data <<= 1;
被翻成了
_Data << 1;

解决方法:
方法一:
选择菜单Options->Project,打开C51->Optimizer选项,将Optimizer level改为2以下即可。
优点:间单,对于文件别处类似问题一样有效。
缺点:牺牲代码质量,影响代码运行速度。

修改后生成代码如下:

            ; FUNCTION _I2CWrite (BEGIN)
              ; Register R7 is assigned to parameter _Data
              ; R6 is assigned to i
                                           ; SOURCE LINE # 11
0000 7E00           MOV    R6,#000H
0002         ?FOR1:
                                           ; SOURCE LINE # 12
0002 EF             MOV    A,R7
0003 30E704         JNB    ACC.7,?ELSE1
                                           ; SOURCE LINE # 13
0006 D281           SETB   SDA
0008 8002           SJMP   ?NXT5
000A         ?ELSE1:
                                           ; SOURCE LINE # 15
000A C281           CLR    SDA
000C         ?NXT5:
                                           ; SOURCE LINE # 16
000C D280           SETB   SCL
                                           ; SOURCE LINE # 17
000E C280           CLR    SCL
                                           ; SOURCE LINE # 18
0010 EF             MOV    A,R7
0011 C3             CLR    C
0012 33             RLC    A
0013 FF             MOV    R7,A
0014         ?NXT4:
                                           ; SOURCE LINE # 11
0014 0E             INC    R6
0015 EE             MOV    A,R6
0016 6480           XRL    A,#080H
0018 B48800         CJNE   A,#088H,?LAB3
001B         ?LAB3:
001B 40E5           JC     ?FOR1
001D         ?NXT3:
                                           ; SOURCE LINE # 20
001D 120000  R      LCALL  WaitForACK
0020 22             RET    

            ; FUNCTION _I2CWrite (END)
方法二:
增加一临时变量:
优缺点与方法一刚好相反。
修改后原代码:
#define Byte unsigned char

sbit SCL = 0x80;
sbit SDA = 0x81;

void WaitForACK(void);

void I2CWrite(Byte _Data)
{
char i;
Byte temp = _Data;

for(i = 0; i < 8; i++){
if(temp & 0x80)
SDA = 1;
else
SDA = 0;
SCL = 1;
SCL = 0;
temp <<= 1;
}
WaitForACK();
}
生成代码:
stmt level    source
   1          #define Byte unsigned char
   2          
   3          sbit SCL = 0x80;
   4          sbit SDA = 0x81;
   5          
   6          void WaitForACK(void);
   7          
   8          void I2CWrite(Byte _Data)
   9          {
  10   1       char i;
  11   1       Byte temp = _Data;
  12   1      
  13   1       for(i = 0; i < 8; i++){
  14   2       if(temp & 0x80)
  15   2       SDA = 1;
  16   2       else
  17   2       SDA = 0;
  18   2       SCL = 1;
  19   2       SCL = 0;
  20   2       temp <<= 1;
  21   2       }
  22   1       WaitForACK();
  23   1      }
  24          
  25          
C51 COMPILER V6.11.28,  I2C                       11/03/102  20:06:43  PAGE  2

ASSEMBLY LISTING OF GENERATED OBJECT CODE

            ; FUNCTION _I2CWrite (BEGIN)
              ; Register R7 is assigned to parameter _Data
                                           ; SOURCE LINE # 11
0000 8F00    R      MOV    temp,R7
              ; R6 is assigned to i
                                           ; SOURCE LINE # 13
0002 7E00           MOV    R6,#000H
0004         ?FOR1:
                                           ; SOURCE LINE # 14
0004 E500    R      MOV    A,temp
0006 30E704         JNB    ACC.7,?ELSE1
                                           ; SOURCE LINE # 15
0009 D281           SETB   SDA
000B 8002           SJMP   ?NXT5
000D         ?ELSE1:
                                           ; SOURCE LINE # 17
000D C281           CLR    SDA
000F         ?NXT5:
                                           ; SOURCE LINE # 18
000F D280           SETB   SCL
                                           ; SOURCE LINE # 19
0011 C280           CLR    SCL
                                           ; SOURCE LINE # 20
0013 E500    R      MOV    A,temp
0015 C3             CLR    C
0016 33             RLC    A
0017 F500    R      MOV    temp,A
                                           ; SOURCE LINE # 13
0019 0E             INC    R6
001A BE08E7         CJNE   R6,#008H,?FOR1
                                           ; SOURCE LINE # 22
001D 120000  R      LCALL  WaitForACK
0020 22             RET    

            ; FUNCTION _I2CWrite (END)

注意,原代码第11行:
Byte temp = _Data;
不可写成:
Byte temp;
temp = _Data;
否则无效.
附件名称/大小 下载次数 最后更新
2002-11-03_Franklin.doc (35KB)  1
狼,食肉目犬科犬属。外形和狼狗相似。 有狗的忠诚,但无狗的奴性。 [img]http://www.driverdevelop.com/forum/avatar/u_you_wolf.jpg[/img]
WindThruEars
驱动老牛
驱动老牛
  • 注册日期2002-11-17
  • 最后登录2004-07-10
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2002-11-04 04:08
也不找个好点的compiler。
我是假耳朵
u_you
驱动中牛
驱动中牛
  • 注册日期2002-04-11
  • 最后登录2010-03-05
  • 粉丝0
  • 关注0
  • 积分19分
  • 威望3点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2002-11-04 23:45
也不找个好点的compiler。
 
谢谢,我还以为没人看呢。
我也没办法,底层用的是Franklin。接口被定死了.
狼,食肉目犬科犬属。外形和狼狗相似。 有狗的忠诚,但无狗的奴性。 [img]http://www.driverdevelop.com/forum/avatar/u_you_wolf.jpg[/img]
meizhx
驱动中牛
驱动中牛
  • 注册日期2002-10-21
  • 最后登录2004-06-16
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2002-11-05 14:24
等管道最下边,兴趣没了
现在还来得及
游客

返回顶部