32MDK 下 C 语言基础_08

1.位操作技巧

1.1不改变其他位的值的状况下,对某几个位进行设值。 这个场景单片机开发中经常使用,方法就是先对需要设置的位用&操作符进行清零操作, 然后用|操作符设值。比如我要改变 GPIOA 的状态,可以先对寄存器的值进行&清零操作

GPIOA->CRL&=0XFFFFFF0F; //将第 4-7 位清 0

然后再与需要设置的值进行|或运算

GPIOA->CRL|=0X00000040; //设置相应位的值,不改变其他位的值

1.2移位操作提高代码的可读性。 移位操作在单片机开发中也非常重要,下面让我们看看固件库的 GPIO 初始化的函数里 面的一行代码

GPIOx->BSRR = (((uint32_t)0x01) << pinpos);

将 BSRR 寄存器的第 pinpos 位设置为 1,为什么要通过左移而不是直接设置一个固定的值呢?其实,这是为了提高代码的可读性以及可重用性。这行代码可以很直观明了的知道,是将第 pinpos 位设置为 1。如果你写成

GPIOx -> BSRR =0x0030;

这样的代码不好看也不好重用,类似这样的代码很多:

GPIOA->ODR|=1<<5  //PA.5 输出高,不改变其他位

告诉我们是第 5 位也就是第 6 个端口,1 告诉我们值设置为 1 。

1.3.~取反操作使用技巧

SR 寄存器的每一位都代表一个状态,某个时刻我们希望去设置某一位的值为 0,同时其他位都保留为 1,简单的作法是直接给寄存器设置一个值:

TIMx->SR=0xFFFE;

这样的作法设置第 0位为 0,但是这样的作法同样不好看,并且可读性很差。

看看库函数代码中怎样使用的:

TIMx->SR = (uint16_t)~TIM_FLAG;

//而 TIM_FLAG 是通过宏定义定义的值:

#define TIM_FLAG_Update ((uint16_t)0x0001)

#define TIM_FLAG_CC1 ((uint16_t)0x0002)

看这个应该很容易明白,可以直接从宏定义中看出 TIM_FLAG_Update 就是设置的第 0 位了, 可读性非常强。

2.define宏定义

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

#define 标识符 字符串

“标识符”为所定义的宏名。“字符串”可以是常数、表达式、格式串等,例如:

#define SYSCLK_FREQ_72MHz 72000000

定义标识符 SYSCLK_FREQ_72MHz 的值为 72000000。

3.ifdef 条件编译

单片机程序开发过程中,经常会遇到一种情况,当满足某条件时对一组语句进行编译,而 当条件不满足时则编译另一组语句。条件编译命令最常见的形式为:

#ifdef 标识符

程序段 1

#else

程序段 2

#endif

当标识符已经被定义过(一般是用#define 命令定义),则对程序段 1 进行编译, 否则编译程序段 2。 其中#else 部分也可以没有

#ifdef

程序段 1

#endif

4.extern 变量申明

C 语言中 extern 可以置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。

注意:对于 extern 申明变量可以多次,但定义只有一次。

extern u16 USART_RX_STA;

申明 USART_RX_STA 变量在其他文件中已经定义,在这里要使用到。所以,肯定可以找到在某个地方有变量定义的语句:

u16 USART_RX_STA;

5.typedef 类型别名

typedef 用于为现有类型创建一个新的名字,或称为类型别名,用来简化变量的定义。 typedef 在 MDK 用得最多的是定义结构体的类型别名和枚举类型。

6.结构体

结构体就是将多个相关的变量组合为一个有机的整体。在单片机程序开发过程中,经常会遇到要初始化一个外设比如串口,它的初始化状态是由几个属性来决定的,比如串口号,波特率,极性,以及模式等,可以将相关的属性封装成一个结构体,与属性相关的功能行为封装成函数。

例如:

typedef struct
{
uint32_t USART_BaudRate; 
 uint16_t USART_WordLength; 
uint16_t USART_StopBits; 
 uint16_t USART_Parity; 
uint16_t USART_Mode; 
uint16_t USART_HardwareFlowControl; 
} USART_InitTypeDef;

声明结构体类型:

Struct 结构体名

{ 成员列表; }

变量名列表;

结构体成员变量的引用方法是: 结构体变量名字.成员名

比如要引用 usart1 的成员BaudRate,方法是:

usart1.BaudRate;

结构体指针变量定义也是一样的,跟其他变量没有啥区别。

例如:struct U_TYPE *usart3;//定义结构体指针变量 usart1;

结构体指针成员变量引用方法是通过“->”符号实现,比如要访问 usart3 结构体指针指向的结构体的成员变量 BaudRate,方法是:

Usart3->BaudRate

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值