最近由於在學習STM32看到別人用寄存器編程式控制制跑馬燈,於是自己也想試一試。可是試了好久終究弄不出來。回頭看了下庫函數的調用關係才搞明白。首先通過查看GPIOA的設置函數發現設置如下: 改機構體根據結構體成員函數的大小自己形成了針對首地址的偏移量。從而與需要操作的寄存器地址偏移一一對應。通過查看設置 ...
最近由於在學習STM32看到別人用寄存器編程式控制制跑馬燈,於是自己也想試一試。可是試了好久終究弄不出來。回頭看了下庫函數的調用關係才搞明白。首先通過查看GPIOA的設置函數發現設置如下:
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) { uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00; /* Check the parameters */ assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin)); assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode)); assert_param(IS_GPIO_PUPD(GPIO_InitStruct->GPIO_PuPd)); /* ------------------------- Configure the port pins ---------------- */ /*-- GPIO Mode Configuration --*/ for (pinpos = 0x00; pinpos < 0x10; pinpos++) { pos = ((uint32_t)0x01) << pinpos; /* Get the port pins position */ currentpin = (GPIO_InitStruct->GPIO_Pin) & pos; if (currentpin == pos) { GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (pinpos * 2)); GPIOx->MODER |= (((uint32_t)GPIO_InitStruct->GPIO_Mode) << (pinpos * 2)); if ((GPIO_InitStruct->GPIO_Mode == GPIO_Mode_OUT) || (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_AF)) { /* Check Speed mode parameters */ assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed)); /* Speed mode configuration */ GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (pinpos * 2)); GPIOx->OSPEEDR |= ((uint32_t)(GPIO_InitStruct->GPIO_Speed) << (pinpos * 2)); /* Check Output mode parameters */ assert_param(IS_GPIO_OTYPE(GPIO_InitStruct->GPIO_OType)); /* Output mode configuration*/ GPIOx->OTYPER &= ~((GPIO_OTYPER_OT_0) << ((uint16_t)pinpos)) ; GPIOx->OTYPER |= (uint16_t)(((uint16_t)GPIO_InitStruct->GPIO_OType) << ((uint16_t)pinpos)); } /* Pull-up Pull down resistor configuration*/ GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << ((uint16_t)pinpos * 2)); GPIOx->PUPDR |= (((uint32_t)GPIO_InitStruct->GPIO_PuPd) << (pinpos * 2)); } } }
GPIO_TypeDef埠設置結構體如下:
typedef struct { __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */ __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */ __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */ __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */ __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */ __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */ __IO uint16_t BSRRL; /*!< GPIO port bit set/reset low register, Address offset: 0x18 */ __IO uint16_t BSRRH; /*!< GPIO port bit set/reset high register, Address offset: 0x1A */ __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */ __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */ } GPIO_TypeDef;
改機構體根據結構體成員函數的大小自己形成了針對首地址的偏移量。從而與需要操作的寄存器地址偏移一一對應。通過查看設置函數可以看出,初始設置需要進行幾步必要的設置,經過實驗發現只需要設置
GPIOx->MODER和時鐘就可以。同時需要對GPIO 埠置位/複位寄存器進行操作。由該寄存器可以知,低16位置位1,高16位複位0。由此得出寄存器操作代碼如下:
//#define GPIPA *(volatile unsigned long *)0x40020000; #define GPIOA_MODER *(volatile unsigned long *)0x40020000 #define GPIOA_OSPEEDR *(volatile unsigned long *)0x40020008 #define GPIOA_OTYPER *(volatile unsigned long *)0x40020004 #define GPIOA_PUPDR *(volatile unsigned long *)0x4002000C #define RCC_AHB1ENR *(volatile unsigned long *)0x40023830 #define GPIOA_BSRR *(volatile unsigned long *)0x40020018 //typedef struct //{ // __IO uint32_t MODER; /*!< GPIO port mode register, Address offset: 0x00 */ // __IO uint32_t OTYPER; /*!< GPIO port output type register, Address offset: 0x04 */ // __IO uint32_t OSPEEDR; /*!< GPIO port output speed register, Address offset: 0x08 */ // __IO uint32_t PUPDR; /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */ // __IO uint32_t IDR; /*!< GPIO port input data register, Address offset: 0x10 */ // __IO uint32_t ODR; /*!< GPIO port output data register, Address offset: 0x14 */ // __IO uint16_t BSRRL; /*!< GPIO port bit set/reset low register, Address offset: 0x18 */ // __IO uint16_t BSRRH; /*!< GPIO port bit set/reset high register, Address offset: 0x1A */ // __IO uint32_t LCKR; /*!< GPIO port configuration lock register, Address offset: 0x1C */ // __IO uint32_t AFR[2]; /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */ //} GPIO_TypeDef; void delay_ms(int time) { int i=8000*time; while(i--); } int main(void) { // delay_init(168); int i = 0, j = 0, k = 0; RCC_AHB1ENR |= 0x00000001; GPIOA_MODER &= ~((3<<(6*2))|(3<<(7*2))); GPIOA_MODER |= (1<< (6*2))|(1<<(7*2)); GPIOA_BSRR &= 0x0; //clear /* Speed mode configuration */ // GPIOA_OSPEEDR &= ~((3<<(6*2))|(3<<(7*2))); // GPIOA_OSPEEDR |= (3 << (6 * 2))|(3 << (7 * 2)); /* Output mode configuration*/ // GPIOA_OTYPER &= ~((3<<6)|(3<<7)) ; // GPIOA_OTYPER |= (0 << 6)|(0 << 7); /* Pull-up Pull down resistor configuration*/ // GPIOA_PUPDR &= ~((3<<(6*2))|(3<<(7*2))); // GPIOA_PUPDR |= (1<< (6*2))|(1<<(7*2)); // GPIOA_BSRRL = 0x0040|0x0080; while(1) { GPIOA_BSRR = (0x0040|0x0080)<<16; //reset delay_ms(1000); GPIOA_BSRR = 0x0040|0x0080; //set delay_ms(1000); } } void SystemInit() { ; }
以上代碼便可以實現流水燈例子。