打印

MD,highgear绝对是故意的,我都已经**过一次了

[复制链接]
6607|45
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
刘前辈|  楼主 | 2009-4-16 10:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
如果要把计数器T0中16位数据传到int i;中,用C51的话,有什么简单高效的方法?

  i=TH0*256+TL0; 

显然不好。编译出来(如下)比汇编复杂多了,C显然有更简洁的写法?

C:0x0003    AF8C     MOV      R7,TH0(0x8C)
C:0x0005    EF       MOV      A,R7
C:0x0006    FE       MOV      R6,A
C:0x0007    AD8A     MOV      R5,TL0(0x8A)
C:0x0009    7C00     MOV      R4,#0x00
C:0x000B    E4       CLR      A
C:0x000C    2D       ADD      A,R5
C:0x000D    F509     MOV      0x09,A
C:0x000F    EC       MOV      A,R4
C:0x0010    3E       ADDC     A,R6
C:0x0011    F508     MOV      0x08,A
    21: } 

相关帖子

沙发
yewuyi| | 2009-4-16 10:08 | 只看该作者

i=TH0<<8+TL0;

使用特权

评论回复
板凳
yewuyi| | 2009-4-16 10:11 | 只看该作者

或者是用结构+联合

然后采用向变量传值的方式,估计这样最省代码,但带来的问题就是看起来麻烦。

使用特权

评论回复
地板
computer00| | 2009-4-16 10:21 | 只看该作者

直接对内存地址赋值

((unsigned char *)i)[0]=TH0; 
((unsigned char *)i)[1]=TL0;

使用特权

评论回复
5
常来21ic| | 2009-4-16 10:40 | 只看该作者

学习了!

使用特权

评论回复
6
刘前辈|  楼主 | 2009-4-16 10:49 | 只看该作者

2楼说的我试过 x=(TH0<<8)+TL0; 没得到化简。

    12:  x=(TH0<<8)+TL0; 
    13:  
C:0x0003    AF8C     MOV      R7,TH0(0x8C)
C:0x0005    EF       MOV      A,R7
C:0x0006    FE       MOV      R6,A
C:0x0007    AD8A     MOV      R5,TL0(0x8A)
C:0x0009    7C00     MOV      R4,#0x00
C:0x000B    E4       CLR      A
C:0x000C    2D       ADD      A,R5
C:0x000D    F509     MOV      0x09,A
C:0x000F    EC       MOV      A,R4
C:0x0010    3E       ADDC     A,R6
C:0x0011    F508     MOV      0x08,A
    14: } 

使用特权

评论回复
7
刘前辈|  楼主 | 2009-4-16 10:59 | 只看该作者

圈圈4楼说的编译结果如下,没达到预期效果。如何解决?

    12: ((unsigned char *)i)[0]=TH0;  
C:0x0003    AA08     MOV      R2,0x08
C:0x0005    A909     MOV      R1,0x09
C:0x0007    7B00     MOV      R3,#0x00
C:0x0009    E58C     MOV      A,TH0(0x8C)
C:0x000B    120000   LCALL    C:0000
    13: ((unsigned char *)i)[1]=TL0; 
    14:  
C:0x000E    900001   MOV      DPTR,#0x0001
C:0x0011    E58A     MOV      A,TL0(0x8A)
C:0x0013    120000   LCALL    C:0000
    15: } 

使用特权

评论回复
8
yewuyi| | 2009-4-16 11:03 | 只看该作者

结构+联合的办法就是对内存直接操作了

使用特权

评论回复
9
huangqi412| | 2009-4-16 11:05 | 只看该作者

俺也遇到了,无刷电机控制,对速度要求特高

俺是先编译完,查反汇编,然后再修改成嵌汇编滴。。。  把+-*/ 还有数据搬运,先编译,再反汇编修改成嵌汇编了

使用特权

评论回复
10
huangqi412| | 2009-4-16 11:07 | 只看该作者

比较不喜欢看联合,整的n长一串东东

使用特权

评论回复
11
yewuyi| | 2009-4-16 11:10 | 只看该作者

大致描述

union {
      int i;
      struct {
             uchar   j;
             uchar   k;
             }
      }

然后,可以j=TH0 ; k=TL0;执行完后,就可以使用i了。

要注意大小端的问题,也可能是反过来给值的。

使用特权

评论回复
12
刘前辈|  楼主 | 2009-4-16 11:11 | 只看该作者

谢谢9楼和楼上。

俺总觉得C没那么差,用嵌入式汇编是迫不得已。

这么简单的常用数据传输,真的迫不得已了吗?

记得在哪里看过简单写法,一时记不起来了,找找。

使用特权

评论回复
13
computer00| | 2009-4-16 11:12 | 只看该作者

哦,看来没有自动识别变量地址,自己强制指定一下。

void main(void)
{
     unsigned int i;
     ((unsigned char data *)i)[0]=TH0;
     ((unsigned char data *)i)[1]=TL0;
}

编译后的汇编代码:

    22: void main(void) 
    23: { 
    24:         unsigned int i; 
    25:         ((unsigned char data *)i)[0]=TH0; 
C:0x000F    A809     MOV      R0,0x09
C:0x0011    A68C     MOV      @R0,TH0(0x8C)
    26:         ((unsigned char data *)i)[1]=TL0; 
C:0x0013    E8       MOV      A,R0
C:0x0014    04       INC      A
C:0x0015    F8       MOV      R0,A
C:0x0016    A68A     MOV      @R0,TL0(0x8A)
    27: } 
