PCout(n) -- STM32F103RCT6 位带操作

news2024/12/24 8:11:32

1. 使用位带操作控制GPIO口的输入、输出模式,以及输出的电平高、低

注:位带操作一般是操作单独的一个bit 位,而&=,|= 则可操作多个bit位,看自己的需求吧。(不懂&=,|= 是什么意思的自行问度娘)

#define PERIPH_BASE           ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)
#define GPIOC_BASE            (APB2PERIPH_BASE + 0x1000)

#define BITBAND(addr, bitnum) ((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF) << 5) + (bitnum << 2))  // 计算地址
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr))  // 对地址里面的值进行赋值
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum))  // 传如要操作的实际地址及其bit位

#define LED0  PCout(3)

LED0  = 1;// GPIOC_3 为输出模式,且输出高电平(输出寄存器ODR 置1)

LED0  = 0;// GPIOC_3 为输出模式,且输出低电平(输出寄存器ODR 置0)

LED0  = !LED0  ;// LED0 状态翻转(亮的话就熄灭,熄灭的话就点亮)

2. 宏定义

sys.h:位带操作, 参考《Cortex-M3/M4 权威指南》 第五章(87页~92页)

// IO口操作宏定义, 参考<<CM3权威指南>>第五章(87页~92页)
#define BITBAND(addr, bitnum) ((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF) << 5) + (bitnum << 2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum))

#define GPIOC_ODR_Addr    (GPIOC_BASE + 12) // 0x4001 100C

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)

stm32f10x.h:GPIOC 的地址

#define PERIPH_BASE           ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)
#define GPIOC_BASE            (APB2PERIPH_BASE + 0x1000)

3. 位带操作的宏定义解释

3.1 计算位段区地址对应的别名区地址,总之,就是计算要操作的寄存的地址,计算出来了寄存器的地址,就可以直接操作寄存器了

#define    BITBAND(addr, bitnum)          ((addr & 0xF000 0000)+0x200 0000+((addr &0xF FFFF)<<5)+(bitnum<<2))

这一句定义了位带存储地址的计算方法
addr & 0xF000 0000: 取地址的最高4位,用来区分段的,是片内外设段还是SRAM段。
+0x200 0000:(值为32M)是别名区相对位段区的地址偏移量,别名区在相应位段上方的32M处(别名区 = 位段区 + 0x200 0000)
(addr & 0xF FFFF) << 5): 别名区的地址值等于位段区的地址膨胀32倍,左移5位即可;
(bitnum<<2): 由于每1比特膨胀为32位,32位占用4个字节的存储位置,所以计算地址时要乘以4,左移2位即是;

3.2 取地址里面的值(操作寄存器里面的值)

#define   MEM_ADDR(addr)            *((volatile unsigned long  *)(addr))

在 3.1 中计算出来寄存器的地址后,就可以对地址里面的值进行修改了,至于中间加一个volatile关键字,则是为了告诉编译器不要对该值进行优化,必须每次老老实实地去直接访问这个地址!!

3.3 操作的具体地址及其bit位

#define BIT_ADDR(addr, bitnum)       MEM_ADDR(BITBAND(addr, bitnum))

addr:要操作的寄存器的实际地址,例:GPIOC_ODR_Addr(GPIOC_x的数据寄存器)
bitnum:要操作的寄存器的实际地址的某个bit位,例:GPIOC_3(GPIOC_3的数据寄存器)

4. 例:点亮或者熄灭LED灯

在这里插入图片描述
当GPIOC_3 输出高电平的时候,LED23 点亮
当GPIOC_3 输出低电平的时候,LED23 熄灭

#define LED0  PCout(3)

LED0  = 1;   // GPIOC_3 为输出模式,且输出高电平(输出寄存器ODR 置1)

LED0  = 0;    // GPIOC_3 为输出模式,且输出低电平(输出寄存器ODR 置0)

LED0  = !LED0;    // LED0 状态翻转(亮的话就熄灭,熄灭的话就点亮)

5. 例如,在《Cortex-M3 权威指南》第88页有张图,显示的是实际地址的每个bit位对应的别名地址

在这里插入图片描述

5.1 看图可知:

0x200F FFFF 的地址有8个bit位,每个bit位映射了一个新的地址,操作新地址就相当于在操作实际地址的每个bit位,对应关系:
0x200F FFFF bit[0] --> 0x23FF FFE0
0x200F FFFF bit[1] --> 0x23FF FFE4
0x200F FFFF bit[2] --> 0x23FF FFE8
0x200F FFFF bit[3] --> 0x23FF FFEC
0x200F FFFF bit[4] --> 0x23FF FFF0
0x200F FFFF bit[5] --> 0x23FF FFF4
0x200F FFFF bit[6] --> 0x23FF FFF8
0x200F FFFF bit[7] --> 0x23FF FFFC

5.2 根据实际地址的bit位来计算映射地址

#define BITBAND(addr, bitnum)   ((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF) << 5) + (bitnum << 2)) 
#define MEM_ADDR(addr)    *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)     MEM_ADDR(BITBAND(addr, bitnum))

其中:addr = 0x200F FFFF, bitnum = 0, 1, 2, 3, 4, 5, 6, 7

(addr & 0xF0000000):    0x200F FFFF & 0xF0000000 = 0x2000 0000
+ 0x2000000
(addr & 0xF FFFF) << 5:    (0x200F FFFF & 0xFFFFF) << 5 =  0xF FFFF << 5 = 0x1FF FFE0
+ (bitnum << 2)

0 << 2 = 00;     bit[0]
1 << 2 = 04;     bit[1]
2 << 2 = 08;     bit[2]
3 << 2 = 0C;     bit[3]
4 << 2 = 10;     bit[4]
5 << 2 = 14;     bit[5]
6 << 2 = 18;     bit[6]
7 << 2 = 1C;     bit[7]

所以

((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF) << 5) = 0x2000 0000 + 0x200 0000  + 0x1FF FFE0

((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF) << 5)  + (0 << 2))  = 0x2000 0000 + 0x200 0000  + 0x1FF FFE0 + 0x00  = 0x23FF FFE0
((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF) << 5)  + (1 << 2))  = 0x2000 0000 + 0x200 0000  + 0x1FF FFE0 + 0x04  = 0x23FF FFE4
((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF) << 5)  + (2 << 2))  = 0x2000 0000 + 0x200 0000  + 0x1FF FFE0 + 0x08  = 0x23FF FFE8
((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF) << 5)  + (3 << 2))  = 0x2000 0000 + 0x200 0000  + 0x1FF FFE0 + 0x0C  = 0x23FF FFEC
((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF) << 5)  + (4 << 2))  = 0x2000 0000 + 0x200 0000  + 0x1FF FFE0 + 0x10  = 0x23FF FFF0
((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF) << 5)  + (5 << 2))  = 0x2000 0000 + 0x200 0000  + 0x1FF FFE0 + 0x14  = 0x23FF FFF4
((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF) << 5)  + (6 << 2))  = 0x2000 0000 + 0x200 0000  + 0x1FF FFE0 + 0x18  = 0x23FF FFF8
((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF) << 5)  + (7 << 2))  = 0x2000 0000 + 0x200 0000  + 0x1FF FFE0 + 0x1C  = 0x23FF FFFC

即下图所示: E0、E4、E8、EC、F0、F4、F8、FC (最后两位不同)

在这里插入图片描述

6. sys.h

#ifndef __SYS_H
#define __SYS_H	
#include "stm32f10x.h"

//0,不支持os
//1,支持os
#define SYSTEM_SUPPORT_OS		1		//定义系统文件夹是否支持OS

// IO口操作宏定义, 参考<<CM3权威指南>>第五章(87页~92页)
#define BITBAND(addr, bitnum) ((addr & 0xF0000000) + 0x2000000 + ((addr & 0xFFFFF) << 5) + (bitnum << 2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE + 12) // 0x4001 080C
#define GPIOB_ODR_Addr    (GPIOB_BASE + 12) // 0x4001 0C0C
#define GPIOC_ODR_Addr    (GPIOC_BASE + 12) // 0x4001 100C
#define GPIOD_ODR_Addr    (GPIOD_BASE + 12) // 0x4001 140C
#define GPIOE_ODR_Addr    (GPIOE_BASE + 12) // 0x4001 180C
#define GPIOF_ODR_Addr    (GPIOF_BASE + 12) // 0x4001 1A0C
#define GPIOG_ODR_Addr    (GPIOG_BASE + 12) // 0x4001 1E0C

#define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808 
#define GPIOB_IDR_Addr    (GPIOB_BASE+8) //0x40010C08 
#define GPIOC_IDR_Addr    (GPIOC_BASE+8) //0x40011008 
#define GPIOD_IDR_Addr    (GPIOD_BASE+8) //0x40011408 
#define GPIOE_IDR_Addr    (GPIOE_BASE+8) //0x40011808 
#define GPIOF_IDR_Addr    (GPIOF_BASE+8) //0x40011A08 
#define GPIOG_IDR_Addr    (GPIOG_BASE+8) //0x40011E08 
 
