单片机位操作详解

发布者:温馨小屋最新更新时间:2025-02-25 来源: jianshu关键字:单片机  位操作  固件函数库 手机看文章 扫描二维码
随时随地手机看文章

1.把最低位置1 

 int byt=0x50;

写成:byt|=0x01; 或者 byt|=(0x01<<0);  //要把哪位置1  就左移几位

代码

#include

int main(void)

{

int byt=0x50; //

    byt|=(0x01<<0);//要把哪位置1  就左移几位

     //byt&=~(0x01<<0);//要把哪位清0  就左移几位取反 再进行与操作

    printf('%x',byt);

}

2.把某位清零或置1


#include

#define SET_BIT(x,bit)  (x|=(1<

#define RESET_BIT(x,bit)  (x&=(~(1<

int main(void)

{

  int bty=0x58;   //0101 1000

  SET_BIT(bty,0);  //把第一位置1

  printf('置一 %xn',bty);

  RESET_BIT(bty,0);//把第一位清0

  printf('清零 %xn',bty);

}



一个32位数据 字节读取操作

1.获取单字节

#include

#define GET_LOW_BYTE0(x)  ((x>>0)&0x000000FF) //取第0个字节

#define GET_LOW_BYTE1(x)  ((x>>8)&0x000000ff) //取第1个字节

#define GET_LOW_BYTE2(x)  ((x>>16)&0x000000ff)//取第2个字节

#define GET_LOW_BYTE3(x)  ((x>>24)&0x000000ff)//取第3个字节

int main(void)

{

unsigned long a =0x12345678;

printf('0x%x的第0个字节为: 0x%xn',a,GET_LOW_BYTE0(a));  //0x78

printf('0x%x的第1个字节为: 0x%xn',a,GET_LOW_BYTE1(a)); //0x56

printf('0x%x的第2个字节为: 0x%xn',a,GET_LOW_BYTE2(a)); //0x34

printf('0x%x的第3个字节为: 0x%xn',a,GET_LOW_BYTE3(a)); //0x12

}


2.获取第几位

#include

#define GET_BIT(x,bit) ((x&(1<>bit) /*获取第bit位*/

int main(void)

{

unsigned int byt=0x58;         /*二进制为0101 1000 */

printf('0x%x的第0位为: %dn',byt,GET_BIT(byt,0));

printf('0x%x的第3位为: %dn',byt,GET_BIT(byt,3));

printf('0x%x的第4位为: %dn',byt,GET_BIT(byt,4));

printf('0x%x的第5位为: %dn',byt,GET_BIT(byt,5));

printf('0x%x的第6位为: %dn',byt,GET_BIT(byt,6));

printf('0x%x的第7位为: %dn',byt,GET_BIT(byt,7));

}



一个32bit数据的位,字节清零操作

1.清零某个字节

#include

//32位数据清零某个字节

#define CLEAR_LOW_BYTE0(x) (x&=0xffffff00)

#define CLEAR_LOW_BYTE1(x) (x&=0xffff00ff)

#define CLEAR_LOW_BYTE2(x) (x&=0xff00ffff)

#define CLEAR_LOW_BYTE3(x) (x&=0x00ffffff)

int main(void)

{

unsigned long a=0x11223344;

unsigned long b=0x11223344;

unsigned long c=0x11223344;

unsigned long d=0x11223344;

printf('第0个字节清空%xn',CLEAR_LOW_BYTE0(a));

printf('清空第1个字节%xn',CLEAR_LOW_BYTE1(b));

printf('第2个字节清空%xn',CLEAR_LOW_BYTE2(c));

printf('清空第3个字节%xn',CLEAR_LOW_BYTE3(d));

}






STM32寄存器配置

STM32有几套固件函数库,这些固件库函数以函数的形式进行1层或者多层封装(软件开发中很重要的思想之一:分层思想),但是到了最里面的一层就是对寄存器的配置。

我们平时都比较喜欢固件库来开发,大概是因为固件库用起来比较简单,用固件库写出来的代码比较容易阅读。

最近一段时间一直在配置寄存器,越发地发现使用寄存器来进行一些外设的配置也是很容易懂的。

使用寄存器的方式编程无非就是往寄存器的某些位置1、清零以及对寄存器一些状态位进行判断、读取寄存器的内容等。

这些基本操作在上面的例子中已经有介绍,我们依旧以实例来巩固上面的知识点(以STM32F1xx为例):

(1)寄存器配置

看一下GPIO功能的端口输出数据寄存器  (GPIOx_ODR) (x=A..E)  :

假设我们要让PA10引脚输出高、输出低,可以这么做:

方法一:

GPIOA->ODR |=1<<10;/* PA10输出高(置1操作) */

GPIOA->ODR &= ~(1<<10);/* PA10输出低(清0操作) */

