历史上的今天
今天是:2024年10月19日(星期六)
2021年10月19日 | stm32专题三:位带操作—GPIO输出和输入
2021-10-19 来源:eefocus
位带操作其实很简单,就是把位带区某寄存器的特定位,用公式给映射到位带别名区的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专题四:启动文件分析
史海拾趣
|
百度的答案,还请大家深入说说: RFIC是RF System 里的Block做成IC ,,基本上成品就是IC ; 而RFID是Radio-frequency identification 是一个系统,有特定的规范。 二者是否有确定的包含与被包含的关系呢?… 查看全部问答> |
|
I2C_IOControl 传一个数组出来,老不成功,郁闷死了 BOOL I2C_IOControl( DWORD context, DWORD code, BYTE *pInBuffer, DWORD inSize, BYTE *pOutBuffer, DWORD outSize, DWORD *pOutSize ) 里面定义了一个BYTE *str;然后给他空间,也 ...… 查看全部问答> |
|
访问允许异常(section permission fault) Hi,Dear all, 我在使用Hms30c7202过程中遇到一个难题,我使用的内核是2.6.13.4,大多数能够正常启动运行,个别出现不能启动情况。打印DEBUG信息,非正常设备启动失败,打印: Kernel panic - not syncing: No init found. Try passi ...… 查看全部问答> |
|
安装CE6的SP1出错toolMsmCA(Error):Setup package issue or CoreCon。。。 安装CE6的SP1是出错 “ToolMsmCA(Error):Setup package issue or CoreCon DataStore corrupted:CDeviceSDKInstallShin Add/Remove failed.HR=0x80004005. 我之前装了VS2005。 这几天才装这个,不知怎么出错,安装进度停在Installing the Gene ...… 查看全部问答> |
|
各位,最近在开发一个驱动的时候需要检测内存泄漏,于是自己重载了new/delete,在win32下测了一下没问题,于是决定将其加入到当前的驱动下。可是,问题来了,总是出现LNK2005的错误,我查了一下这个错,应该是连接顺序的问题,出错信息显示在DDK中 ...… 查看全部问答> |
|
近来老板搞了点垃圾产品,在生产时用的是BSOB,但第二点不是翘线就是打不上,很多参数都用过了,不知还有哪里没想到的。求教怎样可以使ASM eagle60 W/B 的BSOB达到最佳。… 查看全部问答> |