//IO口操作,只对单一的IO口,GPIO_n 设置成输出模式或者输入模式
//确保n的值小于16!
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n) 

#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 

#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入

#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入

#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入

//以下为汇编函数
void WFI_SET(void);		//执行WFI指令
void INTX_DISABLE(void);//关闭所有中断
void INTX_ENABLE(void);	//开启所有中断
void MSR_MSP(u32 addr);	//设置堆栈地址

#endif

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL-6-多表操作

一、复制表 格式 create table 表名 select查询语句注意&#xff1a;复制成新表时&#xff0c;键值&#xff08;pri,index等等&#xff09;索引不会同步复制案例 mysql> create table t2 select name,sex,age from user;二、多表查询 2.1、 多表查询–>连接查询 将2个…

Vue.js 比较重要知识点总结一

概述 谈一谈你对 Vue.js 的响应式数据的理解Vue3 出现解决了什么问题&#xff1f;它有哪些优势&#xff1f;Vue3 新特性有哪些vue2 和 vue3 的响应式有什么区别&#xff1f; 谈一谈你对 Vue.js 的响应式数据的理解 Vue 2.x 对象类型&#xff1a;通过 object.defineProperty(…

MySQL——初窥门径

前言 六一&#xff1f;作为一个大小孩当然是快快乐乐搞技术啦~在这篇文章中&#xff0c;荔枝会梳理SQL语句的基本语法以及MySQL中的函数、约束。多表关系以及查询、事务和事务隔离级别等内容&#xff0c;大致内容归属于MySQL基础知识&#xff0c;荔枝又弄了一篇万字长文哈哈哈哈…

R:GAM非线性回归曲线拟合与散点密度图绘制

作者:CSDN @ _养乐多_ 本文将介绍使用R语言以及GAM模型,绘制回归曲线和散点密度图。 文章目录 一、R语言脚本二、色带一、R语言脚本 install.packages("ggpointdensity") install.packages("ggplot2") insta

IPD发展史

随着IPD&#xff08;集成产品开发&#xff09;在IBM、华为等企业取得了巨大的成功&#xff0c;其他行业也开始在相关新产品研发中初步引入IPD的研发管理理念及模式&#xff0c;对IPD在行业的应用进行初步的探索和研究。 为了更好地应用IPD &#xff0c;不仅要对它的理念和思想理…

浅谈高等学校能源监控管理体系建设

摘要&#xff1a;现代高校担当着人才培养&#xff0c;社会服务和文化传承与创新的光荣使命。高校低碳节能工作是加快建设“和谐社会”、“绿色校园”的重要举措 。当前高校以“数字化能源监测平台”为重心 &#xff0c;积极推动能源管理的转型 。该文总结高校能源监管平台建设的…

达梦数据库作业调度及警报配置

目录 作业... 4 创建代理环境... 4 1、命令行创建及删除... 4 2、客户端创建及删除... 4 操作员... 5 1、命令行创建及删除... 5 2、客户端创建及删除... 5 作业... 6 一、命令行... 6 1、命令行创建作业... 6 2、命令行修改作业... 7 3、启动或暂停作业... 7 4、…

MATLAB与深度学习:Neural Network Toolbox和Deep Learning Toolbox的使用和模型设计

章节一&#xff1a;引言 在当今人工智能和深度学习的时代&#xff0c;MATLAB作为一种功能强大的科学计算和数据分析工具&#xff0c;在深度学习领域也发挥着重要作用。本文将重点介绍MATLAB中的两个关键工具&#xff1a;Neural Network Toolbox和Deep Learning Toolbox的使用和…

chatgpt赋能python:Python主页的SEO优化

Python主页的SEO优化 Python是一种简单易学、高效灵活的编程语言。其主页Python.org是全球最受欢迎的编程语言之一的官方网站。但是&#xff0c;即使是最著名的网站也需要进行优化&#xff0c;以便在搜索引擎中排名更高。在本文中&#xff0c;我们将探讨如何通过SEO来改进Pyth…

关系型数据库一些概念性的知识点总结

在当今数据驱动的世界中&#xff0c;信息为王。从客户资料到金融交易&#xff0c;每个组织都依赖数据来做出明智的决策并在竞争中保持领先地位。但随着数据量以前所未有的速度增长&#xff0c;管理和分析所有这些信息很快就会变得不堪重负。这就是关系数据库的用武之地。 关系数…

