stm32专题三:位带操作—GPIO输出和输入

发布者:RadiantJourney最新更新时间:2021-10-19 来源: eefocus关键字:stm32  位带操作  GPIO 手机看文章 扫描二维码
随时随地手机看文章

位带操作其实很简单,就是把位带区某寄存器的特定位,用公式给映射到位带别名区的32位地址上,该地址在编译器看来是个立即数,因此需要强制类型转换成32位地址指针,最后对指针取值操作。


特别值得注意的是,在强制类型转换成地址时,一定要加volatile关键词,不然一定会被编译器level-3优化掉,导致程序出错。博主一开始是直接使用(unsigned int *),然后在这里调试了很久,一直没发现问题所在,突然想到三级优化,加上volatile后程序正常执行。


以下是位带宏定义和输入—输出测试代码,


#include "stm32f10x.h"

#include "bsp_led.h"

#include "bsp_key.h"

 

/** 

  * @brief 位带操作

  * @cal   ((addr & 0xF0000000) + 0X02000000 + ((addr & 0x00FFFFFF) << 5) + ((bitnum) << 2))

  * @note  上述公式将位带区的寄存器addr第bitnum位,转化为位带别名区的一个32位地址

  * @attention 强制类型时一定要加volatile,不然会被level-3优化掉(ODR正常,IDR错误)

  */

 

// 位带输出

#define GPIOA_ODR_Addr (GPIOA_BASE + 0X0C)

#define GPIOB_ODR_Addr (GPIOB_BASE + 0X0C)

#define GPIOC_ODR_Addr (GPIOC_BASE + 0X0C)

#define GPIOD_ODR_Addr (GPIOD_BASE + 0X0C)

#define GPIOE_ODR_Addr (GPIOE_BASE + 0X0C)

#define GPIOF_ODR_Addr (GPIOF_BASE + 0X0C)

#define GPIOG_ODR_Addr (GPIOG_BASE + 0X0C)

 

#define PAout(n) *(volatile unsigned int *)((GPIOA_ODR_Addr & 0xF0000000) + 0X02000000 + ((GPIOA_ODR_Addr & 0x00FFFFFF) << 5) + ((n) << 2))

#define PBout(n) *(volatile unsigned int *)((GPIOB_ODR_Addr & 0xF0000000) + 0X02000000 + ((GPIOB_ODR_Addr & 0x00FFFFFF) << 5) + ((n) << 2))

#define PCout(n) *(volatile unsigned int *)((GPIOC_ODR_Addr & 0xF0000000) + 0X02000000 + ((GPIOC_ODR_Addr & 0x00FFFFFF) << 5) + ((n) << 2)) 

#define PDout(n) *(volatile unsigned int *)((GPIOD_ODR_Addr & 0xF0000000) + 0X02000000 + ((GPIOD_ODR_Addr & 0x00FFFFFF) << 5) + ((n) << 2))

#define PEout(n) *(volatile unsigned int *)((GPIOE_ODR_Addr & 0xF0000000) + 0X02000000 + ((GPIOE_ODR_Addr & 0x00FFFFFF) << 5) + ((n) << 2))

#define PFout(n) *(volatile unsigned int *)((GPIOF_ODR_Addr & 0xF0000000) + 0X02000000 + ((GPIOF_ODR_Addr & 0x00FFFFFF) << 5) + ((n) << 2))

#define PGout(n) *(volatile unsigned int *)((GPIOG_ODR_Addr & 0xF0000000) + 0X02000000 + ((GPIOG_ODR_Addr & 0x00FFFFFF) << 5) + ((n) << 2))

 

// 位带输入

#define GPIOA_IDR_Addr (GPIOA_BASE + 0X08)

#define GPIOB_IDR_Addr (GPIOB_BASE + 0X08)

#define GPIOC_IDR_Addr (GPIOC_BASE + 0X08)

#define GPIOD_IDR_Addr (GPIOD_BASE + 0X08)

#define GPIOE_IDR_Addr (GPIOE_BASE + 0X08)

#define GPIOF_IDR_Addr (GPIOF_BASE + 0X08)

#define GPIOG_IDR_Addr (GPIOG_BASE + 0X08)

 

