C语言 将数据写入寄存器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2651955/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:11:15  来源:igfitidea点击:

write data to register

cpointersembeddedhardware

提问by martin

i have the memory address of certain register(the address LCDCW1 is C000).

我有某个寄存器的内存地址(地址 LCDCW1 是 C000)。

c codes:

c代码:

#define LCDCW1 0xC000

*LCDCW1=0x31;

i just want to write data to this register. The codes have problems, how to correct it?

我只想将数据写入这个寄存器。代码有问题,如何解决?

thx!

谢谢!

回答by Dale Hagglund

You can, as others have suggested, declare an appropriate pointer, ie,

正如其他人所建议的那样,您可以声明一个适当的指针,即

volatile uint32_t *reg = (volatile uint32_t *)0xc000;

Note that I've added the volatilequalifier. This is always a good idea when reading or writing hardware registers, because it ensures that each access you perform in your C code actually shows up in the generated code.

请注意,我添加了volatile限定符。在读取或写入硬件寄存器时,这始终是一个好主意,因为它确保您在 C 代码中执行的每次访问都实际显示在生成的代码中。

However, I usually prefer to write macros like this

不过,我通常更喜欢写这样的宏

#define READ_LCDCW1() ...
#define WRITE_LCDCW1(value) ...

and then fill these in with the appropriate gcc asms. I like these better than direct use of pointers because:

然后用适当的 gcc asms 填充它们。我比直接使用指针更喜欢这些,因为:

  • I think they read better in the code, identifying what I'm doing, reading a register, instead of focusing on how I'm doing it.
  • Some registers require a multi-step process to read from the hardware. This is hidden easily in macros of this style, and the bulk of my code still refers to the registers I'm interested in, not the complicated way the hardware makes me touch them.
  • Finally, by using asms, I know exactly how I'm accessing the register. Sometimes there are special instructions or address spaces needed to get to a register, which usually can't be generated by the C compiler.
  • Even if you disagree with the motivation for using asm statements, I'd still suggest wrapping your register accesses in macros (or inline functions) like these.
  • 我认为他们在代码中更好地阅读,识别我在做什么,阅读寄存器,而不是专注于我是如何做的。
  • 一些寄存器需要一个多步骤的过程才能从硬件中读取。这很容易隐藏在这种风格的宏中,我的大部分代码仍然是指我感兴趣的寄存器,而不是硬件让我接触它们的复杂方式。
  • 最后,通过使用asms,我确切地知道我是如何访问寄存器的。有时需要特殊指令或地址空间来访问寄存器,而这些通常不能由 C 编译器生成。
  • 即使您不同意使用 asm 语句的动机,我仍然建议将您的寄存器访问封装在这样的宏(或内联函数)中。

In your case, the simplest definitions should be:

在您的情况下,最简单的定义应该是:

#define LCDCW1_ADDR       0xc000
#define READ_LCDCW1()     (*(volatile uint32_t *)LCDCW1_ADDR)
#define WRITE_LCDCW1(val) ((*(volatile uint32_t *)LCDCW1_ADDR) = (val))

回答by Schedler

I believe one word of caution about the use the keyword volatile is in order.

我相信有关使用关键字 volatile 的一个注意事项是正确的。

Sometimes (often) what the compiler thinks volatile means is not what the programmer intended (and vice versa). It is good practice to always check the resulting machine code when the volatile keyword is used, in order to avoid surprises.

有时(通常)编译器认为 volatile 的意思不是程序员的意图(反之亦然)。使用 volatile 关键字时始终检查生成的机器代码是一种很好的做法,以避免出现意外。

For further references, see e.g. http://www.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf

如需进一步参考,请参见例如http://www.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf

回答by mouviciel

Assuming that register has the same size as a long:

假设寄存器的大小与 a 相同long

volatile long * ldccw1 = (long*)0xc000;

*lcdcw1 = myValue;

回答by Naveen

LCDCW1is just an integer value. You can not do *on that. You need to cast it to integer (or type you require) pointer and then use it. For example: *(int*)LCDCW1=0x31;

LCDCW1只是一个整数值。你不能这样做*。您需要将其转换为整数(或您需要的类型)指针,然后使用它。例如: *(int*)LCDCW1=0x31;

回答by Marcelo Cantos

I don't know what LCDCW1 means, but to write to a constant address:

我不知道 LCDCW1 是什么意思,但要写入一个常量地址:

*(int*)0xC000 = 42;

Adjust to suit (your register may not be int-sized).

调整以适应(您的寄存器可能不是整数大小)。