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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/13353.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

109,【1】攻防世界 web 题目名称-文件包含

进入靶场 直接显示源代码 提示我们通过get方式传递名为filename的参数&#xff0c;同时给出了文件名check.php filenamecheck.php 显示使用了正确的用法&#xff0c;错误的方法 filename./check.php 还是一样的回显 傻了&#xff0c;题目名称是文件包含&#xff0c;需要用到…

算法日记12:SC40树状数组(单点修改)

一、题目 二、题解&#xff1a; 2.1&#xff1a;题目的修改/查询交替进行&#xff0c;一眼就是树状数组的模板题目(当先修改最后查询可以使用前缀和/差分实现)&#xff0c; 2.2&#xff1a;树状数组结构&#xff1a;每一个节点都有其管辖区间 2.2.1:lowbit()函数 : l o w b i…

6 加密技术与认证技术

6 加密技术与认证技术 6.1:对称加密与非对称加密技术 6.1.1:对称加密 对称加密:; 特点: 1、加密强度不高&#xff0c;但效率高;2、密钥分发困难。 常见对称密钥&#xff08;共享秘钥&#xff09;加密算法:DES、3DES(三重DES)、RC-5、IDEA算法。 6.1.1.2非对称加密技术 非对称…

安卓开发,Reason: java.net.SocketTimeoutException: Connect timed out

错误提示&#xff1a; Could not install Gradle distribution from https://services.gradle.org/distributions/gradle-8.9-bin.zip. Reason: java.net.SocketTimeoutException: Connect timed out 解决办法&#xff1a; 1、打开gradle\wrapper\gradle-wrapper.properties …

【Linux】24.进程间通信(3)

文章目录 3.6 systemv共享内存3.6.1 共享内存函数3.6.3 一个简单的共享内存代码实现3.6.4 一个复杂的共享内存代码实现3.6.4 key和shmid的主要区别: 3.7 systemv消息队列&#xff08;了解&#xff09;3.8 systemv信号量&#xff08;了解&#xff09;进程互斥四个问题理解信号量…

2.Mkdocs配置说明(mkdocs.yml)【最新版】

官方文件&#xff1a;Changing the colors - Material for MkDocs 建议详细学习一下上面的官方网站↑↑↑ 我把我目前的配置文件mkdocs.yml代码写在下面&#x1f447;&#x1f3fb; #[Info] site_name: Mkdocs教程 #your site name 显示在左上角 site_url: http://wcowin.wo…

AI大模型:本地部署deepseek

一、安装lmstudio 1、下载网站&#xff1a; LM Studio - Discover, download, and run local LLMs 2、直接安装即可&#xff0c;记住安装的路径 二、下载deepseek模型 2.1、下载的流程 1、下载网站 https://huggingface.co/models 2、在搜索框输入&#xff1a;deepseek …

解析PHP文件路径相关常量

PHP文件路径相关常量包括以下几个常量&#xff1a; __FILE__&#xff1a;表示当前文件的绝对路径&#xff0c;包括文件名。 __DIR__&#xff1a;表示当前文件所在的目录的绝对路径&#xff0c;不包括文件名。 dirname(__FILE__)&#xff1a;等同于__DIR__&#xff0c;表示当前…

LLMs之data:synthetic-data-generator的简介、安装和使用方法、案例应用之详细攻略

LLMs之data&#xff1a;synthetic-data-generator的简介、安装和使用方法、案例应用之详细攻略 目录 synthetic-data-generator的简介 1、核心功能和优势 2、特点 synthetic-data-generator的安装和使用方法 1、安装 pip安装 安装依赖项 运行应用 2、使用方法 快速入…

Unity UI Default Shader分析

文章目录 UI默认材质和Default ShaderShader的属性定义Mask组件支持RectMask2D组件支持其他支持使用Unity UGUI时经常有自定义shader的需求,虽然我们可以直接按照shader lab的规范写出shader,使用也没问题,但如果能让自定义shader符合UI shader的规范,支持Mask,Rect2DMask…

【漫画机器学习】082.岭回归(或脊回归)中的α值(alpha in ridge regression)