kafka的基础知识及概念

介绍 kafka在过去几年获得了巨大的普及。在微服务架构中&#xff0c;它起着举足轻重的作用。它使数据能够从一项服务转移到另一项服务。我开始这个系列是为了帮助初学者深入了解 Kafka。但是&#xff0c;在我们深入之前&#xff0c;了解一些基础知识很重要。因此&#xff0c;在…

《智能新工厂规划白皮书》:新工厂发展趋势一览

在经济下行压力、人口红利消失、消费结构升级、疫情冲击等多种因素推动下&#xff0c;传统工厂的寒冬已至&#xff0c;必须要变革才能顺应未来的发展趋势。伴随着5G、工业互联网、AI、工业大数据、工业软件等技术或产品的发展融合&#xff0c;许多企业纷纷规划建设智能新工厂&a…

【Web服务器集群】Nginx网站服务

文章目录 一、Nginx 概述1.什么是 Nginx2.Nginx 的特点3.Nginx 应用场景 二、Nginx 服务基础1.编译安装 Nginx 服务1.1 布置环境1.2 安装依赖包1.3 创建运行用户、组1.4 编译安装 2.Nginx 的运行控制2.1 检查配置文件2.2 启动、停止 Nginx2.3 日志分割以及升级 Nginx 服务2.4 添…

Linux - 第18节 - 网络基础(传输层一)

目录 1.传输层 1.1.再谈端口号 1.2.端口号范围划分 1.3.认识知名端口号 1.4.两个问题 1.5.netstat命令 1.6.pidof命令 2.UDP协议 2.1.UDP协议格式 2.2.UDP协议的特点 2.3.面向数据报 2.4.UDP的缓冲区 2.5.UDP使用注意事项 2.6.基于UDP的应用层协议 3.TCP协议 3…

抖音seo源码开发代码分享

抖音seo优化&#xff0c;抖音seo源码开发&#xff0c;抖音排名系统源码开发展示实例&#xff1a; 思路&#xff1a;抖音seo源码&#xff0c;抖音seo矩阵系统底层框架上支持了从ai视频混剪&#xff0c;视频批量原创产出&#xff0c;云存储批量视频制作&#xff0c;账号矩阵&…

如何制作一个连杆组简易四足机器人

1. 运动功能说明 本文示例将实现R296样机连杆组简易四足机器人前进的功能。 2. 电子硬件 在这个示例中&#xff0c;我们采用了以下硬件&#xff0c;请大家参考&#xff1a; 主控板 Basra主控板&#xff08;兼容Arduino Uno&#xff09;‍ 扩展板 Bigfish2.1扩展板‍ 电池7.4V锂…

STM32F105RBT6 -- RCC 系统时钟

1. STM32F105RBT6 系统时钟树 2. 使用外部时钟给系统提供时钟HSE&#xff0c;外接一个8Mhz的晶振 3. 系统在启动的时候就会调用系统初始化函数&#xff0c;配置RCC 时钟系统&#xff0c;在调用main函数之前调用SystemInit函数 startup_stm32f10x_hd.s ; Reset handler Reset_…

电脑重装系统 / 系统迁移

1. 台式机太卡了&#xff0c;在网上买了个固态硬盘&#xff1a;250G&#xff0c; Kingston的&#xff0c;把C盘&#xff08;系统盘&#xff09;迁移到固态硬盘上去 2. 下载软件 https://www.diskgenius.cn/download.php3. 使用DiskGenius软件&#xff0c;可以方便地将系统从一…

【MySQL】- 04 MVCC 概要

MVCC 概要 事务概念事务的特性&#xff1a;ACID事务的操作隔离性引发的并发问题事务的隔离级别 LBCC&MVCCLBCC记录锁&#xff08;Record Locks&#xff09;间隙锁&#xff08;GAP Locks&#xff09;临键锁&#xff08;Next-Key Locks&#xff09;总结当前读什么是MVCC?什么…

[QT_055]设置QT源码调试(qtc+vs/mingw+msvc)

在开发过程中&#xff0c;我们经常用到调试功能&#xff0c;这样方便查找Bug&#xff1b;Qt是一个开源的框架&#xff0c;可以看到源码。虽然但大部分情况下&#xff0c;我们开发时&#xff0c;只是使用&#xff0c;并没有调试它的源码&#xff0c;但如果想深入了解Qt的一些机制…