也可用我们上面的置位、清零的宏定义:

SET_BIT(GPIOA->ODR,10);/* PA10输出高(置1操作) */

CLEAR_BIT(GPIOA->ODR,10);/* PA10输出低(清0操作) */

方法二:

GPIOA->ODR |= (uint16_t)0x0400;/* PA10输出高(置1操作) */

GPIOA->ODR &= ~(uint16_t)0x0400;/* PA10输出低(清0操作) */

貌似第二种方法更麻烦?还得去细心地去构造一个数据。

但是,其实第二种方法其实是ST推荐我们用的方法,为什么这么说呢?因为ST官方已经把这些我们要用到的值给我们配好了,在stm32f10x.h中:

这个头文件中存放的就是外设寄存器的一些位配置。

所以我们的方法二等价于:

GPIOA->ODR |= GPIO_ODR_ODR10;/* PA10输出高(置1操作) */

GPIOA->ODR &= ~GPIO_ODR_ODR10;/* PA10输出低(清0操作) */

两种方法都是很好的方法,但方法一似乎更好理解。

配置连续几位的方法也是一样的,就不介绍了。简单介绍配置不连续位的方法,以TIM1的CR1寄存器为例:

设置CEN位为1、设置CMS[1:0]位为01、设置CKD[1:0]位为10:

TIM1->CR1 |= (0x1<<1)| (0x1<<5) |(0x2<<8);

这是组合的写法。当然,像上面一样拆开来写也是可以的。

(2)判断标志位

以状态寄存器(USART_SR) 为例:

判断RXNE是否被置位:

/* 数据寄存器非空,RXNE标志置位 */

if(USART1->SR & (1<<5))

{

/* 其它代码 */

USART1->SR &= ~(1<<5);/* 清零RXNE标志 */

}

或者:

/* 数据寄存器非空,RXNE标志置位 */

if(USART1->SR & USART_SR_RXNE)

{

/* 其它代码 */

USART1->SR &= ~USART_SR_RXNE;/* 清零RXNE标志 */

}

四、总结

以上就是本次关于位操作的一点总结笔记,有必要掌握。虽然说在用STM32的时候有库函数可以用,但是最接近芯片内部原理的还是寄存器。有可能之后有用到其它芯片没有像ST这样把寄存器相关配置封装得那么好,那就不得不直接操控寄存器了。

此外,使用库函数的方式代码占用空间大,用寄存器的话,代码占用空间小。之前有个需求,我能用的Flash的空间大小只有4KB,遇到类似这样的情况就不能那么随性的用库函数了。


i<<3 相当于把所有2进制左移3位  右边补零

左移n位相当于 乘以2的n次方 前提是数据不能丢失

i>>3 相当于把所有2进制右移3位 

右移n位 相当于除以2的n次方


关键字:单片机  位操作  固件函数库 引用地址:单片机位操作详解

上一篇:[课程-014位带操作——GPIO的输入和输出控制]
下一篇:SPI通信四大模式

推荐阅读最新更新时间:2026-03-25 12:05

