当前位置: 首页 > news >正文

C_位运算符及其在单片机寄存器的操作

C语言的位运算符用于直接操作二进制位,本篇简单结束各个位运算符的作业及其在操作寄存器的应用场景。

一、位运算符的简单说明

1、按位与运算符(&

  • 功能:按位与运算符对两个操作数的每一位执行与操作。如果两个对应的二进制位都是1,则结果为1,否则为0。(有0为0,全1为1)
  • 示例
    int a = 5;  // 0101
    int b = 3;  // 0011
    int result = a & b;  // 0001 -> 1
    

2、按位或运算符(|

  • 功能:按位或运算符对两个操作数的每一位执行或操作。如果两个对应的二进制位中至少有一个是1,则结果为1,否则为0。(有1为1,全0为0)
  • 示例
    int a = 5;  // 0101
    int b = 3;  // 0011
    int result = a | b;  // 0111 -> 7
    

3、按位异或运算符(^

  • 功能:按位异或运算符对两个操作数的每一位执行异或操作。如果两个对应的二进制位相同,则结果为0;如果不同,则结果为1。相同为1,不同为0)
  • 示例
    int a = 5;  // 0101
    int b = 3;  // 0011
    int result = a ^ b;  // 0110 -> 6
    
  • 补充: 按位异或运算符也可以用来交换2个变量的数值。交换2个变量1的数值我们常用的方法是定义一个临时变量来暂时存储一个变量的值,当如果不想多定义一个变量就可以采用按位异或运算符来操作,具体方法如下:

4、按位取反运算符(~

  • 功能:按位取反运算符对操作数的每一位执行取反操作,即将0变为1,将1变为0。(0变1,1变0)
  • 示例
    int a = 5;  // 0101
    int result = ~a;  // 1010 -> -6(在补码表示下)
    

5、左移运算符(<<

  • 功能:左移运算符将操作数的二进制位向左移动指定的位数。左移时,空出的低位用0填充。(整体左移,低位补0,高位不一定舍弃)
  • 说明:  整体左移后结果取决于赋值给什么类型的变量,从低到高截位,并不是简单的高位舍弃如果高位没有舍弃,数据左移一位就扩大一倍。如图:
  • 示例
    int a = 5;  // 0101
    int result = a << 1;  // 1010 -> 10
    

6、右移运算符(>>

  • 功能:右移运算符将操作数的二进制位向右移动指定的位数。对于无符号数,空出的高位用0填充;对于有符号数,空出的高位根据符号位填充(算术右移)。(整体右移,低位舍弃,有符号数高位补最高位的数字)
  • 说明:无符号数高位补0,有符号数高位补最高位的数字,数据右移一位就缩小一倍(除以2并舍去余数)。如图:
  • 示例
    int a = 5;  // 0101
    int result = a >> 1;  // 0010 -> 2
    

7. 复合赋值运算符

运算符也可以与赋值运算符组合,形成复合赋值运算符:

  • 按位与赋值&=
  • 按位或赋值|=
  • 按位异或赋值^=
  • 左移赋值<<=
  • 右移赋值>>=

二、位运算符的运用

1、用按位与运算符(&)将变量的某位置0

有一个变量char a = 0b1111 1111,要将其的第n位置0(最右一位为第0位),只需要将其按位与上一个第n位为0,其余为都为1的数据。

char a = 0b11111111
char b = 0b11110111
a &= b;

 这样a的第3位就会被置0;

2、用按位或运算符(|)将变量的某位置1

有一个变量char a = 0b0000 0000,要将其的第n位置1(最右一位为第0位),只需要将其按位或上一个第n位为1,其余为都为0的数据。

char a = 0b00000000
char b = 0b00001000
a |= b;

 这样a的第3位就会被置1; 

3、用左移运算符(<<)和按位或运算符(|)进行数据合成

        ①将两个8位数据合成一个16位数据

        将第一个数据左移8位后按位或上第二个数据

#include <stdio.h>int main() {unsigned char a = 0x34;  // 8位数据,十六进制:34unsigned char b = 0x12;  // 8位数据,十六进制:12unsigned short result = (a << 8) | b;  // 左移a并与b按位或,合成16位数据printf("合成的16位数据: 0x%0X\n", result);  // 输出:0x3412return 0;
}
        ②将两个16数据合成一个32位数据

        将第一个数据左移16位后按位或上第二个数据

#include <stdio.h>int main() {unsigned short x = 0x1234;  // 16位数据,十六进制:1234unsigned short y = 0xABCD;  // 16位数据,十六进制:ABCDunsigned int result = (x << 16) | y;  // 左移x并与y按位或,合成32位数据printf("合成的32位数据: 0x%0X\n", result);  // 输出:0x1234ABCDreturn 0;
}
        ③将一个8位数据和一个16位数据合成一个32位数据
#include <stdio.h>int main() {unsigned char a = 0x12;    // 8位数据,十六进制:12unsigned short b = 0xABCD; // 16位数据,十六进制:ABCDunsigned int result = (a << 16) | b;  // 左移a和b并合成32位数据printf("合成的32位数据: 0x%0X\n", result);  // 输出:0x12ABCDreturn 0;
}

4、截取一个数据的某部分字节

        ①截取一个数据的低字节

        截取低字节可以用赋值运算符或者强制转换。

        例如:截取0xABCD中的0xCD

#include <stdio.h>int main() {unsigned short a = 0xABCD;  // 16位数据,十六进制:ABCDunsigned char b = a;  // 将16位数据a赋值给8位数据bprintf("%0X\n", (unsigned char)a);  // 强制转换为8位,并输出低字节printf("%0X\n", b);  // 输出b的值return 0;
}
        ②截取一个数据的高字节或中间字节

        截取高字节或中间字节可以将数据右移后再用赋值运算符或者强制转换

#include <stdio.h>int main() {unsigned short a = 0xABCD;  // 16位数据,十六进制:ABCDunsigned int b = 0x1234ABCD; // 32位数据,十六进制:1234ABCD// 第一个 printf:将 a 右移8位,得到高字节,然后转换为 unsigned charprintf("%0X\n", (unsigned char)(a >> 8));// 第二个 printf:将 b 右移12位,得到高字节部分的前两位,然后转换为 unsigned charprintf("%0X\n", (unsigned char)(b >> 12));return 0;
}
        ③分别截取一个数据的低字节,中间字节和高字节合成一个新数据 
