STM32微控制器类型转换

3

我有一个关于在STM32微控制器上进行C语言类型转换的问题。 现在我正在尝试编写自己的库来控制微控制器的外设。 但我不明白为什么和何时应该使用像(uint32_t)这样的类型转换。

例如,对于GPIO配置寄存器,我看到了下面的示例:

#define INPUT_ANALOG    ((uint32_t) 0x00)
#define INPUT_FLOATING  ((uint32_t) 0x01)
#define INPUT_PUP_PDOWN ((uint32_t) 0x02)

这些信息来自数据表格(如下所示的截图)。 我不理解为什么使用强制类型转换(uint32_t),而不是只使用0x00或0。
我能否使用下面的代码实现相同的目的?
typedef enum{
    INPUT_ANALOG = 0,
    IN_FLOATING,
    IN_PULL_UP_DOWN,
}PinConfInput_t;

我该为这段代码进行类型转换吗?

你能向我推荐一些关于类型转换的学习材料吗?

谢谢

enter image description here


在该系统上,sizeof(int)是多少? - 001
1
问题比较理论化,因为定义自己的枚举类型和 #define 没有任何意义。对于最简单的 STM32 微控制器,您将不得不定义成千上万个这样的东西。使用 STM 提供的 CMSIS 定义 - 它们涵盖了所有外设的所有位(我没有写关于 HAL 库的内容)。 - 0___________
2个回答

6

在许多情况下,需要将值为0x000x010x02的常量强制转换为unsigned int类型或加上后缀u/U。这些常量本身是int类型的,对于一些位操作,对int类型的值进行位移可能会出现问题,例如将它们左移到符号位置时可能发生的情况!

如果你将值为0x02(int)左移至第31:30位,则会发生这种情况!因此,

0x02 << 30

在32位宽度整数的机器上,该行为未定义,然而...
0x02U << 30 

或者
((uint32_t)0x02) << 30

不会。

在 C 语言中,枚举列表的标识符声明为 (C11 6.7.2.2p3)

常量是 int 类型,并且可以出现在任何允许使用 int 的地方。

也就是说,这些常量在进行位移操作时也需要进行类型转换。


请注意,在 C 语言中,枚举常量的类型不一定是枚举本身的类型:

#include <stdio.h>


enum foo {
    bar = 42
};


int main(void) {
    printf("An enumeration constant is an %s\n",
           _Generic(bar,
                    int: "int",
                    unsigned int: "unsigned int",
                    default: "something else"));


    printf("On this implementation the enum foo is %s\n",
           _Generic((enum foo) 0,
                    int: "int",
                    unsigned int: "unsigned int",
                    default: "something else"));
}

在GCC上,这将打印出枚举常量类型的,以及的类型的。也就是说,常量具有与实际枚举不同的类型。
此外,使用超出整数范围的枚举常量是一种约束违规;由于0x80000000在32位系统上不能表示为,因此无法在可移植性方面用作枚举常量。
% gcc enumtest.c -std=c11 -pedantic
enumtest.c:5:11: warning: ISO C restricts enumerator values to range of ‘int’
        [-Wpedantic]
    5 |     bar = 0x80000000
      |           ^~~~~~~~~~

最后,由于C标准规定枚举类型本身的类型由编译器决定,因此一些编译器可能会将短枚举类型使用无符号字符(unsigned char)。即使在这种情况下,您可能仍需要进行强制转换,因为在进行算术运算之前,unsigned char将被升级为signed int而不是unsigned int

最流行的ARM Cortex编译器(gcc,ARM和Keil)对枚举类型的处理方式与C标准要求略有不同。 - 0___________
@P__J__ 但这些不是枚举类型,它们是枚举常量 - Antti Haapala -- Слава Україні
这是一个STM32问题。特别是在硬件相关代码中使用枚举时,没有人关心可移植性。 - 0___________
@P__J__,你有没有读到我写的任何内容。你运行了 "请注意,在C中枚举常量的类型不需要是枚举本身的类型:" 下的代码吗?它说了什么? - Antti Haapala -- Слава Україні

1

GCCKEILIAR仅提供答案。

在ARM Cortex编程中使用3种最流行的编译器。 ARM / Keil,IAR和gcc被超过99%的ARM Cottex程序员使用。统计数据显示,大多数STM32程序员使用gcc(STM IDE使用gcc作为其编译器)。 gcc是一个非常好但不符合标准的C编译器,它有自己的C方言。

gcc

KEIL enter image description here

IAR: 您需要定义一个足够大的枚举类型,以不适合有符号类型。IAR使用任何整数类型(包括unsigned long long),以容纳所有枚举值。它会自动选择使用有符号或无符号类型(例如,最大的枚举值将是0x80 [它是一个无符号常量] - 类型将为unsigned char)。

因此,如果您使用这三个编译器中的任何一个编译代码,并且没有任何负值,则使用的类型将为unsigned intunsigned char,无需转换。


看我的答案。如果是无符号字符,你需要进行强制类型转换。 - Antti Haapala -- Слава Україні
@AnttiHaapala 这个问题不仅仅涉及到字符,还包括枚举类型。 - 0___________

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接