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

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

相关推荐
Hello_Embed1 小时前
libmodbus 移植 STM32(USB 串口后端篇)
笔记·stm32·单片机·嵌入式·freertos·libmodbus
来自晴朗的明天3 小时前
14、光耦隔离电路(EL3H7)
单片机·嵌入式硬件·硬件工程
G***技3 小时前
杰和IB3-272:以低功耗高性能打造新一代工业智能交互核心
单片机·嵌入式硬件·物联网
czhaii5 小时前
STC AI8052U单片机特点
单片机
MAR-Sky5 小时前
keil5中数据的不同定义和单片机(以stc8为例)里的对应关系(idata,xdata,data,code)
单片机·嵌入式硬件
北京耐用通信5 小时前
破解AGV多协议互联难题:耐达讯自动化Profinet转Devicenet网关如何实现高效协同
人工智能·科技·物联网·网络协议·自动化·信息与通信
项目題供诗7 小时前
51单片机入门(八)
单片机·嵌入式硬件·51单片机
国产化创客7 小时前
ESP32平台web服务器开发框架选型与分析
物联网·智能家居·智能硬件
羽获飞7 小时前
从零开始学嵌入式之STM32——9.STM32的时钟系统
stm32·单片机·嵌入式硬件
飞睿科技8 小时前
乐鑫智能开关方案解析:基于ESP32-C系列的低功耗、高集成设计
嵌入式硬件·物联网·esp32·智能家居·乐鑫科技