STM32F系列ARM Cortex-M3核微控制器基础之系统时钟二

  STM32F系列ARM Cortex-M3核微控制器基础之系统时钟
问题一:STM32 BIT_BAND 位段位带别名区使用:什么是位段、位带别名区? 它有什么好处? 
记得MCS51吗? MCS51就是有位操作,以一位(BIT)为数据对象的操作,MCS51可以简单的将P1口的第2位独立操作: P1.2=0;P1.2=1 ; 就是这样把P1口的第三个脚(BIT2)置0置。而现在STM32的位段、位带别名区就为了实现这样的功能。对象可以是SRAM,I/O外设空间。实现对这些地方的某一位的操作。 它是这样的。在寻址空间(32位地址是 4GB )另一地方,取个别名区空间,从这地址开始处,每一个字(32BIT)就对应SRAM或I/O的一位。 这样呢,1MB SRAM就 可以有32MB的对应别名区空间,就是1位膨胀到32位(1BIT 变为1个字)。我们对这个别名区空间开始的某一字操作,置0或置1,就等于它映射的SRAM或I/O相应的某地址的某一位的操作。  简单来说,可以把代码缩小, 速度更快,效率更高,更安全。一般操作要6条指令,而使用 位带别名区只要4条指令。一般操作是  读-改-写  的方式, 而位带别名区是 写 操作。防止中断对读-改-写  的方式的影响。 
  CM3支持了位带操作(bit_band),可以使用普通的加载/存储指令来对单一的比特进行读写。CM3中有两个区中实现了位带。其中一个是SRAM 区的最低1MB 范围,第二个则是片内外设区的最低1MB 范围。这两个区中的地址除了可以像普通的RAM 一样使用外,它们还都有自己的“位带别名区”,位带别名区把每个比特膨胀成一个32 位的字 每个比特膨胀成一个32 位的字,就是把  1M  扩展为 32M ,于是;RAM地址 0X200000000(一个字节)扩展到8个32 位的字,它们是:0X220000000 ,0X220000004,0X220000008,0X22000000C,0X220000010,0X220000014, 0X220000018,0X22000001C 。支持位带操作的两个内存区的范围是:0x2000_0000‐0x200F_FFFF(SRAM 区中的最低1MB)0x4000_0000‐0x400F_FFFF(片上外设区中的最低1MB)。

对SRAM 位带区的某个比特,记它所在字节地址为A,位序号为n(0<=n<=7),在别名区的地址为:AliasAddr= 0x22000000 +((A‐0x20000000)*8+n)*4 =0x22000000+ (A‐0x20000000)*32 + n*4。对于片上外设位带区的某个比特,记它所在字节的地址为A,位序号为n(0<=n<=7),则该比特在别名区的地址为:AliasAddr= 0x42000000+((A‐0x40000000)*8+n)*4 =0x42000000+ (A‐0x40000000)*32 + n*4。上式中,“*4”表示一个字为4 个字节,“*8”表示一个字节中有8 个比特。
把“位带地址+位序号”转换别名地址宏
#define  BITBAND(addr, bitnum) ((addr & 0xF000 0000)+0x200 0000+((addr &0xF FFFF)<<5)+(bitnum<<2)),
注:addr & 0xF000 0000取出0x2000 0000或0x4000 0000高位,addr &0xF FFFF取出bit-band区地址变化的部分
把该地址转换成一个指针,并解索引
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr))     
使用:
MEM_ADDR(BITBAND( (u32)&CRCValue,1)) = 0x1;




对库函数中的该部分地址的组织规则的探讨:


第一次划分:
#define FLASH_BASE                ((uint32_t)0x08000000) /*!< FLASH base address in the alias region */
#define SRAM_BASE                 ((uint32_t)0x20000000) /*!< SRAM base address in the alias region */
        //别名区SRAM基地址
#define PERIPH_BASE              ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */
        //别名区外设基地址
#define SRAM_BB_BASE          ((uint32_t)0x22000000) /*!< SRAM base address in the bit-band region */
        //位带区SRAM基地址
#define PERIPH_BB_BASE       ((uint32_t)0x42000000) /*!< Peripheral base address in the bit-band region */
        //位带区外设基地址
#define FSMC_R_BASE             ((uint32_t)0xA0000000) /*!< FSMC registers base address */

第二次划分
 /*!< Peripheral memory map 外设存储映像*/
#define APB1PERIPH_BASE       PERIPH_BASE                                                     //APB1总线基地址((uint32_t)0x4000 0000)
#define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)                              //APB2总线基地址((uint32_t)0x4001 0000)
#define AHBPERIPH_BASE         (PERIPH_BASE + 0x20000)                                //AHB 总线基地址((uint32_t)0x4002 0000)

