先放一张计算机上的:
KEIL C下的数据定义与windows和linux系统下的数据定义稍有不同
编程过程中,不同的 MCU 或编译器,其数据类型的意义各不相同,所以一定要注意相应变量数据类型的定义和转换,否则在程序 编译时候会出错。
▲ 在 KELI MDK 数据类型中进了如下定义
char 占用 1 个字节
short int 占用 2 字节//注意这里!
int 占用 4 字节
long 占用 4 字节 //注意这里!
long int 占用 4 字节 //注意这里!
float 占用 4 字节
double 占用 8 字节即有如下宏定义
typedef unsigned char uint8; // 无符号 8 位字符型变量
typedef signed char int8; // 有符号 8 位字符型变量
typedef unsigned short uint16; // 无符号 16 位短整型变量
typedef signed short int16; // 有符号 16 位短整型变量
typedef unsigned int uint32; // 无符号 32 位整型变量
typedef signed int int32; // 有符号 32 位整型变量
typedef float fp32; // 单精度浮点数(32 位长度)
typedef double fp64; // 双精度浮点数(64 位长度)
注:C 语言中的种类数据:整型:int short long 实型:float, double 。其中,Unsigned 为无符号, signed 有符号。
▲ STM32 的数据类型的宏定义
STM32 采用了大量的固件库,其中在 2.0 库中有 24 个数据类型如下
typedef unsigned char u8;/*无符号 8 位变量**/0~255 一字节
typedef signed char s8;/**有符号 8 位变量*/-128~127
typedef volatile unsigned char vu8;/* 易变的 8 位无符号变量**/
typedef volatile signed char vs8;/* 易变的 8 位有符号变量*/
typedef unsigned char const uc8; /* 只读的 8 位无符号变量 */
typedef signed char const sc8; /* 只读的 8 位有符号变量 */
typedef volatile unsigned char const vuc8; /* 易变只读的 8 位无符变量*/
typedef volatile signed char const vsc8; /* 易变只读 8 位有符号变量 */
typedef unsigned short u16; /*16 位短整型无符号变量**/0~65535 两字节
typedef signed short s16; /*16 位短整型有符号变量**/-32768~32767 两字节
typedef volatile unsigned short vu16;
typedef volatile signed short vs16;
typedef unsigned short const uc16; /* Read Only */
typedef signed short const sc16; /* Read Only */
typedef signed short const sc16; /* Read Only */
typedef volatile unsigned short const vuc16; /* Read Only */
typedef volatile signed short const vsc16; /* Read Only */
typedef unsigned long u32; /*32 位长整型无符号变量**/0~(2^32-1)四字节
typedef signed long s32; //*[(-2^32)/2]~ [(-2^32)/2-1]四字节
typedef volatile unsigned long vu32;
typedef volatile signed long vs32;
typedef unsigned long const uc32; /* Read Only */
typedef signed long const sc32; /* Read Only */
typedef volatile unsigned long const vuc32; /* Read Only */
typedef volatile signed long const vsc32; /* Read Only */
对部分数据类型后面作了注释,其它类型类推。对于float int 编译器中不能看到其定义(估计已编译了)。
▲ 不同类型数据的混合运算在C 语言中,不同类型的数据间是可以混合运算的。在进行运算时,不同类型的数据要先转换成同一类型,然后进行运算。转换的规则如下:
注意:箭头的方向只表示数据类型级别的高低,由低向高转换,这个转换过程是一步到位的。
▲ 数据类型转换规则
各类数据类型的转换,分为两种方式:隐式(编译软件自动完成),显式(程序强制转换)
★ 隐式转换规则:
字符必须先转换为整数(C 语言规定字符类型数据和整型数据之间可以通用) short 型转换为 int 型(同属于整型)
float 型数据在运算时一律转换为双精度(double)型,以提高运算精度(同属于实型) 赋值时,一律是右部值转换为左部类型
注:当整型数据和双精度数据进行运算时,C 先将整型数据转换成双精度型数据,再进行运算,结果为双精度类型数据
当字符型数据和实型数据进行运算时,C 先将字符型数据转换成实型数据,然后进行计算,结果为实型数据
★ 显式转换规则:例:(int)(x+y);
注:强制类型转换时,得到一个所需要的中间变量,原来变量的类型未发生变化
▲ 关于两个关键词说明 volatile const
(1)volatile :这个关键字,很多人只知道用,不知道其含义,有介绍解释是不易被编译器优化的。在 STM32 资料中解释加了易挥发的变量。这些解释都是含糊不清的。为此笔者专门查了下这个修饰关键字含义
通俗的解释: 随时会改变,并被多函数调用可以加 volatile 修饰。
简称易变变量或易挥发变量。 表示这个变量的真的很容易变。
进阶解释: 加了这个 volatile 意义就是在每次取这个变量值的时候,要求不是取它上次在某个
时候取的临时缓存变量(比如说暂存在某个寄存器中),而是直接到内存中取。
个人经验: 告诉编译器,volatile 定义的变量必须 RAM 变量.不能是寄存器变量. 尤其是中断中用 全局变量。
(2)const: 在定义变量时候,如果加上关键词 const,则变量的值在程序运行期间不能改变, 当然不能再赋值了。这种变量称为常变量(constant variable)或是只读变量(read-only-variable,这样觉得更恰当)。
▲ STM32F10x_StdPeriph_Driver 3.0 以后的版本中使用了 CMSIS 数据类型
3.0 以后版本与之前版本变量的定义有所不同,但是出于兼容旧版本的目的,以上的数据类型仍然兼容。CMSIS 的 IO 类型限定词如表 3 所示,CMSIS 和 STM32 固件库的数据类型对比如表 5 所示。这些数据类型可以在STM32F10x_StdPeriph_Lib_V3.4.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x
\stm32f10x.h 中找到具体的定义。
▲ 数据类型和IO类型限定词
Cortex-Mx HAL使用标准ANSI C头文件
▲ ST从库包中移除了文件”stm32f10x_type.h”,新的库使用CMSIS和
表5展示了STM32F10xxx和
表5 STM32F10xxx固件库V2.0.3与CMSIS数据类型对比
▲注意出于兼容旧版本的目的文件”stm32f10x.h”中仍然定义了STM32F10xxx固件库原有数据类型。
文件”stm32f10x.h”中也定义了STM32F10xxx固件库专用类型.
它们是:
typedef enum {
FALSE = 0, TRUE = !FALSE} bool;
typedef enum {
RESET = 0, SET = !RESET} FlagStatus, ITStatus;
typedef enum {
DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE))
typedef enum {
ERROR = 0, SUCCESS = !ERROR} ErrorStatus;