#define PAin(n) *(volatile unsigned int *)((GPIOA_IDR_Addr & 0xF0000000) + 0X02000000 + ((GPIOA_IDR_Addr & 0x00FFFFFF) << 5) + ((n) << 2))

#define PBin(n) *(volatile unsigned int *)((GPIOB_IDR_Addr & 0xF0000000) + 0X02000000 + ((GPIOB_IDR_Addr & 0x00FFFFFF) << 5) + ((n) << 2))

#define PCin(n) *(volatile unsigned int *)((GPIOC_IDR_Addr & 0xF0000000) + 0X02000000 + ((GPIOC_IDR_Addr & 0x00FFFFFF) << 5) + ((n) << 2))

#define PDin(n) *(volatile unsigned int *)((GPIOD_IDR_Addr & 0xF0000000) + 0X02000000 + ((GPIOD_IDR_Addr & 0x00FFFFFF) << 5) + ((n) << 2))

#define PEin(n) *(volatile unsigned int *)((GPIOE_IDR_Addr & 0xF0000000) + 0X02000000 + ((GPIOE_IDR_Addr & 0x00FFFFFF) << 5) + ((n) << 2))

#define PFin(n) *(volatile unsigned int *)((GPIOF_IDR_Addr & 0xF0000000) + 0X02000000 + ((GPIOF_IDR_Addr & 0x00FFFFFF) << 5) + ((n) << 2))

#define PGin(n) *(volatile unsigned int *)((GPIOG_IDR_Addr & 0xF0000000) + 0X02000000 + ((GPIOG_IDR_Addr & 0x00FFFFFF) << 5) + ((n) << 2))

 

 

void delay(uint32_t count);

 

int main(void)

{

LED_GPIO_Config();

KEY_GPIO_Config();

 

#if 0

while (1)

{

// 位带输出测试

PBout(1) = 1;

delay(0XFFFFF);

PBout(1) = 0;

delay(0XFFFFF);

}

#else

while (1)

{

// 位带输入测试

if (PAin(0) == KEY_ON)

{

while (PAin(0) == KEY_ON);

LED_B_OFF;

LED_R_TOGGLE;

}

if (PCin(13) == KEY_ON)

{

while (PCin(13) == KEY_ON);

LED_R_OFF;

LED_B_TOGGLE;

}

}

#endif

}

 

void delay(uint32_t count)

{

for (; count != 0; count--);

}


关键字:stm32  位带操作  GPIO 引用地址:stm32专题三:位带操作—GPIO输出和输入

上一篇:stm32专题二:GPIO输入—按键检测
下一篇:stm32专题四:启动文件分析

推荐阅读最新更新时间:2024-11-10 10:58

