位带操作其实很简单,就是把位带区某寄存器的特定位,用公式给映射到位带别名区的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专题四:启动文件分析
推荐阅读
史海拾趣
随着公司规模的扩大和业务的拓展,Chesivale Electronics公司开始积极寻求与其他企业的合作机会。公司高层通过参加行业展览、举办商务洽谈会等方式,与多家知名企业建立了紧密的合作伙伴关系。这些合作不仅为公司带来了更多的业务机会和资源支持,也提升了公司在行业内的知名度和影响力。通过与合作伙伴的共同努力,Chesivale Electronics公司在市场上取得了显著的竞争优势。
ETERNA公司起源于1856年,由格斯塔夫·罗斯切尔德和约翰·乌尔里希在瑞士的圣伊米尔创立。自成立之初,ETERNA便以精湛的制表工艺和不懈的创新精神闻名于世。公司不断推出具有划时代意义的腕表产品,其中最具代表性的是其“五点星座”设计,这一设计成为了品牌的象征,并引领了制表业的新潮流。ETERNA通过不断的技术创新和设计突破,逐渐在电子行业中崭露头角。
随着全球环保意识的不断提高,电子行业对环保材料的需求也日益增长。CUI公司敏锐地抓住了这一市场机遇,积极投入研发,成功开发出了一种绿色环保型的碘化亚铜生产工艺。这种工艺不仅降低了生产过程中的能耗和排放,而且提高了产品的纯度和质量。通过推广这一工艺,CUI公司不仅赢得了客户的青睐,也为行业的绿色发展做出了积极贡献。
在快速发展的同时,Aavid Niagra公司始终关注企业社会责任和可持续发展。公司积极参与环保事业,推广绿色生产和消费理念。同时,公司还注重员工培训和福利保障,为员工创造一个良好的工作环境和发展空间。这些举措不仅提升了公司的社会形象,也为公司的长远发展奠定了坚实的基础。
这些故事框架主要围绕公司的初创、技术创新、全球化战略、行业变革应对以及企业社会责任等关键节点进行构建。您可以根据Aavid Niagra公司的实际情况和公开资料,对每个故事进行具体化和个性化的描述,以确保故事的准确性和可信度。
在激烈的市场竞争中,Arima Lasers Corp始终保持着创新的步伐。公司不断投入研发资源,探索激光技术在各个领域的应用潜力。其中,一项关于激光通信技术的创新项目引起了业界的广泛关注。这项技术利用激光束进行高速数据传输,具有传输速率快、安全性高等优点。随着该技术的商业化应用,Arima Lasers Corp在通信领域取得了重大突破,引领了市场变革的潮流。
Verilog-A的模拟电路行为模型及仿真 文章类别:通信电源 发表日期:2005-2-14 星期一 朱樟明,张春朋,杨银堂,付永朝 (西安电子科技大学微电子研究所,西安710071) 摘 要:分 ...… 查看全部问答∨ |
随着信息化技术的发展,嵌入式系统已经成为当前IT产业界一个非常热门的话题。因其高效、低成本、高可靠性、丰富的代码以及应用程序可扩展性、可移植性等一系列优点,目前已越来越成为工业系统和民用系统的主力军,尤其在信息化产品中,越来越多地应 ...… 查看全部问答∨ |
近一段时间在看ucos,有一点一直不明白,就是在ucos中怎样使用单片机的中断??时钟节拍中断用汇编写的,难道其他所有中断都需要在启动文件中用汇编写吗???请高手指点!!!!… 查看全部问答∨ |
设计资源 培训 开发板 精华推荐
- 报名观看TI 嵌入式处理器主题月直播,涨姿势还能拿全勤奖!
- ST直播主题:高度灵活的、易用的、可定制化的协议栈--BlueNRG-LP 协议栈介绍
- 【EEWORLD大学堂】玩转LaunchPad及TI MSP430G2XX系列超值单片机!!!
- 意法半导体工业峰会2023即将开启!报名、参会均有礼!
- 直播报名:TI 用于感测应用、带可配置信号链元素的新型MSP430™ MCU,报名直播赢双重好礼!
- 【TI 教室】学电源,晒成绩,挖楼有礼!
- 下载Intel白皮书 赢精彩好礼
- 直播已结束【用于光伏逆变器/储能系统的欧姆龙继电器 /开关/连接器解决方案】
- 【EEWORLD第十届社区明星人物】12月明星人物