【C语言笔记】操作位的技巧

操作位有两种方法,一种是位字段,另一种是使用按位运算符。位字段的方法可查看往期笔记:【C语言笔记】位域。本文介绍使用按位运算符操作位的方法。下表为几种位操作符及其含义:

不改变其他位的值的状况下,对某几个位进行设值。

嵌入式编程中,常常需要对一些寄存器进行配置,有的情况下需要改变一个字节中的某一位或者几位,但是又不想改变其它位原有的值,这时就可以使用按位运算符进行操作。下面进行举例说明,假如有一个8位的TEST寄存器:

当我们要设置第0位bit0的值为1时,可能会这样进行设置:

TEST = 0x01;

但是,这样设置是不够准确的,因为这时候已经同时操作到了高7位:bit1~bit7,如果这高7位没有用到的话,这么设置没有什么影响;但是,如果这7位正在被使用,结果就不是我们想要的了。

在这种情况下,我们就可以借用“&”和“|”进行配置。

对于二进制位操作来说,不管该位原来的值是0还是1,它跟0进行&运算,得到的结果都是0,而跟1进行&运算,将保持原来的值不变;不管该位原来的值是0还是1,它跟1进行|运算,得到的结果都是1,而跟0进行|运算,将保持原来的值不变。

所以,此时可以设置为:

TEST = TEST | 0x01;

其意义为:TEST寄存器的高7位均不变,最低位变成1了。在实际编程中,常改写为:

TEST |= 0x01;

这种写法可以一定程度上简化代码,是 C 语言常用的一种编程风格。

同样的,要给TEST的低4位清0,高4位保持不变,可以进行如下配置:

TEST &= 0xF0;

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

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

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

GPIOA->CRL |= 0X00000040; //设置相应位的值,不改变其他位的值
移位操作提高代码的可读性。

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

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

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

GPIOx->BSRR = 0x0030;

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

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

这样我们一目了然,5告诉我们是第5位也就是第6个端口,1告诉我们是设置为1了。

~取反操作使用技巧

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

TIMx->SR = 0xFFF7;

这样的作法设置第3位为0,但是这样的作法同样不好看,并且可读性很差。看看库函数代码中怎样使用的:

TIMx->SR = (uint16_t)~TIM_FLAG;

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

#define TIM_FLAG_Update  ((uint16_t)0x0001)
#define TIM_FLAG_CC1     ((uint16_t)0x0002)
#define TIM_FLAG_CC2     ((uint16_t)0x0004)
#define TIM_FLAG_CC3     ((uint16_t)0x0008)
#define TIM_FLAG_CC4     ((int16_t)0x0010)
#define TIM_FLAG_COM     ((uint16_t)0x0020)
#define TIM_FLAG_Trigger ((uint16_t)0x0040)
#define TIM_FLAG_Break   ((uint16_t)0x0080)
#define TIM_FLAG_CC1OF   ((uint16_t)0x0200)
#define TIM_FLAG_CC2OF   ((uint16_t)0x0400)
#define TIM_FLAG_CC3OF   ((uint16_t)0x0800)
#define TIM_FLAG_CC4OF   ((uint16_t)0x1000)

即设置SR第3位为0时可设置为:

TIMx->SR = (uint16_t)~TIM_FLAG_CC3;

以上就是关于位操作在嵌入式编程中的一些技巧,如有错误,欢迎指出!

参考资料:

《STM32F1开发指南-库函数版本_V3.1 》

《手把手教你学51单片机》

(0)