#include<stdio.h>int main(void)
{unsigned short a = 0xaabb;unsigned short b = 0xccdd;unsigned short c = 0xeeff;unsigned int d = (a & 0x00ff) | (b & 0x0ff0)<<4 | (c & 0xff00)<<8 ;printf("%x",d);
}

5、对寄存器进行操作

假设你有一个 u32 类型的变量 temp,表示一个 32 位的寄存器。

        ①对寄存器的某一位写0

         将temp变量的第n位置0,其他位不变

         规律:temp &=  ~(1 << n)

        ②对寄存器的某一位写1

        将temp变量的第n位置1,其他位不变

        规律:temp |= (1 << n)

        ③对寄存器的某连续两位操作

        1.将temp变量的第n和第n+1位置0,其他位不变

        规律:temp &= ~(3 << n)

        2. 将temp变量的第n和第n+1位置1,其他位不变

        规律:temp |= (3 << n)

        3.将temp变量的第n和第n+1位置01或10,其他位不变

        先将第n和第n+1位清0: temp &=  ~(1 << n)

        01:temp |= (1 << n)

        10:temp |= (2 << n)

        4.将temp的第2位第4位第5位置0,其他位保持不变

        temp &= ~ (1<<2|1<<4|1<<5);

        5.将temp的第n位进行翻转,其他位保持不变

        temp ^ = (1<<n);

三、位运算操作GPIO寄存器_LED

本篇示例所用的芯片型号为STM32F103,先创建好keil工程并配置好环境。

要操作LED灯的亮灭,我们要将对于GPIO端口设置为通用推挽输出模式。

这是一个已经创建好的keil工程,目前只有一个延时函数和基本的框架,接下来我们通过查找芯片手册配置寄存器来点亮LED灯。

通过原理图我们可以看出LED0接在PB5端口上,LED1接在PE5端口上。 因此要点亮LED0和LED1,我们就需要对PB5和PE5端口进行操作,端口输出低电平灯亮,输出高电平灯灭。

我们翻看芯片手册的目录,找到系统架构 。

 

 可以看到 GPIOB和GPIOE都是挂载在APB2总线上的,因此我们首先需要对APB2进行时钟使能。

 翻看目录,找到APB2 外设时钟使能寄存器(RCC_APB2ENR)。

要开启IO端口B和IO端口的时钟,我们需要将寄存器RCC_APB2ENR的位3和位6置1。

 具体操作如下:

接着翻看目录,找到端口配置寄存器。 

我们需要将PB5和PE5设置为通用推挽输出模式 ,PB5和PE5的配置方法是一样的,需要将寄存器GPIOx_CRL的位21和位20置01,位23和位22置00。

