写数据到寄存器

mar*_*tin 8 c hardware embedded pointers

我有某个寄存器的存储器地址(地址LCDCW1是C000).

c代码:

#define LCDCW1 0xC000

*LCDCW1=0x31;
Run Code Online (Sandbox Code Playgroud)

我只想将数据写入该寄存器.代码有问题,如何纠正呢?

谢谢!

Dal*_*und 19

你可以像其他人建议的那样,声明一个合适的指针,即

volatile uint32_t *reg = (volatile uint32_t *)0xc000;
Run Code Online (Sandbox Code Playgroud)

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

但是,我通常喜欢写这样的宏

#define READ_LCDCW1() ...
#define WRITE_LCDCW1(value) ...
Run Code Online (Sandbox Code Playgroud)

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

  • 我认为他们在代码中读得更好,识别我正在做什么,阅读一个寄存器,而不是专注于我是如何做的.
  • 一些寄存器需要多步骤来从硬件读取.这很容易隐藏在这种风格的宏中,我的大部分代码仍然是指我感兴趣的寄存器,而不是硬件让我触摸它们的复杂方式.
  • 最后,通过使用asms,我确切地知道我是如何访问寄存器的.有时需要特殊指令或地址空间才能到达寄存器,这通常不能由C编译器生成.
  • 即使你不同意使用asm语句的动机,我仍然建议将你的寄存器访问包装在这些宏(或内联函数)中.

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

#define LCDCW1_ADDR       0xc000
#define READ_LCDCW1()     (*(volatile uint32_t *)LCDCW1_ADDR)
#define WRITE_LCDCW1(val) ((*(volatile uint32_t *)LCDCW1_ADDR) = (val))
Run Code Online (Sandbox Code Playgroud)


Sch*_*ler 5

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

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

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