岭回归&#xff08;Ridge Regression&#xff09;中的 α 值 岭回归&#xff08;Ridge Regression&#xff09;是一种 带有 L2​ 正则化 的线性回归方法&#xff0c;用于处理多重共线性&#xff08;Multicollinearity&#xff09;问题&#xff0c;提高模型的泛化能力。其中&am…

深入理解和使用定时线程池ScheduledThreadPoolExecutor

文章目录 前言认识定时线程池什么是定时线程池&#xff1f;定时线程池基本API使用定时线程池的应用场景1、定时任务调度2、缓存过期清理3、心跳检测4、延迟任务执行 定时线程池scheduleAtFixedRate与scheduleWithFixedDelay区别scheduleAtFixedRate案例demo&#xff08;period&…

【React】合成事件语法

React 合成事件是 React 为了处理浏览器之间的事件差异而提供的一种跨浏览器的事件系统。它封装了原生的 DOM 事件&#xff0c;提供了一致的事件处理机制。 合成事件与原生事件的区别&#xff1a; 合成事件是 React 自己实现的&#xff0c;封装了原生事件。合成事件依然可以通…

中小企业的采购流程,采购管理是如何进行的?

经营中小企业的&#xff0c;都明白高效采购管理的重要性。我见过不少中小企业&#xff0c;采购环节混乱无序&#xff0c;花费大量成本&#xff0c;却难以保障物资的优质供应。然而到底该如何梳理采购流程&#xff0c;怎样开展采购管理工作呢&#xff1f;这让众多中小企业主愁眉…

在线教程丨YOLO系列10年更新11个版本,最新模型在目标检测多项任务中达SOTA

YOLO (You Only Look Once) 是计算机视觉领域中最具影响力的实时目标检测算法之一&#xff0c;以其高精度与高效性深受业界青睐&#xff0c;广泛应用于自动驾驶、安防监控、医疗影像等领域。 该模型最早于 2015 年由华盛顿大学研究生 Joseph Redmon 发布&#xff0c;开创了将目…

IOPS与吞吐量、读写块大小及延迟之间的关系

IOPS&#xff08;每秒输入/输出操作次数&#xff09;、吞吐量、读写块大小及延迟是衡量存储系统性能的四个关键指标&#xff0c;它们之间存在密切的关系。以下从多个方面详细说明这些指标之间的关系&#xff1a; 1. IOPS与吞吐量的关系 公式关系&#xff1a;吞吐量&#xff0…

DeepSeek 部署过程中的问题

文章目录 DeepSeek 部署过程中的问题一、部署扩展&#xff1a;docker 部署 DS1.1 部署1.2 可视化 二、问题三、GPU 设置3.1 ollama GPU 的支持情况3.2 更新 GPU 驱动3.3 安装 cuda3.4 下载 cuDNN3.5 配置环境变量 四、测试 DeepSeek 部署过程中的问题 Windows 中 利用 ollama 来…

DeepSeek RAGFlow构建本地知识库系统

学习目标 DeepSeek RAGFlow 构建本地知识库系统 学习内容 下载安装Docker 1.1 Docker 是什么 1.2 下载Docker 1.3 安装Docker配置DockerRAGFlow 配置 3.1 下载RAGFlow 3.2 RAGFlow配置 3.3 启动RAGFlow Docker新建知识库 4.1 查看本机IP 4.2 OLLAMA_HOST 变量配置 4.3 添加模…

11 享元(Flyweight)模式

享元模式 1.1 分类 &#xff08;对象&#xff09;结构型 1.2 提出问题 做一个车管所系统&#xff0c;将会产生大量的车辆实体&#xff0c;如果每一个实例都保存自己的所有信息&#xff0c;将会需要大量内存&#xff0c;甚至导致程序崩溃。 1.3 解决方案 运用共享技术有效…

arcgis for js范围内天地图高亮,其余底图灰暗

在GIS地图开发中&#xff0c;有时我们需要突出显示某个特定区域&#xff0c;而将其他区域灰暗处理&#xff0c;以达到视觉上的对比效果。本文将介绍如何使用ArcGIS for JavaScript实现这一功能&#xff0c;具体效果为&#xff1a;在指定范围内&#xff0c;天地图高亮显示&#…