《嵌入式Linux与物联网软件开发——C语言内核深度解析》一2.3 位操作与寄存器

简介:

本节书摘来自异步社区《嵌入式Linux与物联网软件开发——C语言内核深度解析》一书中的第2章,第2.3节,作者朱有鹏 , 张先凤,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.3 位操作与寄存器

2.3.1 寄存器的操作

一般来说,一个SOC片内外设由若干个寄存器控制,IO操作的寄存器与内存统一编址,如果我们要操作片内外设,那么就是操作片内外设的控制寄存器。因此,控制硬件就是读写寄存器(寄存器亦可理解为特定地址的内存)。

SOC中一个寄存器的数据宽度一般是32bit,每个bit可以配置为0或者1,单个bit或相邻几个bit一起控制片上外设某个属性的状态。单个bit最多控制两种状态,三个bit最多控制8种状态。因此寄存器的特定bit配置为0或1,就可以实现对硬件的控制。

然而,CPU对寄存器读写一般都是按照寄存器的数据宽度一起读写(部分寄存器可以按照位读取,这里不讨论),即32bit读出,32bit写入。假设我们只想修改寄存器其中某个属性的状态,即修改寄存器特定位。那么就只能先整体读出来,然后将需要修改的部分修改后,再将修改后的值整体写入寄存器中,即读-改-写三部曲。并且我们只能修改需要修改的位,不能影响其他位。对寄存器特定位的操作分三种情况:清零、置1和取反。

2.3.2 寄存器特定位清零用&

如果希望将一个寄存器的某些特定位变成0而不影响其他位,可以构造一个合适的1和0组成的数,和这个寄存器原来的值进行位与操作,就可以将特定位清零。假设原来32位寄存器REG1中的值为0xAAAAAAAA,我们希望将bit8~bit15清零而其他位不变,将这个数与0xFFFF00FF进行位与即可。

REG1 &= 0xFFFF00FF;

经过上式的读-改-写后,REG1中的值为0xAAAA00AA,达到了特定位清零的目的。

2.3.3 寄存器特定位置1用|

如果希望将一个寄存器的某些特定位变成1而不影响其他位,可以构造一个合适的1和0组成的数,和这个寄存器原来的值进行位或操作,就可以将特定位置1。假设原来32位寄存器REG1中的值为0xAAAA00AA,我们希望将bit8~bit15置1而其他位不变,将这个数与0X0000FF00进行位或即可。

REG1 |= 0x0000FF00;

经过上式的读-改-写后,REG1中的值为0xAAAAFFAA,达到了特定位置1的目的。

2.3.4 寄存器特定位取反用~

如果希望将一个寄存器的某些特定位0变成1,而1变成0,即取反而不影响其他位,可以构造一个合适的1和0组成的数,和这个寄存器原来的值进行位异或操作,就可以将特定位取反。假设原来32位寄存器REG1中的值为0xAAAAAAAA,我们希望将bit8~bit15取反而其他位不变,将这个数与0X0000FF00进行位异或即可。

REG1 ^= 0x0000FF00;

经过上式的读-改-写后,REG1中的值为0xAAAA55AA,达到了特定位取反的目的。

学完本节,你会发现配置寄存器操作并没有想象的那么难,只要我们学会设置位操作的特定的构造数就行了。上面举的例子是bit8~bit15,很好算。但如果要构造一个bit1、bit3~bit5、bit15~bit17位为1的数。傻眼了?一步步来,先用二进制挨个排列好0011 1000 0000 0011 1010,再换算成十六进制0X0003803A,总算算出来了。是不是非要这么麻烦呢?我们既然已经学习了位运算,能不能用位运算构建一个构造数呢?