C:0x0018    22       RET      

使用特权

评论回复
14
yewuyi| | 2009-4-16 11:12 | 只看该作者

反汇编比结构+联合更罗嗦,更没有通用性

也更难维护,基本等于不合理的做法。


所以个人认为绝不应该采用小黄的做法。

使用特权

评论回复
15
huangqi412| | 2009-4-16 11:16 | 只看该作者

呵呵,老叶,俺开始也是和蛋蛋一样 指针弄的,

后面,俺不知道为什么RP这么差,keil莫名其妙出了很多灵异现象,挺晕的,干脆嵌汇编,这下总保险了。

使用特权

评论回复
16
程疗匠人| | 2009-4-16 11:18 | 只看该作者

这已有讨论。

https://bbs.21ic.com/club/bbs/list.asp?boardid=11&t=3264388&tp=ANSI%20C%u4E2D%u5982%u4F55%u80FD%u5C06%u4E24%u4E2Achar%u62FC%u5408%u6210%u4E00%u4E2Ashort%20int%uFF1F%u4F7F%u7528%u6307%u9488%u53EF%u4EE5%u5417%uFF1F
相关链接:https://bbs.21ic.com/club/bbs/list.asp?boardid=11&t=3264388&tp=ANSI%20C%u4E2D%u5982%u4F55%u80FD%u5C06%u4E24%u4E2Achar%u62FC%u5408%u6210%u4E00%u4E2Ashort%20int%uFF1F%u4F7F%u7528%u6307%u9488%u53EF%u4EE5%u5417%uFF1F

使用特权

评论回复
17
computer00| | 2009-4-16 11:21 | 只看该作者

抱歉,俺搞错了,忘记取地址了,应该是这样的:

unsigned int i;
void main(void)
{
((unsigned char *)&i)[0]=TH0;
((unsigned char *)&i)[1]=TL0;
}

这个汇编结果才是最爽的……我说怎么一直不对呢……

    21: void main(void) 
    22: { 
    23: ((unsigned char *)&i)[0]=TH0; 
C:0x000F    858C08   MOV      i(0x08),TH0(0x8C)
    24: ((unsigned char *)&i)[1]=TL0; 
C:0x0012    858A09   MOV      0x09,TL0(0x8A)
    25: } 
C:0x0015    22       RET      

使用特权

评论回复
18
xwj| | 2009-4-16 11:24 | 只看该作者

给你两种方法,结果完全一样:

#include <REG52.H>
#include <intrins.h>

#define uchar unsigned char
#define uint  unsigned int
#define ulong unsigned long

union Union_tow{                     //
uchar uc;
uint ui;
uchar mem[2];
}unBuf;

uint i;

void main(void)
{
    TR0=1;
    while(1)
    {
        TR0=0;
        unBuf.mem[0]=TH0;
        unBuf.mem[1]=TL0;
        *((unsigned char *)(&i))=TH0; 
        *((unsigned char *)(&i) +1)=TL0; 
        TR0=1;
    }
}

Keil生成的代码:(看,Keil还是蛮聪明的嘛~)
    18: void main(void) 
    19: { 
    20:         TR0=1; 
C:0x0003    D28C     SETB     TR0(0x88.4)
    21:         while(1) 
    22:         { 
    23:                 TR0=0; 
C:0x0005    C28C     CLR      TR0(0x88.4)
    24:                 unBuf.mem[0]=TH0; 
C:0x0007    858C08   MOV      unBuf(0x08),TH0(0x8C)
    25:                 unBuf.mem[1]=TL0; 
C:0x000A    858A09   MOV      0x09,TL0(0x8A)
    26:                 *((unsigned char *)(&i))=TH0;  
C:0x000D    858C0A   MOV      i(0x0A),TH0(0x8C)
    27:                 *((unsigned char *)(&i) +1)=TL0;  
C:0x0010    858A0B   MOV      0x0B,TL0(0x8A)
    28:                 TR0=1; 
C:0x0013    D28C     SETB     TR0(0x88.4)
    29:         } 
C:0x0015    80EE     SJMP     C:0005
C:0x0017    787F     MOV      R0,#0x7F
C:0x0019    E4       CLR      A
C:0x001A    F6       MOV      @R0,A
C:0x001B    D8FD     DJNZ     R0,C:001A
C:0x001D    75810B   MOV      SP(0x81),#0x0B
C:0x0020    020003   LJMP     main(C:0003)


注意:

读取定时器值时如果不能一次读出,则一定要先停掉定时器!


否则很容易临界数据错误!

使用特权

评论回复
19
computer00| | 2009-4-16 11:26 | 只看该作者

个人觉得用联合太麻烦,另外定义一个联合,直接用指针爽

使用特权

评论回复
20
刘前辈|  楼主 | 2009-4-16 11:27 | 只看该作者

谢谢圈圈,跟几位大侠学到一些方法。

圈圈能不能给我讲讲为什么下面的写法可以:

int i;
i=TH0;  //  这里应该没有疑问。
(char)i=TH0;  //关键这里得到了简化。


    11: int i; 
    12: i=TL0; 
C:0x000F    AF8A     MOV      R7,TL0(0x8A)
    13: (char)i=TH0; 
    14:  
C:0x0011    AE8C     MOV      R6,TH0(0x8C)
    15: } 

这样完全跟汇编一样简了。

(char)i=TH0;  //有什么理论可以?谢谢大家。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

24

主题

1038

帖子

4

粉丝