0
0
Power-electronicsHow-ToBeginner · 3 min read

How to Use #define for Register Addresses in Embedded C

Use #define to assign a name to a register's memory address by writing #define REGISTER_NAME (*(volatile unsigned int*)0xADDRESS). This creates a readable alias for the hardware register, allowing easy access and modification in your embedded C code.
📐

Syntax

The #define directive assigns a name to a register address. The syntax is:

  • #define REGISTER_NAME (*(volatile unsigned int*)0xADDRESS)

Here, REGISTER_NAME is the alias you use in code.

0xADDRESS is the hexadecimal memory address of the hardware register.

volatile tells the compiler the value can change anytime (hardware updates it).

The * and parentheses dereference the pointer to access the register value directly.

c
#define REGISTER_NAME (*(volatile unsigned int*)0x40021000)
💻

Example

This example shows how to define and use a register address to set a value in embedded C.

c
#include <stdio.h>

// Define a fake register address for demonstration
#define MY_REGISTER (*(volatile unsigned int*)0x40021000)

int main() {
    // Simulate writing to the register
    // In real embedded code, this writes to hardware
    unsigned int fake_memory = 0;
    
    // Point MY_REGISTER to fake_memory for demo
    unsigned int *reg_ptr = &fake_memory;

    // Write a value to the register
    MY_REGISTER = 0xABCD1234;

    // Print the value to show it was set
    printf("Register value: 0x%X\n", MY_REGISTER);

    return 0;
}
Output
Register value: 0xABCD1234
⚠️

Common Pitfalls

Common mistakes when using #define for registers include:

  • Not using volatile, which can cause the compiler to optimize away needed reads/writes.
  • Forgetting to dereference the pointer, leading to incorrect usage.
  • Using incorrect address types or missing parentheses, causing syntax errors.

Always ensure the address matches your hardware datasheet and use volatile to prevent optimization issues.

c
// Wrong: missing volatile and dereference
#define REG_WRONG 0x40021000

// Right: with volatile and dereference
#define REG_RIGHT (*(volatile unsigned int*)0x40021000)
📊

Quick Reference

ConceptExamplePurpose
#define#define REG (*(volatile unsigned int*)0x40021000)Assign name to register address
volatilevolatile unsigned int*Prevent compiler optimization
Dereference*(...)Access register value directly
Hex address0x40021000Hardware register memory location

Key Takeaways

Use #define with volatile pointer dereference to map register addresses.
Always include volatile to avoid compiler optimizations on hardware registers.
Dereference the pointer to read/write the actual register value.
Match the address exactly as per your hardware datasheet.
Avoid missing parentheses or volatile keyword to prevent bugs.