凡铁游戏提供最新游戏下载和手游攻略!

STM32中常用C语言知识点,开始复习!整型长整型的区别

发布时间:2024-07-16浏览:10

C语言是单片机开发必备的基础知识,本文列举了一些STM32学习中会遇到的C语言基础知识点,希望对大家有所帮助。

01

位操作

接下来我们先讲解几个位运算符,然后再讲解位运算的用法。C语言支持以下6种位运算:

六位运算

接下来我们来重点介绍一下单片机开发中位操作的一些实用技巧。

1.1 设置某些位,不改变其他位的值

这种场景在单片机开发中经常用到,方法是先用&操作符把需要设置的位清零,再用|操作符设置值。

例如,如果我想改变 GPIOA 的状态,我可以先清除寄存器的值:

然后与要设置的值执行或运算:

1.2 移位运算提高代码的可读性

移位操作在单片机开发中非常重要,下面是delay_init函数中的一行代码:

SysTick->CTRL |= 1 << 1;

这个操作就是把CTRL寄存器的第一位(从0开始)设置为1,为什么需要左移,而不是直接设置一个固定的值呢?

其实这是为了提高代码的可读性和复用性,很直观的就能知道这行代码就是把第一位设置为1,如果写成:

SysTick->CTRL |= 0X0002;

这样虽然能达到同样的效果,但是可读性较差,并且修改起来也比较困难。

1.3 ~ 使用按位反转的技巧

位反转在设置寄存器的时候经常用到,也经常用来清除某一个或者几个位,下面是delay_us函数的一行代码:

SysTick->CTRL &= ~(1 << 0) ; /* 关闭SYSTICK */

这段代码可以理解为仅将CTRL寄存器的第0位(最低位)设置为0,其他位的值保持不变。

类似地,我们不使用按位反转,代码如下:

SysTick->CTRL &= 0XFFFFFFFE; /* 关闭SYSTICK */

可以看出前者的可读性和可维护性要比后者好很多。

1.4 ^按位异或运算使用技巧

该函数非常适合控制位翻转,一个常见的应用场景是控制LED闪烁,如:

GPIOB->ODR ^= 1 << 5;

执行一次此代码将翻转 PB5 的输出状态。如果我们的 LED 连接到 PB5,我们可以看到 LED 闪烁。

02

定义宏定义

define 是 C 语言中的预处理命令,用于宏定义(定义常量),可以提高源代码的可读性,为编程提供方便。常用格式:

整型长度为4_整型长整型的区别_长整型

“Identifier”是定义的宏的名称。“String”可以是常量、表达式、格式字符串等。例如:

标识符HSE_VALUE的值定义为8000000,数字后面的U表示无符号。

至于关于define宏定义的其他一些知识,比如带参数的宏定义等,这里就不再讲解了。

03

ifdef 条件编译

在单片机程序开发过程中,我们经常会遇到这样的情况:当满足某个条件时,编译一组语句,当不满足该条件时,编译另一组语句。

最常见的条件编译命令形式是:

#ifdef 标识符 程序段1#else 程序段2#endif

其功能为:当该标识符已经定义(通常用#define命令定义)时,编译程序段1,否则编译程序段2。#else部分也可以省略,即:

#ifdef 程序段1 #endif

条件编译在HAL库中使用得比较多,在头文件stm32mp1xx_hal_conf.h中,经常会看到这样的语句:

#if !defined (HSE_VALUE) #define HSE_VALUE 24000000U #endif

如果HSE_VALUE宏没有定义,那么就定义HSE_VALUE宏,HSE_VALUE的值为24000000U。条件编译也是C语言的基础知识。

这里需要提一下,24000000U中的U代表无符号整数,一般UL代表无符号长整数,F代表浮点数。

这里加上U之后,系统在编译的时候就不会进行类型检查,直接把值以U的形式赋给某个对应的内存,如果超出了定义变量的范围,就会被截取。

04

外部变量声明

在C语言中,extern可以放在变量或函数之前,表示该变量或函数的定义在另一个文件中,提示编译器在遇到这个变量或函数时去其他模块中寻找它的定义。

请注意,您可以多次声明外部变量,但只能定义一次。在我们的代码中,您将看到如下语句:

extern uint16_t g_usart_rx_sta;

该语句声明 g_usart_rx_sta 变量已在其他文件中定义,并将在此处使用。

因此,你肯定可以在某处找到变量定义:

uint16_t g_usart_rx_sta;

extern的使用比较简单,但是经常用到,需要掌握。

05

typedef 类型别名

Typedef 用于为现有类型创建一个新名称,或类型别名,以简化变量的定义。HAL 库中 typedef 最常见的用途是为结构和枚举类型定义类型别名。

struct _GPIO { __IO uint32_t CRL; __IO uint32_t CRH;    };

定义了一个结构体GPIO,因此我们定义结构体变量如下:

struct _GPIO gpiox; /* 定义结构体变量gpiox */

但是这样很繁琐,HAL库中有很多这样的结构体变量需要定义。这里我们可以给结构体定义一个别名GPIO_TypeDef,这样我们在其他地方就可以通过别名GPIO_TypeDef来定义该结构体变量了,如下:

typedef struct { __IO uint32_t CRL; __IO uint32_t CRH; } GPIO_TypeDef;

Typedef为结构体定义了一个别名GPIO_TypeDef,因此我们可以通过GPIO_TypeDef定义结构体变量:GPIO_TypeDef gpiox;

这里的GPIO_TypeDef和struct _GPIO功能相同,但是GPIO_TypeDef使用起来方便得多。

热点资讯