在 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(12)-- GPIO输入,按键检测
stm32·单片机·嵌入式硬件
DLGXY1 小时前
STM32——ADC、多通道转换(十三)
stm32·单片机·嵌入式硬件
日更嵌入式的打工仔1 小时前
嵌入式MPU、MCU与SoC的本质区别
单片机·嵌入式硬件
__万波__1 小时前
STM32L475看门狗
stm32·单片机·嵌入式硬件
wanglong37132 小时前
51单片机STC8G1K08输出PWM
单片机·嵌入式硬件·51单片机
时光找茬13 小时前
【瑞萨AI挑战赛-FPB-RA6E2】+ 从零开始:FPB-RA6E2 开箱测评与 e2 studio 环境配置
c++·单片机·边缘计算
@good_good_study14 小时前
FreeRTOS内存管理
单片机
Hello_Embed15 小时前
libmodbus 移植 STM32(基础篇)
笔记·stm32·单片机·学习·modbus
qqssss121dfd17 小时前
STM32H750XBH6的ETH模块移植LWIP
网络·stm32·嵌入式硬件
jkyy201417 小时前
健康座舱:健康有益赋能新能源汽车开启移动健康新场景
人工智能·物联网·汽车·健康医疗