我对STM32所用位带操作宏的超详细剖析、优势分析及应用推广探索研究(持续更新,欢迎讨论交流)

2019-07-20 23:21发布

本帖最后由 warship 于 2018-7-16 19:56 编辑

在原子例程的sys.h中,使用宏定义建立了位带操作的基础,
使得操作IO端口可以像51一样实现位操作。
其实深入了解了位带操作的原理,几乎就可以实现对STM32所有外设寄存器的访问,
极端情况下,什么库函数版本,什么寄存器版本都可以不用,直接精准地操控所有寄存器的每一位的读写!!!

知道了STM32将所有外设寄存器的每一位都建立了位带别名区,
你只要再花一点点时间,彻底搞明白下面的三句宏定义,位带操作就都不在话下了:
#define BITBAND(addr, bitnum)          ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr)                *((volatile unsigned long  *)(addr))
#define BIT_ADDR(addr, bitnum)       MEM_ADDR(BITBAND(addr, bitnum))



************************************************************************************************
注:本文后文所探索的寄存器位段操作宏定义包含在另文所附范例(外部中断试验的工程包)中,并随时更新。
有需要研究探讨的网友,可移步下载http://www.openedv.com/forum.php ... d=274724&extra=


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
49条回答
warship
1楼-- · 2019-07-25 16:06
d1z1y2 发表于 2018-7-9 12:37
以前的RAM都是省着用,标志位全部是定义成bit,不像现在的单片机资源那么丰富,只要能快速的把项目做出来, ...

有道理,一般人可以不用研究,
但官方的库还是要讲究效率的,个人觉得。
warship
2楼-- · 2019-07-25 17:11
 精彩回答 2  元偷偷看……
warship
3楼-- · 2019-07-25 18:16
不过,位带操作的局限性是如果同时给多个位赋值,就得分开操作各个位,这时候就不如直接操作寄存器本身了。
但是没有关系,可以采取操作单一比特时用位带,两个以上时仍读写整个寄存器的混合编程方式。
我试着对原子寄存器版本中的系统时钟初始化函数局部使用位带操作进行改写。
原版是:
void Stm32_Clock_Init(u8 PLL)
{
        unsigned char temp=0;   
        MYRCC_DeInit();                  //复位并配置向量表
        RCC->CR|=0x00010000;  //外部高速时钟使能HSEON
        while(!(RCC->CR>>17));//等待外部时钟就绪
        RCC->CFGR=0X00000400; //APB1=DIV2;APB2=DIV1;AHB=DIV1;
        PLL-=2;                                  //抵消2个单位(因为是从2开始的,设置0就是2)
        RCC->CFGR|=PLL<<18;   //设置PLL值 2~16
        RCC->CFGR|=1<<16;          //PLLSRC ON
        FLASH->ACR|=0x32;          //FLASH 2个延时周期
        RCC->CR|=0x01000000;  //PLLON
        while(!(RCC->CR>>25));//等待PLL锁定
        RCC->CFGR|=0x00000002;//PLL作为系统时钟         
        while(temp!=0x02)     //等待PLL作为系统时钟设置成功
        {   
                temp=RCC->CFGR>>2;
                temp&=0x03;
        }   
}
warship
4楼-- · 2019-07-25 22:21
 精彩回答 2  元偷偷看……
gotofly21
5楼-- · 2019-07-25 23:37
本帖最后由 gotofly21 于 2018-7-9 17:06 编辑

说道寄存器位寻找,好像有一回我用位寻址设置和清除 TIMER的CEN,结果老是出错(大部分时候也对)。(关键有时候要单脉冲,有时候不需要单脉冲,就是想着需要单脉冲只要把单脉冲位赋值一次,后面就不管这个位,只要赋值cen就启动)。后来还是用CR1整体赋值就不出错了。也没时间查查为什么。
warship
6楼-- · 2019-07-26 04:54
gotofly21 发表于 2018-7-9 16:58
说道寄存器位寻找,好像有一回我用位寻址设置和清除 TIMER的CEN,结果老是出错。后来还是用CR1整体赋值就不 ...

那可能是别名地址没有计算正确,
对照寄存器基址、偏移量和比特位,
编出一份别名地址宏定义的头文件后,
就是想出错也不容易的,哈哈。

一周热门 更多>