STM8单片机工程师之路二-与或非操作
与或非操作的问题 PE_ODR &= 0XFE; //第0位清零,输出低电平 PD_ODR &= 0XF7; //第3位清零,输出低电平 我之前不知道为什么这样写! 现在来解释一下&=0XFE=1111 1110,也就是再用&=的时候,高7位待定, 第0位就是0这是一定的。 那么&0XF7=1111 0111 同理第3位一定是0。 &是什么作用呢? 让某一位清零,也就是最低位清零,而其他位保持不变; PE_ODR |= 0X01; //第0位置位,输出高电平 PD_ODR |= 0X08; //第3位置位,输出高电平 解释:|=0X01=0000 0001 这个是|=操作,所以高八位待定不变,第0位必定置1 同理:|= 0
[单片机]
51单片机位及操作指令
我们已经习惯了“位”一位就是一盏灯的亮和灭,而我们学的指令却全都是用“字节”来介绍的:字节的移动、加法、减法、逻辑运算、移位等等。用字节来处理一些数学问题,比如说:控制冰箱的温度、电视的音量等等很直观,可以直接用数值来表在。可是如果用它来控制一些开关的打开和合上,灯的亮和灭,就有些不直接了?我们知道送往P1口的数值后并不能马上知道哪个灯亮和来灭,而是要化成二进制才知道。工业中有很多场合需要处理这类开关输出,继电器吸合,用字节来处理就显示有些麻烦,所以在8051单片机中特意引入一个位处理机制。 位寻址区 在8051中,有一部份RAM和一部份SFR是具有位寻址功能的,也就是说这些RAM的每一个位都有自已的地址,可以直接用这个地址来
[单片机]
操作原理
什么是位带操作 某块存储区域(如SRAM)支持位带操作就被称为位带区,这个位带区中的地址除了可以像普通的 RAM 一样使用外,它们还都有自己的“位带别名区”,位带别名区把每个比特膨胀成一个 32 位的字。当你通过位带别名区访问这些字时,就可以达到访问原始比特的目的。 2.位带别名映射方法 以STM32的SRAM的位带区举例,说明位带别名的映射规则 对于 SRAM 位带区的某个比特,记它所在字节地址为 A,位序号为 n(0 =n =7),则该比特 在别名区的地址为: AliasAddr= 0x22000000+((A‐0x20000000)8+n)4 =0x22000000+ (A‐0x20000000)32 + n4 实例
[单片机]
[课程-014操作——GPIO的输入和输出控制]
一、概念性 什么是位带操作 位带操作就是可以单独对一个比特位读和写。在51单片机中,通过sbit关键字来实现位定义。 对于STM32位带区和位带别名区的理解 STM32里没有这样的关键字,但可以通过位带别名区来实现。 想要控制这些bit,就可以通过访问和控制位带别名区的一个32bit的字(因为stm32单片机以32bit为单位操作最为高效),来控制位带区内的任意一位。 一个位带区的位对应位带别名区的四个字节(32bit)。 SRAM存储代码的区域。 二 、位带区和位带别名区的地址转换 - 地址关系 (一) 外设位带区和位带别名区 AliasAddr = 0x4200 0000 + (Addr-0x4000
[单片机]
[课程-014<font color='red'>位</font>带<font color='red'>操作</font>——GPIO的输入和输出控制]
stm32操作有什么用
STM32位带操作是一种在ARM Cortex-M微控制器中使用的特殊技术,它允许同时处理多个位,并且可以提高代码效率和性能。在这篇文章中,我将详细介绍STM32位带操作的原理、用途以及如何使用它。 一、STM32位带操作的原理 位带别名区 在STM32微控制器中,每个外设寄存器都有32位,其中每个位都可以被独立访问。位带操作使用了ARM Cortex-M中的位带别名区(Bit Band Alias Region)技术,该区域位于内存映射地址空间的末尾部分,用于访问特定位的寄存器。位带别名区通过对特定位进行编址,使得每个位都拥有一个独立的内存地址。 位带操作的映射 位带操作利用了位带别名区的映射关系,将寄存器位的操作映射到了单
[单片机]
STM32F407入门开发: 操作
一、位带的文档介绍 STM32F407的位带操作可以实现类似51单片机中寄存器的操作方法,操作GPIO口代码简洁方便。 关于位段的操作在Cortex-M3M4权威指南里有详细描述: 支持位带操作后,可以使用普通的加载/存储指令来对单一的比特位进行读写。 在CM3位带区中,有两个区中实现了位带。 其中一个是 SRAM 区的最低 1MB 范围,第二个则是片内外设区的最低 1MB 范围。 这两个区中的地址除了可以像普通的 RAM 一样使用外,它们还都有自己的“位带别名区”,位带别名区把每个比特膨胀成一个 32 位的字。当你通过位带别名区访 问这些字时,就可以达到访问原始比特位的目的。 二、位带实现代码 Sys.c文件增加以下
[单片机]
汽车操作系统抢战:从暗斗走向明争
2023年,或许是全球智能汽车操作系统(OS)竞争从暗斗走向明争的一年。 从国外企业看,在2023年1月举行的CES上,黑莓(BlackBerry)宣布,与亚马逊云服务(AWS)联合打造的云连接汽车AI平台BlackBerry IVY已集成到头部一级汽车供应商博世和博泰的三款商用数字座舱平台中,基于此,汽车企业可快速部署新车载服务。也是在CES上,谷歌展示了新版Android Auto,几天后,谷歌与保时捷就汽车操作系统应用程序使用权谈判,达成和解。 从中国企业看,2022年最后一个月,华为内部会议要求其智能汽车解决方案BU(简称汽车BU)在2025年盈利;由吉利控股集团创始人兼董事长李书福和前吉利汽车研究院副院长沈子瑜共
[汽车电子]
汽车<font color='red'>操作</font>系统抢<font color='red'>位</font>战:从暗斗走向明争
STM32F103系列头文件(支持操作
【1】头文件介绍 和51的头文件类似,采用特殊方法封装,只要在工程中加入该头文件即可直接操控寄存器,支持位带操作。 【2】使用说明 详见头文件 【3】地址链接 点个关注吧,我会持续推出好东西的! 链接:https://pan.baidu.com/s/16WdrCZgjvgrPLzejeMFBkg 提取码:v35g 【4】注意 除了头文件还给出了自己的应用实例,推荐使用混合模板。即寄存器和标准库结合的编程方式。
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved