STM32外设寄存器地址定义

2023-05-16

一直都是用STM32做项目中的主控芯片,在编程的时候,之前一直忽视了一个问题,那就是寄存器的位置是如何定义的,为什么用一个USART1->CR操作就能够给这个CR寄存器赋值?其实这是一个比较底层的问题,不懂这方面的知识也并不影响使用STM32,因为底层的定义工作,厂家一般都会做好,但是多了解一点原理性的东西,对自己还是很有帮助的。

这里我就以STM32F407的USART寄存器为例,介绍一下ST厂家是如何做寄存器定义的。

首先在stm32f4xx.h中

typedef struct
{
  __IO uint16_t SR;         /*!< USART Status register,                   Address offset: 0x00 */
  uint16_t      RESERVED0;  /*!< Reserved, 0x02                                                */
  __IO uint16_t DR;         /*!< USART Data register,                     Address offset: 0x04 */
  uint16_t      RESERVED1;  /*!< Reserved, 0x06                                                */
  __IO uint16_t BRR;        /*!< USART Baud rate register,                Address offset: 0x08 */
  uint16_t      RESERVED2;  /*!< Reserved, 0x0A                                                */
  __IO uint16_t CR1;        /*!< USART Control register 1,                Address offset: 0x0C */
  uint16_t      RESERVED3;  /*!< Reserved, 0x0E                                                */
  __IO uint16_t CR2;        /*!< USART Control register 2,                Address offset: 0x10 */
  uint16_t      RESERVED4;  /*!< Reserved, 0x12                                                */
  __IO uint16_t CR3;        /*!< USART Control register 3,                Address offset: 0x14 */
  uint16_t      RESERVED5;  /*!< Reserved, 0x16                                                */
  __IO uint16_t GTPR;       /*!< USART Guard time and prescaler register, Address offset: 0x18 */
  uint16_t      RESERVED6;  /*!< Reserved, 0x1A                                                */
} USART_TypeDef;
这是因为USART的寄存器组包括SR,DR,BRR,CR1,CR2,CR3,GPTR这几个寄存器,所以用一个USART_TypeDef结构体包含这些寄存器。如果在别的程序中用到这些寄存器,只需要如下:

USART_TypeDef   USART1//任意取名,尽量与Datasheet中给出的名字一致便于理解
USART1.SR = 0x0000 0001;
或者 
USART_TypeDef*   USART1
USART1->SR = 0x0000 0001;
(*USART1).SR = 0x0000 0011;

  

那么具体到各个寄存器的位置到底是怎样的呢?从Datasheet和reference manual中可以看到

USART2属于APB1管理的外设,起始地址是0x4000 4400,STM32上所有的外设的基地址都是0x4000 0000(这其实是ARM公司规定的),这也是APB1的起始地址,然后USART2的起始地址在APB1外设基地址的基础上偏移0x4400,于是便可以按照下面代码来分配各个外设的起始地址了

#define PERIPH_BASE           ((uint32_t)0x40000000)
/*!< Peripheral base address in the alias region*/
 
/*!< Peripheral memory map */
#define APB1PERIPH_BASE       PERIPH_BASE
 
#define USART2_BASE           (APB1PERIPH_BASE + 0x4400)
#define USART3_BASE           (APB1PERIPH_BASE + 0x4800)
#define UART4_BASE            (APB1PERIPH_BASE + 0x4C00)
#define UART5_BASE            (APB1PERIPH_BASE + 0x5000)
 
#define USART2              ((USART_TypeDef *) USART2_BASE)
#define USART3              ((USART_TypeDef *) USART3_BASE)
#define UART4               ((USART_TypeDef *) UART4_BASE)
#define UART5               ((USART_TypeDef *) UART5_BASE)

有了这些外设的基地址,加上上面提到的寄存器结构体,便可以操作各个寄存器了,例如,只需要如下语句,便可以使能USART2

USART_Cmd(USART2, ENABLE);
USART_Cmd这是ST官方给出的库函数,具体定义如下
void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_USART_ALL_PERIPH(USARTx));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  
  if (NewState != DISABLE)
  {
    /* Enable the selected USART by setting the UE bit in the CR1 register */
    USARTx->CR1 |= USART_CR1_UE;
  }
  else
  {
    /* Disable the selected USART by clearing the UE bit in the CR1 register */
    USARTx->CR1 &= (uint16_t)~((uint16_t)USART_CR1_UE);
  }
}

如果理解了上述所讲的内容,你会发现,这种通过结构体定义寄存器的方法非常常见,这是因为现在的处理器,各种寄存器相当多(成百上千),如果按照传统的定义方法去操作寄存器,会相当的麻烦。不只是STM32,我知道的有TI的C2000系列DSP,NXP的ARM系列MCU,瑞萨的ARM R4 RZ/T1处理器都是按这样的方法来定义寄存器。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

