之前为大家分享的《Cortex-M位带操作的原理》,虽然现在不常用位带操作了,但里面很多知识点值得学习和了解。
指针变量及例子
位带操作牵涉到的一个重要知识点就是指针变量。
这种位带映射操作,就是操作映射过后的地址,其实就是操作指针变量(存放地址的变量)。
指针变量是一种特殊的变量,它不同于一般的变量,一般变量存放的是数据本身,而指针变量存放的是数据的地址。《摘自百度百科【指针变量】》
指针变量的例子:
int main(void) { uint32_t *p; p = (uint32_t *)(0x42210184); System_Initializes(); while(1) { *p = 0; TIMDelay_Nms(500); *p = 1; TIMDelay_Nms(500); } }
上面例子中给p指针变量赋的值是“0x42210184”,只是强制转换成(uint32_t *)这种指针类型。
而*p = 0;代表该地址上的数据值为0;也就是上面说的该地址存放的数据为0;
前面有一个朋友问过我关于指针变量的问题,看到这里,相信你应该知道使用指针变量,直接打印指针就可以判断指针是否越界。
指针变量---位带操作
上面代码中“0x42210184”代表STM32F103系列芯片中PA1的位带别名地址(就是映射过去的地址),截一个图,大家看看:
提示:上图中对p的赋值,其实是一样的(在STM32中),都是0x42210184。
结合公式理解:之前文章《位带操作原理》列出了关于片上外设区计算公式:AliasAddr = 0x42000000+(A-0x40000000)*32 + n*4
对比截图中第一个p赋的值,就是片上外设的计算公式。第二个p只是对代码优化了:“&”到“-”的优化,可以看编译器相关手册。
第4个p就是上一节代码中值,有没有发现,位带操作其实就操作指针变量啊?
这样相比读出寄存器,再&或者|再写入寄存器的效率要高多啦?
位带别名区最低有效位
有朋友发现,*p = 0;这样操作对地址0x42210184(PA1输出)写入0,PA1输出低。假如我写入0x10,那么PA1输出多少呢?
答案:输出低。
原因在于:在位带区中,每个比特都映射到别名地址区的一个字只有 LSB 有效,也就是最低一位有效。
位带操作另一种宏定义
有通过之前的两个公式,可以推出下图的公式:
上面框起来的定义适合RAM和外设两种,假如定义一个LED为PA1,只需要将PA1相关参数传入即可。
LED另外一种定义:#define LED BIT_ADDR((GPIOA_BASE + 12), 1)
这种定义需要注意:+12,其实是ODR相对GPIOA的基地址的偏移地址。
我曾在这里遇到的坑:我将STM32F1的移植到F4上,出现了问题,我找了半天才发现由于这个偏移地址不一样导致的。
STM32F1的ODR偏移是12,而F4的ODR偏移是20。所以,建议大家使用GPIOA->ODR这种方式。(不管是标准外设库还是HAL库都有这样定义)。
------------ END ------------
上一篇:针对单片机开发的轻量级OTA组件
下一篇:一文带你掌握串口通信
设计资源 培训 开发板 精华推荐
- LTC3400ES6-1 单节电池至 3.3V 同步升压转换器的典型应用电路
- UNO下载器|TTL多口调试下载器
- NCP1075PSRGEVB,初级侧控制,10 瓦,离线反激评估板
- DC941A,演示电路采用 LTC2482、16 位高性能 DS 模数转换器
- 使用 IXYS 的 MX846 的参考设计
- 1.3寸 IIC接口的OLED转接板-适配市面常见尺寸(已验证)
- 基于LNBH25的单个LNB电源和控制IC DiSEqC 2.0兼容
- MPC8308RDB: MPC8308-RDB参考平台
- 【广西师大校赛】FM调频接收机灵敏度测试装置
- LT3080-1 的典型应用 - 可并联 1.1A 可调单电阻器低压差稳压器
- 免费申请测评:超小型 Linux 开发套件:Quantum Tiny Linux(带 SoM 和扩展板)
- 邀您观看 微信直播:户外照明智能互连解决方案 让TE连接光明与智能未来
- ADI有奖下载活动之11 ADI锂电池测试设备解决方案
- STM32 线上技术日开播【40块新品开发板等你抽】|解读多款新品技术及应用
- 你晒单我送礼,晒TI样片订单即可赢好礼!
- 看是德科技汽车电子精彩专题,为你的出行安全打call, 下载赢好礼!
- 直播已结束【借助 TI DLP 技术,开始您的下一代4K显示应用设计】
- TI DLP知识有奖快问快答排位赛
- 有奖直播:安森美汽车热管理e- Compressor 应用
- 中国版BeagleBone Black 春节不打烊,火爆开团!