具体操作如下: 

最后找到端口输出数据寄存器(GPIOx_ODR) (x=A..E) 

将寄存器GPIOB_ODR/GPIOE_ODR的位5置1则端口PB5/PE5输出高电平,置0则输出低电平。 

 具体操作如下:

 烧录后效果如下:

LED

相关文章:

C_位运算符及其在单片机寄存器的操作

C语言的位运算符用于直接操作二进制位&#xff0c;本篇简单结束各个位运算符的作业及其在操作寄存器的应用场景。 一、位运算符的简单说明 1、按位与运算符&#xff08;&&#xff09; 功能&#xff1a;按位与运算符对两个操作数的每一位执行与操作。如果两个对应的二进制…...

【算法篇】贪心算法

目录 贪心算法 贪心算法实际应用 一&#xff0c;零钱找回问题 二&#xff0c;活动选择问题 三&#xff0c;分数背包问题 将数组和减半的最小操作次数 最大数 贪心算法 贪心算法&#xff0c;是一种在每一步选择中都采取当前状态下的最优策略&#xff0c;期望得到全局最优…...

Selenium 浏览器操作与使用技巧——详细解析(Java版)

目录 一、浏览器及窗口操作 二、键盘与鼠标操作 三、勾选复选框 四、多层框架/窗口定位 五、操作下拉框 六、上传文件操作 七、处理弹窗与 alert 八、处理动态元素 九、使用 Selenium 进行网站监控 前言 Selenium 是一款非常强大的 Web 自动化测试工具&#xff0c;能够…...

ioDraw桌面版 v3.4.0发布!AI文生图,AI图生图,手绘风格一键转换!

流程图功能升级 AI 文生图&#xff1a; 用户现在能输入文字描述&#xff0c;让软件自动生成对应的流程图画面&#xff0c;减少了手动绘图的工作量&#xff0c;提高创作效率&#xff0c;比如输入 “项目开发流程”&#xff0c;软件可能就会生成包含需求分析、设计、开发、测试…...

深入理解Node.js_架构与最佳实践

1. 引言 1.1 什么是Node.js Node.js简介:Node.js是一个基于Chrome V8引擎的JavaScript运行时,用于构建快速、可扩展的网络应用。Node.js的历史背景和发展:Node.js最初由Ryan Dahl在2009年发布,旨在解决I/O密集型应用的性能问题。随着时间的推移,Node.js社区不断壮大,提供…...

安装和卸载RabbitMQ

我的飞书:https://rvg7rs2jk1g.feishu.cn/docx/SUWXdDb0UoCV86xP6b3c7qtMn6b 使用Ubuntu环境进行安装 一、安装Erlang 在安装RabbitMQ之前,我们需要先安装Erlang,RabbitMQ需要Erlang的语言支持 #安装Erlang sudo apt-get install erlang 在安装的过程中,会弹出一段信息,此…...

第27节课:安全审计与防御—构建坚固的网络安全防线

目录 安全审计工具与流程安全审计工具NessusNmapBurp Suite 安全审计流程规划与准备信息收集漏洞扫描分析与评估报告与建议 安全防御策略网络层防御应用层防御数据层防御安全管理 结语 在当今数字化时代&#xff0c;网络安全已成为企业和个人不可忽视的重要议题。随着网络攻击手…...

【蓝桥杯】日志统计

日志统计&#xff08;编程题&#xff09;https://dashoj.com/d/lqbproblem/p/53https://dashoj.com/d/lqbproblem/p/53https://dashoj.com/d/lqbproblem/p/53 题目 日志统计(编程题) 讲解 这个讲解感觉比较通俗易懂。 蓝桥杯2018年省赛B组08&#xff08;c/c&#xff09;日…...

23.Word:小王-制作公司战略规划文档❗【5】

目录 NO1.2.3.4 NO5.6​ NO7.8.9​ NO10.11​ NO12​ NO13.14 NO1.2.3.4 布局→页面设置对话框→纸张&#xff1a;纸张大小&#xff1a;宽度/高度→页边距&#xff1a;上下左右→版式&#xff1a;页眉页脚→文档网格&#xff1a;勾选只指定行网格✔→ 每页&#xff1a;…...

基于单片机的智能安全插座(论文+源码)

1 系统整体方案设计 本课题基于单片机的智能安全插座设计&#xff0c;以STM32嵌入式单片机为主体&#xff0c;将计算机技术和检测技术有机结合&#xff0c;设计一款电量参数采集装置&#xff0c;实现电压、电流信号的数据采集任务&#xff0c;电压、电流和功率在上位机的显示任…...

