STM32外設(shè)寄存器地址定義
一直都是用STM32做項(xiàng)目中的主控芯片,在編程的時(shí)候,之前一直忽視了一個(gè)問題,那就是寄存器的位置是如何定義的,為什么用一個(gè)USART1->CR操作就能夠給這個(gè)CR寄存器賦值?其實(shí)這是一個(gè)比較底層的問題,不懂這方面的知識(shí)也并不影響使用STM32,因?yàn)榈讓拥亩x工作,廠家一般都會(huì)做好,但是多了解一點(diǎn)原理性的東西,對(duì)自己還是很有幫助的。
這里我就以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; 這是因?yàn)閁SART的寄存器組包括SR,DR,BRR,CR1,CR2,CR3,GPTR這幾個(gè)寄存器,所以用一個(gè)USART_TypeDef結(jié)構(gòu)體包含這些寄存器。如果在別的程序中用到這些寄存器,只需要如下: USART_TypeDefUSART1//任意取名,盡量與Datasheet中給出的名字一致便于理解 USART1.SR=0x00000001; 或者 USART_TypeDef*USART1 USART1->SR=0x00000001; (*USART1).SR=0x00000011; 那么具體到各個(gè)寄存器的位置到底是怎樣的呢?從Datasheet和reference manual中可以看到 USART2屬于APB1管理的外設(shè),起始地址是0x4000 4400,STM32上所有的外設(shè)的基地址都是0x4000 0000(這其實(shí)是ARM公司規(guī)定的),這也是APB1的起始地址,然后USART2的起始地址在APB1外設(shè)基地址的基礎(chǔ)上偏移0x4400,于是便可以按照下面代碼來分配各個(gè)外設(shè)的起始地址了 #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) 有了這些外設(shè)的基地址,加上上面提到的寄存器結(jié)構(gòu)體,便可以操作各個(gè)寄存器了,例如,只需要如下語(yǔ)句,便可以使能USART2 USART_Cmd(USART2,ENABLE); USART_Cmd這是ST官方給出的庫(kù)函數(shù),具體定義如下 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); } } 如果理解了上述所講的內(nèi)容,你會(huì)發(fā)現(xiàn),這種通過結(jié)構(gòu)體定義寄存器的方法非常常見,這是因?yàn)楝F(xiàn)在的處理器,各種寄存器相當(dāng)多(成百上千),如果按照傳統(tǒng)的定義方法去操作寄存器,會(huì)相當(dāng)?shù)穆闊?。不只是STM32,我知道的有TI的C2000系列DSP,NXP的ARM系列MCU,瑞薩的ARM R4 RZ/T1處理器都是按這樣的方法來定義寄存器。