《嵌入式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天前
|
存储 安全 Linux
探索Linux操作系统的心脏:内核
在这篇文章中,我们将深入探讨Linux操作系统的核心—内核。通过简单易懂的语言和比喻,我们会发现内核是如何像心脏一样为系统提供动力,处理数据,并保持一切顺畅运行。从文件系统的管理到进程调度,再到设备驱动,我们将一探究竟,看看内核是怎样支撑起整个操作系统的大厦。无论你是计算机新手还是资深用户,这篇文章都将带你领略Linux内核的魅力,让你对这台复杂机器的内部运作有一个清晰的认识。
18 3
|
14天前
|
缓存 安全 Unix
Linux 内核黑客不可靠指南【ChatGPT】
Linux 内核黑客不可靠指南【ChatGPT】
|
14天前
|
Linux 开发者
Linux内核贡献成熟度模型 【ChatGPT】
Linux内核贡献成熟度模型 【ChatGPT】
|
13天前
|
Shell Linux API
C语言在linux环境下执行终端命令
本文介绍了在Linux环境下使用C语言执行终端命令的方法。首先,文章描述了`system()`函数,其可以直接执行shell命令并返回结果。接着介绍了更强大的`popen()`函数,它允许程序与命令行命令交互,并详细说明了如何使用此函数及其配套的`pclose()`函数。此外,还讲解了`fork()`和`exec`系列函数,前者创建新进程,后者替换当前进程执行文件。最后,对比了`system()`与`exec`系列函数的区别,并针对不同场景推荐了合适的函数选择。
|
14天前
|
网络协议 Ubuntu Linux
用Qemu模拟vexpress-a9 (三)--- 实现用u-boot引导Linux内核
用Qemu模拟vexpress-a9 (三)--- 实现用u-boot引导Linux内核
|
14天前
|
Linux
用clang编译Linux内核
用clang编译Linux内核
|
14天前
|
Linux API C语言
Linux 内核补丁提交的清单 【ChatGPT】
Linux 内核补丁提交的清单 【ChatGPT】
|
14天前
|
安全 Linux 开发者
Linux内核管理风格 【ChatGPT】
Linux内核管理风格 【ChatGPT】
|
15天前
|
Linux 程序员 编译器
Linux内核驱动程序接口 【ChatGPT】
Linux内核驱动程序接口 【ChatGPT】
|
15天前
|
存储 Linux 开发工具
如何进行Linux内核开发【ChatGPT】
如何进行Linux内核开发【ChatGPT】

相关产品

  • 物联网平台