打印
[信息]

定义STM32单片机寄存器的位置

[复制链接]
361|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主

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

       

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

        首先在stm32f4xx.h中

        typedefstruct

        {

        __IOuint16_tSR;/*!

        uint16_tRESERVED0;/*!

        __IOuint16_tDR;/*!

        uint16_tRESERVED1;/*!

        __IOuint16_tBRR;/*!

        uint16_tRESERVED2;/*!

        __IOuint16_tCR1;/*!

        uint16_tRESERVED3;/*!

        __IOuint16_tCR2;/*!

        uint16_tRESERVED4;/*!

        __IOuint16_tCR3;/*!

        uint16_tRESERVED5;/*!

        __IOuint16_tGTPR;/*!

        uint16_tRESERVED6;/*!

        }USART_TypeDef;

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

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

        USART1.SR=0x00000001;

        或者

        USART_TypeDef*USART1

        USART1-》SR=0x00000001;

        (*USART1).SR=0x00000011;

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

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

        #definePERIPH_BASE((uint32_t)0x40000000)

        /*!

        /*!

        #defineAPB1PERIPH_BASEPERIPH_BASE

        #defineUSART2_BASE(APB1PERIPH_BASE+0x4400)

        #defineUSART3_BASE(APB1PERIPH_BASE+0x4800)

        #defineUART4_BASE(APB1PERIPH_BASE+0x4C00)

        #defineUART5_BASE(APB1PERIPH_BASE+0x5000)

        #defineUSART2((USART_TypeDef*)USART2_BASE)

        #defineUSART3((USART_TypeDef*)USART3_BASE)

        #defineUART4((USART_TypeDef*)UART4_BASE)

        #defineUART5((USART_TypeDef*)UART5_BASE)

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

        USART_Cmd(USART2,ENABLE);

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

        voidUSART_Cmd(USART_TypeDef*USARTx,FunctionalStateNewState)

        {

        /*Checktheparameters*/

        assert_param(IS_USART_ALL_PERIPH(USARTx));

        assert_param(IS_FUNCTIONAL_STATE(NewState));

        if(NewState!=DISABLE)

        {

        /*EnabletheselectedUSARTbysetTIngtheUEbiTIntheCR1register*/

        USARTx-》CR1|=USART_CR1_UE;

        }

        else

        {

        /*DisabletheselectedUSARTbyclearingtheUEbiTIntheCR1register*/

        USARTx-》CR1&=(uint16_t)~((uint16_t)USART_CR1_UE);

        }

        }

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

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

125

主题

201

帖子

0

粉丝