相关实践学习
钉钉群中如何接收IoT温控器数据告警通知
本实验主要介绍如何将温控器设备以MQTT协议接入IoT物联网平台,通过云产品流转到函数计算FC,调用钉钉群机器人API,实时推送温湿度消息到钉钉群。
阿里云AIoT物联网开发实战
本课程将由物联网专家带你熟悉阿里云AIoT物联网领域全套云产品,7天轻松搭建基于Arduino的端到端物联网场景应用。 开始学习前,请先开通下方两个云产品,让学习更流畅: IoT物联网平台:https://iot.console.aliyun.com/ LinkWAN物联网络管理平台:https://linkwan.console.aliyun.com/service-open
相关文章
|
5月前
|
存储 C语言 C++
【c语言】运算符汇总(万字解析)
今天博主跟大家分享了c语言中各种操作符的功能、使用方法以及优先级和结合性,并且与大家深入探讨了表达式求值的两个重要规则--算数转换和整形提升。学习这些知识对我们的C语言和C++学习都有着极大的帮助。
266 2
|
5月前
|
缓存 并行计算 Linux
深入解析Linux操作系统的内核优化策略
本文旨在探讨Linux操作系统内核的优化策略,包括内核参数调整、内存管理、CPU调度以及文件系统性能提升等方面。通过对这些关键领域的分析,我们可以理解如何有效地提高Linux系统的性能和稳定性,从而为用户提供更加流畅和高效的计算体验。
177 24
|
4月前
|
存储 网络协议 编译器
【C语言】深入解析C语言结构体:定义、声明与高级应用实践
通过根据需求合理选择结构体定义和声明的放置位置,并灵活结合动态内存分配、内存优化和数据结构设计,可以显著提高代码的可维护性和运行效率。在实际开发中,建议遵循以下原则: - **模块化设计**:尽可能封装实现细节,减少模块间的耦合。 - **内存管理**:明确动态分配与释放的责任,防止资源泄漏。 - **优化顺序**:合理排列结构体成员以减少内存占用。
312 14
|
4月前
|
存储 Linux API
深入探索Android系统架构:从内核到应用层的全面解析
本文旨在为读者提供一份详尽的Android系统架构分析,从底层的Linux内核到顶层的应用程序框架。我们将探讨Android系统的模块化设计、各层之间的交互机制以及它们如何共同协作以支持丰富多样的应用生态。通过本篇文章,开发者和爱好者可以更深入理解Android平台的工作原理,从而优化开发流程和提升应用性能。
|
4月前
|
存储 编译器 C语言
【C语言】数据类型全解析:编程效率提升的秘诀
在C语言中,合理选择和使用数据类型是编程的关键。通过深入理解基本数据类型和派生数据类型,掌握类型限定符和扩展技巧,可以编写出高效、稳定、可维护的代码。无论是在普通应用还是嵌入式系统中,数据类型的合理使用都能显著提升程序的性能和可靠性。
155 8
|
4月前
|
存储 算法 C语言
【C语言】深入浅出:C语言链表的全面解析
链表是一种重要的基础数据结构,适用于频繁的插入和删除操作。通过本篇详细讲解了单链表、双向链表和循环链表的概念和实现,以及各类常用操作的示例代码。掌握链表的使用对于理解更复杂的数据结构和算法具有重要意义。
1761 6
|
4月前
|
存储 网络协议 算法
【C语言】进制转换无难事:二进制、十进制、八进制与十六进制的全解析与实例
进制转换是计算机编程中常见的操作。在C语言中,了解如何在不同进制之间转换数据对于处理和显示数据非常重要。本文将详细介绍如何在二进制、十进制、八进制和十六进制之间进行转换。
235 5
|
4月前
|
C语言 开发者
【C语言】断言函数 -《深入解析C语言调试利器 !》
断言(assert)是一种调试工具,用于在程序运行时检查某些条件是否成立。如果条件不成立,断言会触发错误,并通常会终止程序的执行。断言有助于在开发和测试阶段捕捉逻辑错误。
91 5
|
4月前
|
安全 搜索推荐 Unix
【C语言】《回调函数》详细解析
回调函数是指一个通过函数指针调用的函数。它允许将一个函数作为参数传递给另一个函数,并在特定事件发生时执行。这种技术使得编程更加灵活,可以动态决定在何时调用哪个函数。
144 1
|
5月前
|
存储 人工智能 安全
操作系统的心脏——内核深度解析
【10月更文挑战第29天】 本文深入探讨了操作系统的核心组件——内核,包括其定义、功能、架构以及在现代计算中的重要性。通过对比不同操作系统内核的设计哲学和技术实现,揭示了内核如何影响系统性能、稳定性和安全性。此外,文章还讨论了未来内核技术的潜在发展方向,为读者提供了一个全面了解内核工作原理的平台。

相关产品

  • 物联网平台