第三次划分
#define TIM2_BASE                       (APB1PERIPH_BASE + 0x0000)                                 //TIM2定时器基地址((uint32_t)0x4000 0000)
#define TIM3_BASE                       (APB1PERIPH_BASE + 0x0400)                                 //TIM3定时器基地址((uint32_t)0x4000 0400)
#define TIM4_BASE                       (APB1PERIPH_BASE + 0x0800)                                 //TIM4定时器基地址((uint32_t)0x4000 0800)
#define TIM5_BASE                       (APB1PERIPH_BASE + 0x0C00)                                //TIM5定时器基地址((uint32_t)0x4000 0C00)
#define TIM6_BASE                       (APB1PERIPH_BASE + 0x1000)                                 //TIM6定时器基地址((uint32_t)0x4000 1000)
#define TIM7_BASE                       (APB1PERIPH_BASE + 0x1400)                                 //TIM7定时器基地址((uint32_t)0x4000 1400)
#define TIM12_BASE                    (APB1PERIPH_BASE + 0x1800)
#define TIM13_BASE                    (APB1PERIPH_BASE + 0x1C00)
#define TIM14_BASE                    (APB1PERIPH_BASE + 0x2000)
#define RTC_BASE                       (APB1PERIPH_BASE + 0x2800)                                 //RTC基地址       ((uint32_t)0x4000 2800)
#define WWDG_BASE                  (APB1PERIPH_BASE + 0x2C00)                            //窗口看门狗基地址((uint32_t)0x4000 2C00)
#define IWDG_BASE                     (APB1PERIPH_BASE + 0x3000)                               //独立看门狗基地址((uint32_t)0x4000 3000)
......
#define RCC_BASE              (AHBPERIPH_BASE + 0x1000)                                  //复位和时钟控制基地址((uint32_t)0x4002 1000)

下面是各寄存器的地址参考:




我们可以看到固件库中的外设地址宏定义是按照先整体后部分的模式来组织的。 先定义在存储器中外设别名和位带的基地址,然后在外设别名区此基础上分割出AHB,APB1,APB2的基地址。最后对各个总线下挂载的外设寄存器的基地址进行宏定义。

固件V3.5.0中对位带操作的使用:
/* ------------ RCC registers bit address in the alias region ----------- */   
//复位和时钟控制寄存器别名区位地址
#define RCC_OFFSET                (RCC_BASE - PERIPH_BASE)                          //RCC寄存器组在外设存储映像中的偏移
//RCC_BASE = (AHBPERIPH_BASE + 0x1000) AHBPERIPH_BASE = (PERIPH_BASE + 0x20000)
//PERIPH_BASE = ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */
//RCC_BASE = ((uint32_t)0x40021000)  RCC_OFFSET = ((uint32_t)0x0002 1000)                               

/* --- CR Register ---*/
//时钟控制寄存器
#define CR_OFFSET                 (RCC_OFFSET + 0x00)                                         //CR寄存器在外设存储映像中的偏移
//CR_OFFSET = (RCC_OFFSET + 0x00) = ((uint32_t)0x0002 1000)

/* Alias word address of HSION bit */                                                                         //外部高速时钟使能位的别名
#define HSION_BitNumber           0x00                                                                     //HSION在CR寄存器中处于第0位
#define CR_HSION_BB               (PERIPH_BB_BASE + (CR_OFFSET * 32) + (HSION_BitNumber * 4))        //将位带区的位转换为别名区的字
//PERIPH_BB_BASE = ((uint32_t)0x42000000)              /* Peripheral base address in the bit-band region */

操作举例:
/**
  * @brief  Enables or disables the Internal High Speed oscillator (HSI).
            使能或失能内部高速晶振
  * @note   HSI can not be stopped if it is used directly or through the PLL as system clock.
            HSI不能被停止如果HSI直接作为系统时钟或通过PLL间接作为系统时钟
  * @param  NewState: new state of the HSI. This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void RCC_HSICmd(FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  //typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
  //#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE))
  *(__IO uint32_t *) CR_HSION_BB = (uint32_t)NewState;
  /* Alias word address of HSION bit */
  //#define PERIPH_BB_BASE ((uint32_t)0x42000000) /*!< Peripheral base address in the bit-band region */
  //#define CR_OFFSET (RCC_OFFSET + 0x00)   #define HSION_BitNumber  0x00
  //#define CR_HSION_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (HSION_BitNumber * 4))
}
*(__IO uint32_t *) CR_HSION_BB = (uint32_t)NewState;                //这边即是写别名区的字

上面是自己的理解,下面看看Cortex-M3权威指南上关于该部分的内容:


第1章ARMCortex-M3处理器概述 1.1ARM处理器系列 1.1.1命名规则 1.1.2ARM处理器系列 1.2ARMCortex-M3处理器 1.2.1处理器组件 1.2.2Cortex-M3的层次和实现选项 1.2.3处理器内 1.2.4嵌套向量中断控制器(NVIC) 1.2.5总线矩阵 1.2.6集成调试 1.2.7可选组件 1.2.8Cortex-M3处理器应用 1.3ARMCortex-M3指令集 1.4ARMCortex-M3的优势 第2章STM32系列微控制器 2.1STM32系列微控制器简介 2.1.1STM32微控制器的主要优点 2.1.2STM32微控制器的应用 2.2STM32F101xx系列微控制器 2.2.1特点 2.2.2总体结构 2.3STM32F103xx系列微控制器 2.3.1特点 2.3.2总体结构 第3章STM32系列微控制器存储器与外设 3.1存储器和总线的结构 3.1.1系统结构 3.1.2存储器结构 3.1.3存储器映射 3.1.4启动配置 3.2电源控制 3.2.1电源供应 3.2.2电源供应管理 3.2.3低功耗模式 3.2.4电源控制寄存器 3.3复位和时钟控制 3.3.1复位 3.3.2时钟 3.3.3RCC寄存器描述 3.4通用I/O和复用I/O(GPIO和AFIO) 3.4.1GPIO功能描述 3.4.2GPIO寄存器描述 3.4.3复用功能I/O和调试配置(AFIO) 3.4.4AFIO寄存器描述 3.5中断和事件 3.5.1嵌套向量中断控制器(NVIC) 3.5.2外部中断/事件控制器(EXTI) 3.5.3EXTI寄存器 3.6DMA控制器 3.6.1简介 3.6.2主要特性 3.6.3功能描述 3.6.4DMA寄存器 3.7实时时钟(RTC) 3.7.1简介 3.7.2主要特性 3.7.3功能描述 3.7.4RTC寄存器描述 3.8备份寄存器(BKP) 3.8.1简介 3.8.2主要特性 3.8.3干扰检测 3.8.4RTC校验 3.8.5BKP寄存器描述 3.9独立的看门狗 3.9.1简介 3.9.2IWDG寄存器描述 3.10窗口看门狗(WWDG) 3.10.1简介 3.10.2主要特性 3.10.3功能描述 3.10.4如何编程看门狗的超时时间 3.10.5调试模式 3.10.6寄存器描述 3.11高级控制定时器 3.11.1简介 3.11.2主要特性 3.11.3框图 3.11.4功能描述 3.11.5TIMI寄存器描述 3.12通用定时器(TIMx) 3.12.1简介 3.12.2主要特性 3.12.3框图 3.12.4功能描述 3.12.5TIMx寄存器描述 3.13控制器局域网(bxCAN) 3.13.1简介 3.13.2主要特性 3.13.3总体描述 3.13.4运行模式 3.13.5功能描述 3.13.6中断 3.13.7寄存器访问保护 3.13.8CAN寄存器描述 3.14内部集成电路(I2C)接口 3.14.1简介 3.14.2主要特性 3.14.3总体描述 3.14.4功能描述 3.14.5中断请求 3.14.6I2C调试模式 3.14.7I2C寄存器描述 3.15串行外设接FI(SPI) 3.15.1简介 3.15.2主要特性 3.15.3功能描述 3.15.4SPI寄存器描述 3.16通用同步异步收发机(USART) 3.16.1简介 3.16.2主要特性 3.16.3总体描述 3.16.4中断请求 3.16.5USART寄存器描述 3.17USB全速设备接口 3.17.1概述 3.17.2主要特性 3.17.3结构框图 3.17.4功能描述 3.17.5编程中需要考虑的问题 3.17.6USB寄存器描述 3.18模/数转换器(ADC) 3.18.1概述 3.18.2主要特性 3.18.3引脚描述 3.18.4功能描述 3.18.5校准 3.18.6数据对齐 3.18.7基于通道的可编程的采样时间 3.18.8外部触发转换 3.18.9DMA请求 3.18.10双ADC模式 3.18.11温度传感器 3.18.12中断 3.18.13ADC寄存器描述 3.19调试支持(DBG) 3.19.1概述 3.19.2相关的ARM文档 3.19.3SWJ调试端口(串行线和JTAG) 3.19.4引脚分布和调试端口引脚 3.19.5STM32F10xJTAGTAP连接 3.19.6ID编码和锁定机制 3.19.7JTAG调试端口 3.19.8SW调试端口 第4章STM32固件库 4.1STM32固件库的定义规则 4.1.1固件库命名规则 4.1.2代码标准 4.2STM32库的层次结构 4.2.1固件包描述 4.2.2固件库文件描述 4.3STM32库的使用 第5章STM32系列微控制器开发工具与应用 5.1KeilMDK介绍 5.1.1开发过程及集成开发环境简介 5.1.2工程管理 5.1.3编写源程序 5.1.4编译程序 5.1.5调试程序 5.2IAREWARM介绍 5.2.1EWARM集成开发环境及配套仿真器 5.2.2在EWARM中生成一个新项目 5.2.3编译和链接应用程序 5.2.4用J-LINK调试应用程序 5.3STM32-SK仿真评估板 5.3.1评估板规格说明 5.3.2测试程序 5.3.3关于仿真评估板的几个问题 5.4STM32-DK开发板 5.4.1开发板规格说明 5.4.2开发板实例程序 5.4.3关于STARM的常见问题 5.5mx-Pro量产编程器使用简介 5.5.1编程文件管理 5.5.2芯片烧写 5.6应用实例:基于STM32的数据采集器 5.6.1硬件设计 5.6.2软件设计 参考文献
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值