在 stm32 中 volatile unsigned signed 分别有什么作用,分别在什么场景下使用?

在STM32开发中,

plaintext

复制

volatile

plaintext

复制

unsigned

plaintext

复制

signed

是三个关键的关键字,它们的用途和场景如下:


1.

plaintext

复制

volatile

关键字

作用
  • 禁止编译器优化:告诉编译器该变量的值可能随时被外部因素(如硬件、中断、多线程等)改变,要求每次访问变量时都直接从内存中读取,而不是使用寄存器中的缓存值。
  • 保证内存可见性:确保变量的读写操作直接作用于内存,避免因编译器优化导致时序错误。
使用场景
  • 硬件寄存器操作
    STM32的寄存器(如

    plaintext

    复制

    GPIOx->ODR

    plaintext

    复制

    TIMx->CNT
    )必须用

    plaintext

    复制

    volatile
    修饰,因为它们的值由硬件直接修改。

    复制代码

    c

    复制

    volatile uint32_t *pReg = (volatile uint32_t*)0x40020000; // 硬件寄存器地址

  • 中断服务程序(ISR)中的共享变量
    如果变量在主循环和ISR中被共同修改,必须用

    plaintext

    复制

    volatile
    修饰,确保双方看到的变量值一致。

    复制代码

    c

    复制

    volatile uint8_t flag = 0; // 在中断中修改,在主循环中读取

  • 多线程/RTOS中的共享数据
    在实时操作系统(如FreeRTOS)中,任务间共享的变量需要

    plaintext

    复制

    volatile
    修饰(通常还需配合互斥锁)。

注意事项
  • 过度使用 plaintext

    复制

    volatile
    可能导致性能下降(频繁内存访问)。

  • 不能替代原子操作或多线程同步机制(如互斥锁)。


2.

plaintext

复制

unsigned

plaintext

复制

signed

关键字

作用
  • 指定整型的符号性
    • plaintext

      复制

      unsigned
      :无符号整数(范围:

      plaintext

      复制

      0

      plaintext

      复制

      2^n - 1
      )。

    • plaintext

      复制

      signed
      :有符号整数(范围:

      plaintext

      复制

      -2^(n-1)

      plaintext

      复制

      2^(n-1) - 1
      )。

      plaintext

      复制

      n
      为类型位数,如

      plaintext

      复制

      uint32_t
      是32位)

使用场景

plaintext

复制

unsigned
的典型场景

  • 硬件相关数据
    ADC采样值(如

    plaintext

    复制

    uint16_t adc_value
    )、定时器计数值(

    plaintext

    复制

    TIMx->CNT
    )等不会为负的值。

  • 位操作
    无符号数右移时高位补0,适合位掩码操作(如

    plaintext

    复制

    GPIO引脚控制
    )。

  • 避免溢出
    当数值可能超过有符号类型的正最大值时(如32位计数器的

    plaintext

    复制

    0xFFFFFFFF
    )。

plaintext

复制

signed
的典型场景

  • 需要负值的场景
    如温度传感器读数(

    plaintext

    复制

    int16_t temperature
    )、电机速度方向(正/负表示方向)。

  • 数学运算
    涉及负数的计算(如滤波算法、PID控制)。

注意事项
  • 默认情况下, plaintext

    复制

    int

    plaintext

    复制

    signed
    ,但

    plaintext

    复制

    char
    的符号性取决于编译器(建议显式声明)。

  • 混合使用 plaintext

    复制

    unsigned

    plaintext

    复制

    signed
    可能导致意外的类型提升和逻辑错误:

    复制代码

    c

    复制

    uint32_t a = 5; int32_t b = -10; if (a > b) { ... } // 这里b会被隐式转换为无符号数,导致比较结果错误!


3. 在STM32中的典型代码示例

硬件寄存器操作(必须用

plaintext

复制

volatile

):

复制代码

c

复制

// 定义一个GPIO输出寄存器(volatile + unsigned) volatile uint32_t *GPIOA_ODR = (volatile uint32_t*)0x40020014; *GPIOA_ODR |= 0x00000001; // 设置PA0引脚为高电平

中断服务程序中的共享变量:
复制代码

c

复制

volatile uint8_t data_ready = 0; // 主循环和UART中断共享 // 中断服务函数 void USART1_IRQHandler(void) { data_ready = 1; // 数据到达时置位标志 } // 主循环中等待标志 while (1) { if (data_ready) { process_data(); data_ready = 0; } }

使用无符号类型处理ADC数据:
复制代码

c

复制

uint16_t adc_value = 0; // ADC采样值(0-4095,无符号) adc_value = HAL_ADC_GetValue(&hadc1); // 读取ADC值

使用有符号类型处理温度数据:
复制代码

c

复制

int16_t temperature = -25; // 温度可能为负 if (temperature < 0) { heating_enable(); }


总结表

关键字 作用 典型场景
plaintext 复制 volatile 防止编译器优化,保证内存可见性 硬件寄存器、中断共享变量、多线程
plaintext 复制 unsigned 无符号整数(0到最大值) ADC采样、定时器计数、位操作
plaintext 复制 signed 有符号整数(含负数) 温度、速度方向、需要负值的计算

合理使用这些关键字可以避免嵌入式开发中常见的硬件操作错误、数据溢出和逻辑问题。

相关推荐
努力小周1 小时前
STM32智能安防系统
c语言·stm32·单片机·嵌入式硬件·物联网·计算机网络·pcb工艺
华科大胡子3 小时前
在STM32上跑通TinyML
stm32·单片机·嵌入式硬件
iCxhust4 小时前
C#进程管理程序
开发语言·汇编·stm32·单片机·c#·微机原理
SUNNYSPY0017 小时前
AO3402-ASEMI开关电源专用AO3402
单片机
iCxhust7 小时前
MTK8088单板机制作(一)时钟电路
汇编·单片机·嵌入式硬件·微机原理·8088单板机
崇山峻岭之间8 小时前
单片机直流有刷电机速度环PID控制实验
单片机·嵌入式硬件
xiangw@GZ8 小时前
智能锁浮空系统指纹头金属环ESD防护技术分析
单片机·嵌入式硬件
项目題供诗8 小时前
STM32-DMA直接存储器存储(二十)
stm32·单片机·嵌入式硬件
TDengine (老段)8 小时前
TDengine 扫描算子 — TableScan、TagScan 与下推优化
大数据·数据库·物联网·时序数据库·tdengine·涛思数据
耳朵东先生9 小时前
STM32 开发利器:SEGGER RTT 日志打印与 Shell 实践解析
单片机·嵌入式硬件