×
单片机 > 单片机程序设计 > 详情

STM32外设寄存器地址定义

发布时间:2020-08-21 发布时间:
|

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

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

首先在stm32f4xx.h中


  1. typedef struct  

  2. {  

  3.   __IO uint16_t SR;         /*!

  4.   uint16_t      RESERVED0;  /*!

  5.   __IO uint16_t DR;         /*!

  6.   uint16_t      RESERVED1;  /*!

  7.   __IO uint16_t BRR;        /*!

  8.   uint16_t      RESERVED2;  /*!

  9.   __IO uint16_t CR1;        /*!

  10.   uint16_t      RESERVED3;  /*!

  11.   __IO uint16_t CR2;        /*!

  12.   uint16_t      RESERVED4;  /*!

  13.   __IO uint16_t CR3;        /*!

  14.   uint16_t      RESERVED5;  /*!

  15.   __IO uint16_t GTPR;       /*!

  16.   uint16_t      RESERVED6;  /*!

  17. } USART_TypeDef;  

这是因为USART的寄存器组包括SR,DR,BRR,CR1,CR2,CR3,GPTR这几个寄存器,所以用一个USART_TypeDef结构体包含这些寄存器。如果在别的程序中用到这些寄存器,只需要如下:


  1. USART_TypeDef   USART1//任意取名,尽量与Datasheet中给出的名字一致便于理解  

  2. USART1.SR = 0x0000 0001;  

或者 


  1. USART_TypeDef*   USART1  

  2. USART1->SR = 0x0000 0001;  


  1. (*USART1).SR = 0x0000 0011;  


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

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


  1. #define PERIPH_BASE           ((uint32_t)0x40000000)  

  2. /*!

  3.    

  4. /*!

  5. #define APB1PERIPH_BASE       PERIPH_BASE  

  6.    

  7. #define USART2_BASE           (APB1PERIPH_BASE + 0x4400)  

  8. #define USART3_BASE           (APB1PERIPH_BASE + 0x4800)  

  9. #define UART4_BASE            (APB1PERIPH_BASE + 0x4C00)  

  10. #define UART5_BASE            (APB1PERIPH_BASE + 0x5000)  

  11.    

  12. #define USART2              ((USART_TypeDef *) USART2_BASE)  

  13. #define USART3              ((USART_TypeDef *) USART3_BASE)  

  14. #define UART4               ((USART_TypeDef *) UART4_BASE)  

  15. #define UART5               ((USART_TypeDef *) UART5_BASE)  

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


  1. USART_Cmd(USART2, ENABLE);  

USART_Cmd这是ST官方给出的库函数,具体定义如下


  1. void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState)  

  2. {  

  3.   /* Check the parameters */  

  4.   assert_param(IS_USART_ALL_PERIPH(USARTx));  

  5.   assert_param(IS_FUNCTIONAL_STATE(NewState));  

  6.     

  7.   if (NewState != DISABLE)  

  8.   {  

  9.     /* Enable the selected USART by setting the UE bit in the CR1 register */  

  10.     USARTx->CR1 |= USART_CR1_UE;  

  11.   }  

  12.   else  

  13.   {  

  14.     /* Disable the selected USART by clearing the UE bit in the CR1 register */  

  15.     USARTx->CR1 &= (uint16_t)~((uint16_t)USART_CR1_UE);  

  16.   }  

  17. }  

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


关键字:STM32  外设寄存器  地址定义 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
ARM 汇编的必知必会