2025年人工智能技术:Prompt与Agent的发展趋势与机遇

文章目录 一、Prompt与Agent的定义与区别(一)定义(二)区别二、2025年Prompt与Agent的应用场景(一)Prompt的应用场景(二)Agent的应用场景三、2025年Prompt与Agent的适合群体(一)Prompt适合的群体(二)Agent适合的群体四、2025年Prompt与Agent的发展机遇(一)Prompt的…...

vue2-v-if和v-for的优先级

vue2-v-if和v-for的优先级 1.v-if和v-for的作用 v-if是条件渲染&#xff0c;只有条件表达式true的情况下&#xff0c;才会渲染v-for是基于一个数组来渲染一个列表&#xff0c;在v-for的时候&#xff0c;保证给每个元素添加独一无二的key值&#xff0c;便于diff算法进行优化 …...

C++六大默认成员函数

C六大默认成员函数 默认构造函数默认析构函数RAII技术RAII的核心思想优点示例应用场景 默认拷贝构造深拷贝和浅拷贝 默认拷贝赋值运算符移动构造函数&#xff08;C11起&#xff09;默认移动赋值运算符&#xff08;C11起&#xff09;取地址及const取地址操作符重载取地址操作符重…...

基于springboot校园点歌系统

基于Spring Boot的校园点歌系统是一种专为校园场景设计的音乐点播平台&#xff0c;它能够丰富学生的校园生活&#xff0c;提升学生的娱乐体验。以下是对该系统的详细介绍&#xff1a; 一、系统背景与意义 在校园环境中&#xff0c;学生们对于音乐有着浓厚的兴趣&#xff0c;传…...

pycharm 中的 Mark Directory As 的作用是什么?

文章目录 Mark Directory As 的作用PYTHONPATH 是什么PYTHONPATH 作用注意事项 Mark Directory As 的作用 可以查看官网&#xff1a;https://www.jetbrains.com/help/pycharm/project-structure-dialog.html#-9p9rve_3 我们这里以 Mark Directory As Sources 为例进行介绍。 这…...

【Elasticsearch】文本分类聚合Categorize Text Aggregation

响应参数讲解: key &#xff08;字符串&#xff09;由 categorization_analyzer 提取的标记组成&#xff0c;这些标记是类别中所有输入字段值的共同部分。 doc_count &#xff08;整数&#xff09;与类别匹配的文档数量。 max_matching_length &#xff08;整数&#xff09;从…...

算法随笔_40: 爬楼梯

上一篇:算法随笔_39: 最多能完成排序的块_方法2-CSDN博客 题目描述如下: 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&am…...

【Linux探索学习】第二十七弹——信号(一):Linux 信号基础详解

Linux学习笔记&#xff1a; https://blog.csdn.net/2301_80220607/category_12805278.html?spm1001.2014.3001.5482 前言&#xff1a; 前面我们已经将进程通信部分讲完了&#xff0c;现在我们来讲一个进程部分也非常重要的知识点——信号&#xff0c;信号也是进程间通信的一…...

【数学】矩阵、向量(内含矩阵乘法C++)

目录 一、前置知识&#xff1a;向量&#xff08;一列或一行的矩阵&#xff09;、矩阵1. 行向量2. 列向量3. 向量其余基本概念4. 矩阵基本概念5. 关于它们的细节 二、运算1. 转置&#xff08;1&#xff09;定义&#xff08;2&#xff09;性质 2. 矩阵&#xff08;向量&#xff0…...

设置git区分大小写

设置git区分大小写 1.全局设置 (影响全部仓库): git config --global core.ignorecase false2.仓库级别设置 (影响当前仓库): git config core.ignorecase false3.已经提交了大小写不一致的文件处理: git mv -f OldName newName # 强制重命名 git commit -m "Fix cas…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

376. Wiggle Subsequence

376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

JS设计模式(4):观察者模式

JS设计模式(4):观察者模式 一、引入 在开发中&#xff0c;我们经常会遇到这样的场景&#xff1a;一个对象的状态变化需要自动通知其他对象&#xff0c;比如&#xff1a; 电商平台中&#xff0c;商品库存变化时需要通知所有订阅该商品的用户&#xff1b;新闻网站中&#xff0…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

Linux 中如何提取压缩文件 ?

Linux 是一种流行的开源操作系统&#xff0c;它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间&#xff0c;使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的&#xff0c;要在 …...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...