相关推荐

  • AVR446

    如:1rad/1s,1分钟转过的弧度为=1rad*60,则每分钟转数:(1rad*60分钟/2π)=9.55rpm 步距角为1.8°则:1.8/360=x/2*π-->步距角弧度为单位:0.03 ...

  • 长文花了两天时间整理了STM32中的一些C语言知识点

    https://m.toutiao.com/is/euo2NE7/ 前言 一位初学单片机的小伙伴让我推荐C语言书籍,因为C语言基础比较差,想把C语言重新学一遍,再去学单片机,我以前刚学单片机的时候也有 ...

  • stm32f10x基于freeRTOS的低功耗实现 | 一只菜鸟攻城狮啊

    0. 写在前面 没有太多时间更新,可能偶尔有时间就更新一些. 因为突然有项目用到了stm32f10x系列并且是电池驱动的,所以需要对功耗进行优化,其他CM3核心系列应该也同样适用. 1. 背景 Stm ...

  • C语言访问存储器的方法

    在单片机中我们经常需要访问某个指定的寄存器或者到指定的RAM地址,在本文为简单描述,下文所说的存储器可指:寄存器,RAM等. 01 宏定义: 定义一个宏,将地址值转化为C指针,然后取这个指针指向的内容 ...

  • STM32端口复用和重映射(AFIO辅助功能时钟) | MCU加油站

    端口复用功能 端口复用的定义 STM32有许多的内置外设(如串口.ADC.DCA等等),这些外设的外部引脚都是和GPIO复用的.也就是说,一个GPIO如果可以复用为内置外设的功能引脚,那么当这个GPI ...

  • STM32F1系列之常用外设说明

    STM32F1系列之常用外设说明

  • Go语言中切片操作的那些技巧

    Go语言中文网 今天 以下文章来源于李文周 ,作者李文周 李文周一个北漂程序员的自我更新之旅. 本文翻译自官方wiki,整理了Go语言中关于切片操作的一些技巧. 备注:由于行文需要,一些细节与原文存在 ...

  • “刘冰熔教授《ERAT操作理念及技巧解读》”学习笔记

    “刘冰熔教授《ERAT操作理念及技巧解读》”学习笔记

  • 9图看懂侧方位停车技巧

    光明网05-08 18:01显示图片 不会侧方停车?没关系老司机用9张图就能教会你!非常简单的技巧,收藏!新手司机都来学习学习,一篇靠谱实用的侧方停车步骤分解图析. 来源: 深圳交警 2021-05- ...

  • 早读 | Stoppa入路复位技术,操作细节与技巧看这篇课件!

    长期以来,髋臼骨折的手术显露.复位及内固定对骨科医师都是巨大挑战.Stoppa入路是骨盆髋臼主要的前方入路之一,适用于双侧髋臼骨折.前环骨折.耻骨联合分离等.临床中可以同时进行修补膀胱.尿道会师等手术 ...

  • 看图速学:髋臼骨折标准且极具代表的手术入路,操作细节与技巧全解!

    髋臼骨折的手术较为复杂,要求术者具备一定的手术经验.由于其位置深在.解剖结构复杂.骨折形态多变,长期以来其手术显露.复位及内固定对骨科医师都是巨大挑战.手术入路的选择应基于骨折类型.手术医生的经验以及 ...

  • 狭窄区域的侧方位停车技巧

    一. 短车位侧方停车 遇到路边停车位比较短的时候,新手司机就犯难了,往往反复几次都无法将车停进去,只好作罢,再另寻车位,这其实是有技巧的. 1. 先与停车位前方的车辆平行,车头和车尾与右车对齐,距离右 ...

  • 骨科清创术的15个操作要点及技巧!

    清创术是用外科手术的方法,清除开放伤口内的异物,切除坏死.失活或严重污染的组织.缝合伤口,使之尽量减少污染,甚至变成清洁伤口,达到一期愈合,有利受伤部位的功能和形态的恢复. 一般清创术步骤与方法 1. ...

  • Stoppa入路复位技术,操作细节与技巧看这篇课件!

    长期以来,髋臼骨折的手术显露.复位及内固定对骨科医师都是巨大挑战.Stoppa入路是骨盆髋臼主要的前方入路之一,适用于双侧髋臼骨折.前环骨折.耻骨联合分离等.临床中可以同时进行修补膀胱.尿道会师等手术 ...

  • 【转】语言|中国最后一位语言学全才孤独而有尊严的一生

    本文来源:<东方早报> 转自:群学书院 1984年的春天,84岁的王力开始编撰一部他心中"理想的字典".这也将是中国第一部比较完备的--<古汉语字典>.计划 ...