简体   繁体   English

写数据到寄存器

[英]write data to register

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! 谢谢!

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 volatile qualifier. 请注意,我添加了volatile限定符。 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. 在读取或写入硬件寄存器时,这总是一个好主意,因为它确保您在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. 然后用适当的gcc asms填充它们。 I like these better than direct use of pointers because: 我喜欢这些比直接使用指针更好,因为:

  • 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 asm s, I know exactly how I'm accessing the register. 最后,通过使用asm s,我确切地知道我是如何访问寄存器的。 Sometimes there are special instructions or address spaces needed to get to a register, which usually can't be generated by the C compiler. 有时需要特殊指令或地址空间才能到达寄存器,这通常不能由C编译器生成。
  • 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. 即使你不同意使用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))

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关键字时始终检查生成的机器代码,以避免出现意外。

For further references, see eg http://www.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf 有关进一步参考,请参见http://www.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf

Assuming that register has the same size as a long : 假设寄存器的大小与long相同:

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

*lcdcw1 = myValue;

LCDCW1 is just an integer value. LCDCW1只是一个整数值。 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; 例如: *(int*)LCDCW1=0x31;

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). 调整到适合(您的寄存器可能不是int尺寸)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM