C 使用解引用指针和结构之间的STM32F446xx外围寄存器访问差异
我试图简单地点亮一个外部LED(连接到我的STM32F446RE的端口C引脚10)。我使用gcc arm none eabi 8-2019-q3-update for windows用于编译器,使用Keil uVision5 IDE用于板的闪烁/调试(Keil IDE还使用gcc编译器处理编译) 在下面的代码中,当使用structs引用GPIO和RCC外围寄存器(main的第二个“部分”)时,一切都能正常工作。C 使用解引用指针和结构之间的STM32F446xx外围寄存器访问差异,c,gcc,arm,embedded,cortex-m,C,Gcc,Arm,Embedded,Cortex M,我试图简单地点亮一个外部LED(连接到我的STM32F446RE的端口C引脚10)。我使用gcc arm none eabi 8-2019-q3-update for windows用于编译器,使用Keil uVision5 IDE用于板的闪烁/调试(Keil IDE还使用gcc编译器处理编译) 在下面的代码中,当使用structs引用GPIO和RCC外围寄存器(main的第二个“部分”)时,一切都能正常工作。RCC->AHB1ENR和GPIOC->MODER写入行正确更新相关内存地址的值,并且
RCC->AHB1ENR
和GPIOC->MODER
写入行正确更新相关内存地址的值,并且LED确实亮起
但是,当使用未引用的指针(main的第一个“部分”)时,LED不亮。调试此问题时,在执行*GPIOC\u MODER
和*RCC\u AHB1ENR
行之后,所有寄存器的内存位置都没有被写入
这两种方法的区别是什么?为什么一种有效而另一种无效?我已经用STM32F446xx数据表()对地址进行了三次检查,即使地址不正确,基于结构的方法也不应该起作用
#include <stdint.h>
/* General Purpose Input Output Registers, Address Range 0x4002 0000 - 0x4002 1FFF */
typedef struct
{
uint32_t volatile MODER; /* Offset: 0x00 (R/W) Mode Register */
uint32_t volatile OTYPER; /* Offset: 0x04 (R/W) Output Type Register */
uint32_t volatile OSPEEDR; /* Offset: 0x08 (R/W) Output Speed Register */
uint32_t volatile PUPDR; /* Offset: 0x0C (R/W) Pull-up/Pull-down Register */
uint32_t volatile IDR; /* Offset: 0x10 (R/W) Input Data Register */
uint32_t volatile ODR; /* Offset: 0x14 (R/W) Output Data Register */
uint32_t volatile BSRR; /* Offset: 0x18 (R/W) Bit Set/Reset Register */
uint32_t volatile LCKR; /* Offset: 0x1C (R/W) Configuration Lock Register */
uint32_t volatile AFRL; /* Offset: 0x20 (R/W) Alternate Function Low Register */
uint32_t volatile AFRH; /* Offset: 0x24 (R/W) Alternate Function High Register */
} GPIO_t;
#define GPIOA ((GPIO_t *)0x40020000)
#define GPIOB ((GPIO_t *)0x40020400)
#define GPIOC ((GPIO_t *)0x40020800)
#define GPIOD ((GPIO_t *)0x40020C00)
#define GPIOE ((GPIO_t *)0x40021000)
#define GPIOF ((GPIO_t *)0x40021400)
#define GPIOG ((GPIO_t *)0x40021800)
#define GPIOH ((GPIO_t *)0x40021C00)
/* Reset and Clock Control Registers (RCC), Address Range: 0x4002 3800 - 0x4002 3BFF */
typedef struct
{
uint32_t volatile CR; /* Offset: 0x00 (R/W) Clock Control Register */
uint32_t volatile PLLCFGR; /* Offset: 0x04 (R/W) PLL Configuration Register */
uint32_t volatile CFGR; /* Offset: 0x08 (R/W) Clock Configuration Register */
uint32_t volatile CIR; /* Offset: 0x0C (R/W) Clock Interrupt Register */
uint32_t volatile AHB1RSTR; /* Offset: 0x10 (R/W) AHB1 Peripheral Reset Register */
uint32_t volatile AHB2RSTR; /* Offset: 0x14 (R/W) AHB2 Peripheral Reset Register */
uint32_t volatile AHB3RSTR; /* Offset: 0x18 (R/W) AHB3 Peripheral Reset Register */
uint32_t volatile reserved0;
uint32_t volatile APB1RSTR; /* Offset: 0x20 (R/W) APB1 Peripheral Reset Register */
uint32_t volatile APB2RSTR; /* Offset: 0x24 (R/W) APB2 Peripheral Reset Register */
uint32_t reserved1[2];
uint32_t volatile AHB1ENR; /* Offset: 0x30 (R/W) AHB1 Peripheral Clock Enable Register */
uint32_t volatile AHB2ENR; /* Offset: 0x34 (R/W) AHB2 Peripheral Clock Enable Register */
uint32_t volatile AHB3ENR; /* Offset: 0x38 (R/W) AHB3 Peripheral Clock Enable Register */
uint32_t reserved2;
uint32_t volatile APB1ENR; /* Offset: 0x40 (R/W) APB1 Peripheral Clock Enable Register */
uint32_t volatile APB2ENR; /* Offset: 0x44 (R/W) APB1 Peripheral Clock Enable Register */
uint32_t reserved3[2];
uint32_t volatile AHB1LPENR; /* Offset: 0x50 (R/W) AHB1 Peripheral Clock Enable Lower Power Mode Register */
uint32_t volatile AHB2LPENR; /* Offset: 0x54 (R/W) AHB2 Peripheral Clock Enable Lower Power Mode Register */
uint32_t volatile AHB3LPENR; /* Offset: 0x58 (R/W) AHB3 Peripheral Clock Enable Lower Power Mode Register */
uint32_t reserved4;
uint32_t volatile APB1LPENR; /* Offset: 0x60 (R/W) APB1 Peripheral Clock Enable Lower Power Mode Register */
uint32_t volatile APB2LPENR; /* Offset: 0x64 (R/W) APB2 Peripheral Clock Enable Lower Power Mode Register */
uint32_t reserved5[2];
uint32_t volatile BDCR; /* Offset: 0x70 (R/W) Backup Domain Control Register */
uint32_t volatile CSR; /* Offset: 0x74 (R/W) Clock Control & Status Register */
uint32_t reserved6[2];
uint32_t volatile SSCGR; /* Offset: 0x80 (R/W) Spread Spectrum Clock Generation Register */
uint32_t volatile PLLI2SCFGR; /* Offset: 0x84 (R/W) PLLI2S Configuration Register */
uint32_t volatile PLLSAICFGR; /* Offset: 0x88 (R/W) PLLSAI Configuration Register */
uint32_t volatile DCKCFGR; /* Offset: 0x8C (R/W) Dedicated Clocks Configuration Register */
uint32_t volatile CKGATENR; /* Offset: 0x90 (R/W) Clocks Gated Enabled Register */
uint32_t volatile DCKCFGR2; /* Offset: 0x94 (R/W) Dedicated Clocks Configuration Register 2 */
} RCC_t;
#define RCC ((RCC_t *)0x40023800)
void main()
{
/* This section doesn't work */
uint32_t volatile * const GPIOC_MODER = (uint32_t *)0x40020800;
uint32_t volatile * const GPIOC_ODR = (uint32_t *)0x40020814;
uint32_t volatile * const RCC_AHB1ENR = (uint32_t *)0x40023830;
*GPIOC_MODER &= ~(0x1 << 21); //!# Enable clock to GPIO Port C
*GPIOC_MODER |= 0x1 << 20; //!# Clear bit 21 to put pin 10 into general purpose output mode
*RCC_AHB1ENR |= 0x1 << 2; //!# Set bit 20 to put pin 10 into general purpose output mode
while (1) {
*GPIOC_ODR |= 0x1 << 10; //!# Write a 1 to bit 10 (port 10) of GPIO Port C
}
/* This section does work */
RCC->AHB1ENR |= 0x1 << 2; //!# Enable clock to GPIO Port C
GPIOC->MODER &= ~(0x1 << 21); //!# Clear bit 21 to put pin 10 into general purpose output mode
GPIOC->MODER |= 0x1 << 20; //!# Set bit 20 to put pin 10 into general purpose output mode
while (1) {
GPIOC->ODR |= 0x1 << 10; //!# Write a 1 to bit 10 (port 10) of GPIO Port C
}
}
#包括
/*通用输入输出寄存器,地址范围0x4002 0000-0x4002 1FF*/
类型定义结构
{
uint32_t volatile MODER;/*偏移量:0x00(R/W)模式寄存器*/
uint32_t易失性OTYPER;/*偏移量:0x04(R/W)输出类型寄存器*/
uint32\u t易失性OSpeder;/*偏移量:0x08(R/W)输出速度寄存器*/
uint32\u t volatile PUPDR;/*偏移量:0x0C(R/W)上拉/下拉寄存器*/
uint32\u t易失性IDR;/*偏移量:0x10(R/W)输入数据寄存器*/
uint32_t易失性ODR;/*偏移量:0x14(R/W)输出数据寄存器*/
uint32_t易失性BSRR;/*偏移量:0x18(R/W)位设置/重置寄存器*/
uint32_t易失性LCKR;/*偏移量:0x1C(R/W)配置锁寄存器*/
uint32_t易失性AFRL;/*偏移量:0x20(R/W)备用功能低电平寄存器*/
uint32_t易失性AFRH;/*偏移量:0x24(R/W)备用功能高电平寄存器*/
}GPIO\t;
#定义GPIOA((GPIO_t*)0x40020000)
#定义GPIOB((GPIO_t*)0x40020400)
#定义GPIOC((GPIO_t*)0x40020800)
#定义GPIOD((GPIO_t*)0x40020C00)
#定义GPIOE((GPIO_t*)0x40021000)
#定义GPIOF((GPIO_t*)0x40021400)
#定义GPIOG((GPIO_t*)0x40021800)
#定义GPIOH((GPIO_t*)0x40021C00)
/*复位和时钟控制寄存器(RCC),地址范围:0x4002 3800-0x4002 3BFF*/
类型定义结构
{
uint32_t volatile CR;/*偏移量:0x00(R/W)时钟控制寄存器*/
uint32_t易失性PLLCFGR;/*偏移量:0x04(R/W)PLL配置寄存器*/
uint32_t volatile CFGR;/*偏移量:0x08(R/W)时钟配置寄存器*/
uint32_t volatile CIR;/*偏移量:0x0C(R/W)时钟中断寄存器*/
uint32_t易失性AHB1RSTR;/*偏移量:0x10(R/W)AHB1外围复位寄存器*/
uint32_t易失性AHB2RSTR;/*偏移量:0x14(R/W)AHB2外围重置寄存器*/
uint32_t易失性AHB3RSTR;/*偏移量:0x18(R/W)AHB3外围重置寄存器*/
uint32\u t挥发性储备;
uint32_t易失性APB1RSTR;/*偏移量:0x20(R/W)APB1外围复位寄存器*/
uint32_t易失性APB2RSTR;/*偏移量:0x24(R/W)APB2外围重置寄存器*/
uint32_t reserved1[2];
uint32\u t易失性AHB1ENR;/*偏移量:0x30(R/W)AHB1外围时钟启用寄存器*/
uint32_t易失性AHB2ENR;/*偏移量:0x34(R/W)AHB2外围时钟启用寄存器*/
uint32_t易失性AHB3ENR;/*偏移量:0x38(R/W)AHB3外围时钟启用寄存器*/
uint32_t储备2;
uint32\u t易失性APB1ENR;/*偏移量:0x40(R/W)APB1外围时钟启用寄存器*/
uint32_t易失性APB2ENR;/*偏移量:0x44(R/W)APB1外围时钟启用寄存器*/
uint32_t reserved3[2];
uint32\u t易失性AHB1LPENR;/*偏移量:0x50(R/W)AHB1外围时钟启用低功率模式寄存器*/
uint32_t易失性AHB2LPENR;/*偏移量:0x54(R/W)AHB2外围时钟启用低功率模式寄存器*/
uint32_t易失性AHB3LPENR;/*偏移量:0x58(R/W)AHB3外围时钟启用低功率模式寄存器*/
uint32_t保留4;
uint32\u t易失性APB1LPENR;/*偏移量:0x60(R/W)APB1外围时钟启用低功率模式寄存器*/
uint32_t易失性APB2LPENR;/*偏移量:0x64(R/W)APB2外围时钟启用低功率模式寄存器*/
uint32_t保留5[2];
uint32_t volatile BDCR;/*偏移量:0x70(R/W)备份域控制寄存器*/
uint32\u t易失性CSR;/*偏移量:0x74(R/W)时钟控制和状态寄存器*/
uint32_t保留6[2];
uint32_t易失性SSCGR;/*偏移量:0x80(R/W)扩频时钟生成寄存器*/
uint32_t易失性PLLI2SCFGR;/*偏移量:0x84(R/W)PLLI2S配置寄存器*/
uint32_t易失性PLLSAICFGR;/*偏移量:0x88(R/W)PLLSAI配置寄存器*/
uint32\u t易失性DCKCFGR;/*偏移量:0x8C(R/W)