首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >嵌入式C数组索引文本与变量问题

嵌入式C数组索引文本与变量问题
EN

Stack Overflow用户
提问于 2017-06-05 16:00:24
回答 1查看 266关注 0票数 3

我正在工作中的第一个嵌入式C项目中,我遇到了一种令我困惑的行为。

我是usindKeilsss5IDE,并通过下面的链接uVision找到了如何映射到特殊功能寄存器(SFR)内存空间

我用下面两个文件片段做的

dataStructures.h

代码语言:javascript
复制
typedef unsigned char byte;
typedef struct DAC {        
    byte loc[15]; 
} DAC;
extern DAC DAC_MAP; 

DAC_MAP.a51

代码语言:javascript
复制
PUBLIC DAC_MAP

DAC_MAP     DATA  0xB9

END

然后我有C代码,它只在使用1的文字值时才能工作。

代码语言:javascript
复制
byte i = 1;
DAC_MAP.loc[i] = value; // Does not write to the SFR
DAC_MAP.loc[1] = value; // Writes to the SFR

我真的很想能够按索引写到一个位置,而不必写大的开关用例来解决这个问题。

对为什么会发生这种事有什么想法吗?

DAC_MAP.a51

代码语言:javascript
复制
PUBLIC DAC_MAP

DAC_MAP     DATA  0xB9

END

driver.c

代码语言:javascript
复制
#include <DP8051XP.H> 

typedef unsigned char byte;

typedef struct DAC {        
    byte loc[15]; 
} DAC;

extern DAC DAC_MAP; 

int main(void) {
    byte i = 1;

    DAC_MAP.loc[i] = 0xAA; // Does not write to the SFR
    DAC_MAP.loc[1] = 0xAA; // Writes to the SFR

    return 0;
}

当我在KEIL uVision 5调试器中运行这段代码时,您可以在内存映射中看到,当由变量执行索引时,没有任何更改,但是当使用文字时,值会按预期变化。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-06-05 19:16:00

这个问题是因为您试图使用间接寻址访问8051的特殊功能寄存器,这是不支持的。您将不得不强制编译器使用直接寻址。

来自通用SFR接口

8051中的SFRs仅可直接寻址。这意味着地址必须是程序的一部分。没有办法间接解决SFRs问题。所以指针不起作用。看看关于内部数据内存的Intel文档,它应该变得清晰了。 这样做的一种方法是为每个SFR地址定义一个SFR,并使用一个大开关语句,如下所示: sfr SFR_0x80 = 0x80;sfr SFR_0x81 = 0x81;sfr SFR_0x82 = 0x82;。。void write_sfr (无符号字符sfr_address,无符号字符值){ switch (sfr_address) { case 0x80: SFR_0x80 = value;SFR_0x80;case 0x81: SFR_0x81 = value;SFR_0x81;case 0x82: SFR_0x82 = value;SFR_0x82};

因为您的编译器看起来很聪明,可以将DAC_MAP.loc[1]转换成直接地址,所以这个driver.c可能适用于您:

代码语言:javascript
复制
#include <DP8051XP.H> 

typedef unsigned char byte;
typedef struct DAC {        
    byte loc[15]; 
} DAC;
extern DAC DAC_MAP;

static void write_dac_map(byte i, byte d) {
    switch (i) {
        case 0:  DAC_MAP.loc[0]  = d; break;
        case 1:  DAC_MAP.loc[1]  = d; break;
        case 2:  DAC_MAP.loc[2]  = d; break;
        case 3:  DAC_MAP.loc[3]  = d; break;
        case 4:  DAC_MAP.loc[4]  = d; break;
        case 5:  DAC_MAP.loc[5]  = d; break;
        case 6:  DAC_MAP.loc[6]  = d; break;
        case 7:  DAC_MAP.loc[7]  = d; break;
        case 8:  DAC_MAP.loc[8]  = d; break;
        case 9:  DAC_MAP.loc[9]  = d; break;
        case 10: DAC_MAP.loc[10] = d; break;
        case 11: DAC_MAP.loc[11] = d; break;
        case 12: DAC_MAP.loc[12] = d; break;
        case 13: DAC_MAP.loc[13] = d; break;
        case 14: DAC_MAP.loc[14] = d; break;
        default: //error
    }
}

int main(void) {
    byte i = 1;
    write_dac_map(i, 0xAA);
    return 0;
}

如果查看代码生成的程序集(由stargateur提供),问题在C:0x0806

代码语言:javascript
复制
     9: int main(void) { 
    10:     byte i = 1; 
    11:  
C:0x0800    7F01     MOV      R7,#0x01
    12:     DAC_MAP.loc[i] = 0xAA; // Does not write to the SFR 
C:0x0802    74B9     MOV      A,#DAC_MAP(0xB9)
C:0x0804    2F       ADD      A,R7
C:0x0805    F8       MOV      R0,A
C:0x0806    76AA     MOV      @R0,#0xAA
    13:     DAC_MAP.loc[1] = 0xAA; // Writes to the SFR 
    14:  
C:0x0808    75BAAA   MOV      0xBA,#0xAA
    15:     return 0; 
C:0x080B    E4       CLR      A
C:0x080C    FE       MOV      R6,A
C:0x080D    1F       DEC      R7
    16: }
C:0x080E    22       RET      
C:0x080F    787F     MOV      R0,#0x7F
C:0x0811    E4       CLR      A
C:0x0812    F6       MOV      @R0,A
C:0x0813    D8FD     DJNZ     R0,C:0812
C:0x0815    758107   MOV      SP(0x81),#0x07
C:0x0818    020800   LJMP     main(C:0800)

MOV @R0,#0xAA使用间接寻址,并将0xAA写入地址0xBA处的内部RAM (R0设置为0xB9 + 1)。

MOV 0xBA,#0xAA指令在C:0x0808使用直接寻址,并将写0xAA到SFR的地址0xBA。(使用直接寻址时,0x000x7F之间的地址指的是SFRs,而不是0x7F中的位置)。

本网站提供了更多关于8051:http://www.8052.com/tutaddr.phtml的不同寻址方式的信息。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44372928

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档