stm32红外遥控
HS0038B http://www.51hei.com/stm32/3589.html 我用的红外遥控是使用的NEC协议,即使用PWM来调制发送的信息 NEC协议,其特征如下: 1、8位地址和8位指令长度; 2、地址和命令2次传输(确保可靠性) 3、PWM脉冲位置调制,以发射红外载波的占空比代表“0”和“1”; 4、载波频率为38Khz; 5、位时间为1.125ms或2.25ms; NEC码的位定义:一个脉冲对应560us的连续载波,一个逻辑1传输需要2.25ms(560us脉冲+1680us低电平),一个逻辑0的传输需要1.125ms(560us脉冲+560us低电平)。而遥控接收头在收到脉冲的时候为低电平,
[单片机]
<font color='red'>stm32</font>红外遥控
STM32 74HC595驱动程序
以下为.h文件: #ifndef __74HC595_H__ #define __74HC595_H__ #include stm32f10x.h #define SHCP_GPIO_PORT GPIOA #define SHCP_GPIO_CLK RCC_APB2Periph_GPIOA #define SHCP_GPIO_PIN GPIO_Pin_1 #define STCP_GPIO_PORT GPIOA #define STCP_GPIO_CLK RCC_APB2Periph_GPIOA #define STCP_GPIO_PIN
[单片机]
<font color='red'>STM32</font> 74HC595驱动程序
STM32使用模拟IIC实现24C02读取
1.与硬件IIC的比较 1.1.使用灵活 可使用任意2个IO口实现,不用受芯片管脚限制; 1.2.速率快 通过调整延时,可以实现超过400k的速率,实际测试最大速率接近800k; 1.3.容错性强 硬件IIC在通信出错后,无法自行恢复,模拟IIC则可以迅速恢复; 2.底层接口函数 2.1. I2C_Start static uint8_t I2C_Start(void) { SDA_H; //拉高数据线 SCL_H; //拉高时钟线 I2C_DELAY; if(SDA_read == RESET) //SDA线为低电平则总线忙,退出 { return I2C_BUS_BUSY; } S
[单片机]
4*4键盘程序代码 基于STM32
这是自己写的扫描第一行按键的程序代码。 PE的位8~位11设置为下拉输入。 PE的位12~位15设置为推挽输出 其中PE的位11是4*4键盘的第一列,PE的为键盘的第一行。 先将第一行设置为高电平,检测列中是否有高电平 u8 KEY_Scan(u8 mode) { staticu8 key_up=1;//按键按松开标志 if(mode)key_up=1; //支持连按 GPIO_SetBits(GPIOE,GPIO_Pin_15); if(key_up&&( (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin
[单片机]
stm32专题十一:USART(四)USART编程
stm32的串口USART编程要点 先初始化串口所用到的GPIO; 初始化串口,配置pUSART_InitTypeDef结构体; 配置中断NVIC(接收中断,中断优先级); 使能串口; 编写发送和接收函数; 编写中断服务函数; 接下在看具体的代码实现过程: USART初始化配置函数,不难但是过程挺多的,容易遗漏,代码如下: // 串口1 USART1 #define DEBUG_USARTx USART1 #define DEBUG_USART_CLK RCC_APB2Periph_USART1 #define DEBUG_USART_APBxClkCmd RCC_APB2PeriphCloc
[单片机]
<font color='red'>stm32</font>专题十一:USART(四)USART编程
stm32 SysTick系统定时器
它是一个24位向下递减的定时器,每计数一次所需时间为1/SYSTICK,SYSTICK是系统定时器时钟,它可以直接取自系统时钟,还可以通过系统时钟8分频后获取 当定时器计数到0时,将从LOAD 寄存器中自动重装定时器初值,重新向下递减计数 如果开启SysTick中断的话,当定时器计数到0,将产生一个中断信号 void SysTick_Init(u8 SYSCLK) { SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); fac_us=SYSCLK/8; //1us次数 fac_ms=(u16)fac_us*1000; //1ms次
[单片机]
<font color='red'>stm32</font> SysTick系统定时器
STM32系列命名规则
例如:STM32F103C6T7xxx STM32 F 103 C 6 T 7 xxx 第1部分:产品系列名,固定为STM32 第2部分:产品类型;F表示这是Flash产品,目前没有其它选项 第3部分:产品子系列;103表示增强型产品,101表示基本型产品 105表示集成一个全速USB 2.0 Host/Device/OTG接口和两个具有先进过滤功能的CAN2.0B控制器, 107表示在STM32F105系列基础增加一个10/100以太 网媒体访问控制器(MAC),互联型产品, 第4部分:管脚数目; T=36脚; C=48脚; R=64脚;V=100脚; Z=144脚 第5部分:闪存存储器容量: 6=32K字节;8=
[单片机]
调试器不能连接到STM32的问题与解决办法
简介:很多人都碰到过调试器不能连接到STM32的问题,不管是IAR的J-Link还是Keil的ULink,或者是ST的ST-Link。出现这个问题时,调试软件会提示不能建立与Cortex-M3的连接,或提示不能下载程序,或提示找不到要调试的设备等。 这样的问题都是发生在调试那些可以在CPU不干预的时候自动运行的模块、或在调试低功耗模式的程序的时候。 所谓“可以在CPU不干预的时候自动运行的模块”包括:DMA、定时器、连续转换模式下的ADC、看门狗等模块。 这个问题的根源是: 1)调试器需要在RAM内执行一段程序,对Flash进行擦写操作,如果不停止这些自动运行的模块,它们会干扰程序在RAM中的执行,致使下载失败。比
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved