最近由于在学习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()
{
;
}
以上代码便可以实现流水灯例子。
上一篇:STM32F4外设驱动系列之GPIO
下一篇:STM32学习笔记之GPIO(二)
推荐阅读最新更新时间:2024-11-09 18:26
设计资源 培训 开发板 精华推荐
- TWR-K24F120M、Kinetis K24 120-MHz MCU 塔式系统模块,具有高 RAM 密度,适用于连接和传感器融合应用
- 基于HSOP8封装的4A LED2001具有调光功能的HB LED驱动器
- LT1021DCS8-10 具有升压输出电流和电流限制的电压基准的典型应用
- STR-ADAS-PREREGULATOR-GEVK,灵活的 ADAS 电源解决方案开发套件
- #第五届立创电子设计大赛#四轴无人机
- 使用 Analog Devices 的 LTC6404CUD-2 的参考设计
- DC957A,使用 LTC3785、3.3V、3.0A 高效率同步降压-升压转换器的演示板
- LTC6253 的典型应用 - 720MHz、3.5mA 双功率高效轨至轨 I/O 运算放大器
- 使用 LTC2380HMS-16、16 位、2Msps、低功耗 SAR ADC 的典型应用
- USB 电源 2.0
- 已结束|Maxim IO-Link通信协议设计方案详解,5大优势助你轻松联网!
- 感恩季 送礼季!EEWORLD陪你玩着游戏奔新年
- 3.5\"嵌入式主板给力开团 仅售599元包邮!
- 【TI 嵌入式研讨会集锦】小站添加了很多新内容,欢迎提货!
- 齐分享,月月有奖第25期活动华丽升级来袭
- 有奖直播:如何利用瑞萨电子的GreenPAK™平台优化混合信号电路设计
- STM32H7R/S 高性能MCU 开启全新的创新机遇!答题好礼~还有开发板等你拿!
- 【世健的ADI之路主题游】 第三站:了解物联网前沿器件与方案,打卡赢Kindle、《新概念模拟电路》
- 选你所爱,TI 19款模拟芯片超低价团购!
- Silicon Labs BG22-EK4108A 开发套件 用科技连接未来 申请进行时!