STM32外设寄存器地址定义 的相关文章

  • C/C++ —— 小端转大端函数的使用

    函数说明 uint32 t htonl uint32 t hostlong uint16 t htons uint16 t hostshort uint32 t ntohl uint32 t netlong uint16 t ntohs u
  • AntDesign Upload组件上传图片

    技术选型 前端技术选型 xff1a React Hook 43 typescript antd版本 xff1a 3 18 使用Upload上传图片 上传效果截图 预览效果截图 项目中完整写法 xff1a span class token k
  • [LeetCode] 876. Middle of the Linked List

    Given a non empty singly linked list with head node head return a middle node of linked list If there are two middle nod
  • 博客搬家啦

    博客搬家啦 xff0c 新博客地址 https blueleek blue 小伙伴一起嗨学一起来
  • MFC 改变编辑框字体(大小,字体)

    1 在 Dlg h文件中加入 CFont font 字体对象 2 定义一个CEdit控件变量 CEdit m EditAa 61 CEdit GetDlgItem IDC A EDIT A 关联控件A CEdit m EditBb 61 C
  • STM32 中浮点转成字符串,解决 -u_printf_float

    开发偶遇问题 在C 43 43 或其他高级语言中 xff0c 以及C语言在Visual Studio或者linux平台上 xff0c 是可以直接通过sprintf将 xff0c int float转换成string类型的 xff1b 但是
  • 路由器原理(一)

    觉得之前对路由器的了解还不是特别清楚 xff0c 继续来学习 xff0c 是参考了路由器的原理及其配置 xff08 一 xff09 一 xff1a 路由器的基础知识 xff08 1 xff09 路由器的概述 xff1a 作为网络层的网络互连
  • 表单提交及后台数据接收

    用POST请求 xff0c 后台原生接收的一个公式 xff1a span class hljs transposed variable req span addListener span class hljs string 34 data
  • JSON怎样添加注释

    今天在写一个程序的时候发现了一个问题 xff0c 在json文件中添加注释之后 xff0c 程序就出现bug了 于是 xff0c 去搜了一下这个问题的相关解释 xff0c 在这里和大家分享一下 xff1a JSON为什么不能添加注释 xff
  • Converting circular structure to JSON

    在做手机验证码模块 xff0c 遇到一个bug Converting circular span class hljs keyword structure span span class hljs keyword to span JSON
  • Mac root和普通用户切换

    今日 xff0c 老身在用su 命令 xff0c 输入密码之后准备切换至root用户 但不幸得到这个消息 xff1a su Sorry 找到解决方案如下 xff1a span class hljs built in sudo span su
  • TCP UDP 的区别和具体应用场景

    TCP和UDP 两者都是通信协议 xff0c TCP和UDP都是传输层协议 xff0c 但是他们的通信机制和应用场景不同 TCP TCP xff08 Transmission Control Protocol xff09 又叫传输控制协议
  • 浏览器缓存机制详解(一)

    浏览器缓存机制可以极大的提升用户体验 xff0c 另一方面会因为读取缓存而展示了错误的东西 xff0c 因而在开发中要设法将其删除 什么是浏览器缓存 xff1f 浏览器缓存就是把一个已经请求过的web资源 xff08 如html页面 xff
  • G2O库和Eigen库can not find 问题——FindG2O.cmake FindEigen3.cmake

    目录 CMakeLists设置FindG2O cmake文件内容FindEigen3 cmake 文件内容 CMakeLists设置 在CMakeLists里加入如下这句话 xff0c 并在项目文件夹中新建cmake文件夹 LIST APP
  • sockaddr_in结构体

    点击进入结构如下 xff1a struct sockaddr in uint8 t sin len sa family t sin family in port t sin port struct in addr sin addr char
  • Win7下VS2010使用STLPort .

    Win7下VS2010使用STLPort 更新于2012年8月24日 星期五 http blog csdn net shunqiziranhao007 article details 7905435 STLport的下载地址 http so
  • 【极简笔记】OpenPose

    极简笔记 Realtime Multi Person 2D Pose Estimation using Part Affinity Fields 论文地址 xff1a https arxiv org abs 1611 08050 文章的核心
  • C++各类库

    1 C 43 43 各大有名库的介绍 C 43 43 标准库 2 C 43 43 各大有名库的介绍 准标准库Boost 3 C 43 43 各大有名库的介绍 GUI 4 C 43 43 各大有名库的介绍 网络通信 5 C 43 43 各大有
  • watch 50 行代码实现 windows watch

    watch 50 行代码实现 windows watch 最近想监控 gpu 使用情况 xff0c 无奈在 windows 上没有 watch 指令 xff0c nvidia smi lms 20 自带输出也不美观 xff0c 那么为何不自
  • intel CPU 命名含义

    https www intel com content www us en processors processor numbers html

