历史上的今天

今天是:2024年10月19日(星期六)

正在发生

2021年10月19日 | stm32专题三:位带操作—GPIO输出和输入

发布者:RadiantJourney 来源: 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专题四:启动文件分析

推荐阅读

器官芯片作为近年发展起来的一门新兴技术,曾在被2016年达沃斯论坛列为“十大新兴技术”之一,其并不是利用硅电子芯片进行人体器官模拟的模拟器,而是含有真正人体活体细胞的生物芯片,换句话说,器官芯片不是创造人类整个完整器官,而是仿真人体器官中的最小功能单元,实现药物或化学物质在非活体环境中,研究活体环境的交互反应,其在新药测试、干细胞研...
平台:iTOP-4412开发板本文介绍 uboot、Linux3.0.15 和 linux-3.5 内核、Android4.0.3 和Android4.2.2 编译环境的搭建以及编译。Uboot、Kernel 以及 Android 的编译环境看似复杂,用户只要抓住以下几个要点就可以了:第一:Uboot、Kernel 编译器。编译器在光盘中都有提供,在需要使用的步骤中,会说明编译器在光盘中的位置。第二:设置环境变量。Uboot、Ke...
综合中国台湾媒体报道,尽管华为海思 5nm 芯片代工在前三季度完成集中交货,第四季度在七大巨头的接力下,台积电 5nm 第四季度需求井喷。 这七大巨头除了大客户苹果直接包圆了华为空缺的产能,占比超过 50%,还有赛灵思、超微(AMD)、联发科、博通、比特大陆、英特尔。 据悉,5nm 制程在第三季度已经占到台积电营收的 8%,增长迅速。台积电预计...
台式万用表是常用的电阻测量仪器,但实际应用中万用表测量电阻的方法你都用对了么?下面安泰测试Agitek就给大家看看一些常见情形。Q1、2线 OR 4线怎么选?许多万用表包含2线和4线的测量法,如何判断在具体测量时使用哪种方法呢?通常只有在测量高于10欧姆的电阻值时,才应该使用2线方法,这是由于引线电阻的影响会明显增加误差(1%或以上)。图|2线和4线...

史海拾趣

问答坊 | AI 解惑

Verilog-A的模拟电路行为模型及仿真

Verilog-A的模拟电路行为模型及仿真 文章类别:通信电源   发表日期:2005-2-14  星期一        朱樟明,张春朋,杨银堂,付永朝   (西安电子科技大学微电子研究所,西安710071)    摘 要:分 ...…

查看全部问答∨

嵌入式系统及其应用开发

随着信息化技术的发展,嵌入式系统已经成为当前IT产业界一个非常热门的话题。因其高效、低成本、高可靠性、丰富的代码以及应用程序可扩展性、可移植性等一系列优点,目前已越来越成为工业系统和民用系统的主力军,尤其在信息化产品中,越来越多地应 ...…

查看全部问答∨

我的第二版示波器

我的第二版示波器…

查看全部问答∨

09年大赛征题原件

本帖最后由 paulhyde 于 2014-9-15 09:08 编辑 09年大赛征题原件  …

查看全部问答∨

修改内核函数遇到问题

KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);           关闭写保护                     fun_addr = 0x90;    //fu ...…

查看全部问答∨

PDA如何与Oracle同步

目前PC上是Oracle数据库,PDA要怎样才能和Oracle同步(如sqlce 和 SqlServer一样)。…

查看全部问答∨

求DAC5573中文资料

本帖最后由 dontium 于 2015-1-23 13:11 编辑 用MCU通过I2C与DAC5573通信,DAC5573无输出。 …

查看全部问答∨

ucos比较迷茫的问题

近一段时间在看ucos,有一点一直不明白,就是在ucos中怎样使用单片机的中断??时钟节拍中断用汇编写的,难道其他所有中断都需要在启动文件中用汇编写吗???请高手指点!!!!…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

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

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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