在 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 有符号整数(含负数) 温度、速度方向、需要负值的计算

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

相关推荐
腾讯云中间件10 小时前
腾讯云 TDMQ MQTT 版解锁 5.0 协议,你的物联网设备“更会说话”了
物联网·消息队列
蝈蝈(GuoGuo)13 小时前
STM32103CBT6显示ST7789通过SPI方式显示柬埔寨文
stm32·单片机·嵌入式硬件
大鼻噶喳14 小时前
使用VSCode开发MCU,FreeRTOS进Hard_Fault调试
vscode·单片机
我命由我1234515 小时前
嵌入式 STM32 开发问题:烧录 STM32CubeMX 创建的 Keil 程序没有反应
c语言·开发语言·c++·stm32·单片机·嵌入式硬件·嵌入式
麦德泽特15 小时前
超高速总线CDCTL01A 芯片在机器人领域的应用解析
人工智能·嵌入式硬件·物联网·机器人·信息与通信
vicorv2517 小时前
电流传感器在汽车中的应用:从BMS电池管理到电机控制的工程解析
stm32·单片机·嵌入式硬件
物联网嵌入式小冉学长17 小时前
3.TCP回响服务器实现及源码分析上
stm32·网络协议·tcp/ip·嵌入式
几道之旅1 天前
零基础RT-thread第二节:按键控制
c语言·stm32
Archer-1 天前
解决STM32H7系列串口DMA发送一次卡死
stm32·单片机·嵌入式硬件
深圳市尚想信息技术有限公司1 天前
【深尚想】SM8102ABC 95%高效降压芯片!TWS/物联网专用,2A输出+1.5mm超小体积
物联网·低功耗·电源管理·消费电子·转换器·降压芯片