随机推荐

  • 使用 c++ 如何一行行的读取文本数据?

    使用 std getline 函数读取文件行 https en cppreference com w cpp string basic string getline 下面进行不同写法读取文件行的方式的比较 for std string li
  • android NDK 如何使用 JNI 与 Java&Kotlin 语言交互?

    android NDK 如何使用 JNI 与 Java amp Kotlin 语言交互 xff1f http web archive org web 20120626135526 http java sun com docs books j
  • 海康威视摄像头 rtsp 地址格式

    海康威视摄像头 rtsp 地址格式 单播取流格式 rtsp username password 64 ip port Steaming Channels number 多播取流格式 rtsp username password 64 ip
  • debian 11.3 国内最快镜像源

    debian 11 3 国内最快镜像源 deb https mirrors tencent com debian bullseye main non free contrib deb src https mirrors tencent co
  • golang 如何自定义解析 markdown to html ?

    golang 如何自定义解析 markdown to html xff1f 输出 HTML 模板内容如下 span class token doctype span class token punctuation lt span span
  • 如何计算 2d 多边形面积?

    如何使用 C 43 43 11 30 行代码搞定计算 2D 多边形面积 xff1f 完整代码如下 xff1a include lt vector gt include lt utility gt using Point 61 std pai
  • 怎样为MFC对话框建立初始化函数BOOL HistoryData::OnInitDialog()

    一 在要建立OnInitDialog 的对话框上右击建立类向导 xff0c 如下图 xff1a 二 为对话框建立消息映射 xff0c 如下图 xff1a 在classwizard的Message Maps中的Object IDs选择该对话框
  • 颜色值如何使用 C++ 输出字符串格式?

    颜色值如何使用 C 43 43 输出字符串格式 xff1f https developer android com reference android graphics Color html https en wikipedia org w
  • 如何使用 opencv 调用 yolov5 onnx 模型 ?

    如何使用 opencv 调用 yolov5 onnx 模型 xff1f rtx3090 24G release 90 fps by use yolov5n rtx3090 24G release 20 fps by use yolov5s
  • Conda 备忘录指南 (VER 4.12.0)

    Conda 备忘录指南 VER 4 12 0 快速入门 提示 建议为任何新项目或工作流创建一个新环境 CNENCMD验证conda安装和检查版本verify conda install and check versionconda info
  • 使用 C++ filesystem 递归目录

    如何使用 C 43 43 filesystem 递归目录 xff1f include lt Windows h gt include lt iostream gt include lt string gt include lt fstrea
  • CMake 如何复制文件?

    何时执行自定义指令 PRE BUILD PRE LINK POST BUILD 单文件 add custom command TARGET PROJECT NAME POST BUILD COMMAND CMAKE COMMAND E co
  • 什么是 MQ?

    消息队列 MQ 是在微服务架构中使用的异步服务到服务通信协议 在 MQ 中 xff0c 消息被排队 xff0c 直到它们被处理和删除 每条消息只处理一次 此外 xff0c MQ 可用于解耦重量级处理 缓冲和批处理工作 消息队列提供系统不同部
  • Qt 如何并发异步调用?

    Qt 如何并发异步调用 xff1f QT 43 61 core concurrent widgets template lt typename T typename Handler gt void await const QFuture l
  • 如何使用 C++ 构建一个环结构?

    C 43 43 环状移动 include lt iostream gt include lt list gt int main auto list 61 std list lt int gt 1 3 5 7 9 for auto i 61
  • C++ std::thread 如何使用?

    C 43 43 是一种高级编程语言 xff0c 被广泛用于开发高性能 大规模 复杂的软件系统 其中一个强大的特性就是多线程编程 xff0c 而std thread是C 43 43 标准库提供的多线程支持的重要组成部分 免费虚拟手机号注册网址
  • 导航雷达回波信号格式和目标检测算法

    导航雷达回波信号格式 导航雷达回波信号格式会根据具体的雷达类型和应用场景有所不同 通常 xff0c 导航雷达回波信号包含以下几个关键参数 xff1a 距离信息 xff08 Range xff09 xff1a 雷达发送的电磁波与目标相互作用后
  • 厦门IT公司名单及联系方式

    厦门高士达科技实业有限公司 xff1a xff08 已走访并开展了座谈 xff09 地址 xff1a 厦门软件园观日路58号9楼 总机 xff1a 2958000 联系人 xff1a 童小姐 xff08 人事专员 xff09 厦门恒深智能软
  • 巧用可变参数宏、编译器内置宏和printf输出调试信息

    前言 xff1a 我们在写程序的时候 xff0c 总是或多或少会加入一些printf之类的语句用于输出调试信息 xff0c 但是printf语句有个很不方便的地方就是当我们需要发布程序的时候要一条一条的把这些语句删除 xff0c 而一旦需要
  • STM32外设寄存器地址定义

    一直都是用STM32做项目中的主控芯片 xff0c 在编程的时候 xff0c 之前一直忽视了一个问题 xff0c 那就是寄存器的位置是如何定义的 xff0c 为什么用一个USART1 gt CR操作就能够给这个CR寄存器赋值 xff1f 其