一、概括
首先,说点不靠谱的,APB和AHB总线,我个人感觉这个类似于个人PC系统里的北桥和南桥总线。
南桥总线上挂接的都是鼠标、键盘这些慢速的设备,北桥上挂接显卡等高速设备。南桥频率低,北桥频率高。另外,南桥最后也要接到北桥上。
这些感觉都类似于APB和AHB。
AHB,是Advanced High performance Bus的缩写,译作高级高性能总线,这是一种“系统总线”。
AHB主要用于高性能模块(如CPU、DMA和DSP等)之间的连接。AHB 系统由主模块、从模块和基础结构(Infrastructure)3部分组成,整个AHB总线上的传输都由主模块发出,由从模块负责回应。APB,是Advanced Peripheral Bus的缩写,这是一种外围总线。
APB主要用于低带宽的周边外设之间的连接,例如UART、1284等,它的总线架构不像 AHB支持多个主模块,在APB里面唯一的主模块就是APB 桥。再往下,APB2负责AD,I/O,高级TIM,串口1;APB1负责DA,USB,SPI,I2C,CAN,串口2345,普通TIM。
这两者都是总线,符合AMBA规范。
片上总线标准种类繁多,而由ARM公司推出的AMBA片上总线受到了广大IP开发商和SoC系统集成者的青睐,已成为一种流行的工业标准片上结构。AMBA规范主要包括了AHB(Advanced High performance Bus)系统总线和APB(Advanced Peripheral Bus)外围总线。二者分别适用于高速与相对低速设备的连接。
由于时钟是一个由内而外的东西,具体设置要从寄存器开始。
RCC 寄存器结构,RCC_TypeDeff,在文件“stm 32f10x_map.h”中定义如下:
typedef struct
{
vu32 CR;
vu32 CFGR;
vu32 CIR;
vu32 APB2RSTR;
vu32 APB1RSTR;
vu32 AHBENR;
vu32 APB2ENR;
vu32 APB1ENR;
vu32 BDCR;
vu32 CSR;
} RCC_TypeDef;
这些寄存器的具体定义和使用方式参见芯片手册,因为C语言的开发可以不和他们直接打交道,当然如果能够加以理解和记忆,无疑是百利而无一害。
如果外接晶振为8Mhz,最高工作频率为72Mhz,显然需要用PLL倍频9倍,这些设置都需要在初始化阶段完成。为了方便说明,以例程的RCC设置函数,并用中文注释的形式加以说明:
static void RCC_Config(void)
{
RCC_DeInit();
RCC_HSEConfig(RCC_HSE_ON);
HSEStartUpStatus = RCC_WaitForHSEStartUp();
if (HSEStartUpStatus == SUCCESS)
{
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
FLASH_SetLatency(FLASH_Latency_2);
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK2Config(RCC_HCLK_Div1);
RCC_PCLK1Config(RCC_HCLK_Div2);
RCC_ADCCLKConfig(RCC_PCLK2_Div6);
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
RCC_PLLCmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
{}
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while (RCC_GetSYSCLKSource() != 0x08)
{}
}
//使能外围接口总线时钟,注意各外设的隶属情况,不同芯片的分配不同,到时候查手册就可以
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE |
RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG |
RCC_APB2Periph_AFIO, ENABLE);
}
由上述程序可以看出系统时钟的设定是比较复杂的,外设越多,需要考虑的因素就越多。同时这种设定也是有规律可循的,设定参数也是有顺序规范的,这是应用中应当注意的,例如PLL的设定需要在使能之前,一旦PLL使能后参数不可更改。
经过此番设置后,对于外置8Mhz晶振的情况下,系统时钟为72Mhz,高速总线和低速总线2都为72Mhz,低速总线1为36Mhz,ADC时钟为12Mhz,USB时钟经过1.5分频设置就可以实现48Mhz的数据传输。
一般性的时钟设置需要先考虑系统时钟的来源,是内部RC还是外部晶振还是外部的振荡器,是否需要PLL。然后考虑内部总线和外部总线,最后考虑外设的时钟信号。遵从先倍频作为CPU时钟,然后在由内向外分频,下级迁就上级的原则。
如果使用内部RC振荡器而不使用外部晶振,请按照如下方法处理:
1)对于100脚或144脚的产品,OSC_IN应接地,OSC_OUT应悬空。
2)对于少于100脚的产品,有2种接法:
i)OSC_IN和OSC_OUT分别通过10K电阻接地。此方法可提高EMC性能。
ii)分别重映射OSC_IN和OSC_OUT至PD0和PD1,再配置PD0和PD1为推挽输出并输出'0'。此方法可以减小功耗并(相对上面i)节省2个外部电阻。
STM32时钟系统结构图
时钟是STM32单片机的脉搏,是单片机的驱动源。使用任何一个外设都必须打开相应的时钟。这样的好处就是,如果不使用一个外设的时候,就把它的时钟关掉,从而可以降低系统的功耗,达到节能,实现低功耗的效果。
STM32单片机的时钟可以由以下3个时钟源提供:
1、HSI:高速内部时钟信号STM32单片机内带的时钟 (8M频率), 精度较差
2、HSE:高速外部时钟信号,精度高。
来源:i. HSE外部晶体/陶瓷谐振器(晶振);
ii.HSE用户外部时钟
3、LSE:低速外部晶体 32.768kHz 主要提供一个精确的时钟源 一般作为RTC时钟使用
STM32单片机的将时钟信号(例如HSE)经过分频或倍频(PLL)后,得到系统时钟,系统时钟经过分频,产生外设所使用的时钟。
上图为STM32整个时钟架构。
为了便于更好了解STM32单片机的时钟,下面以HSE时钟的使用为例。
设置时钟流程:
1、将RCC寄存器重新设置为默认值 RCC_DeInit
2、打开外部高速时钟晶振HSE RCC_HSEConfig(RCC_HSE_ON);
3、等待外部高速时钟晶振工作 HSEStartUpStatus = RCC_WaitForHSEStartUp();
4、设置AHB时钟 RCC_HCLKConfig;
5、设置高速AHB时钟 RCC_PCLK2Config;
6、设置低速速AHB时钟 RCC_PCLK1Config
7、设置PLL RCC_PLLConfig
8、打开PLL RCC_PLLCmd(ENABLE);
9、等待PLL工作 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
10、设置系统时钟 RCC_SYSCLKConfig
11、判断是否PLL是系统时钟 while(RCC_GetSYSCLKSource() != 0x08)
12、打开要使用的外设时钟 RCC_APB2PeriphClockCmd()/RCC_APB1PeriphClockCmd()
在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。
HSI是高速内部时钟,RC振荡器,频率为8MHz。
HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。
LSI是低速内部时钟,RC振荡器,频率为40kHz。
LSE是低速外部时钟,接频率为32.768kHz的石英晶体。
PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。
其中40kHz的LSI供独立看门狗IWDG使用,另外它还可以被选择为实时时钟RTC的时钟源。另外,实时时钟RTC的时钟源还可以选择LSE,或者是HSE的128分频。RTC的时钟源通过RTCSEL[1:0]来选择。
STM32中有一个全速功能的USB模块,其串行接口引擎需要一个频率为48MHz的时钟源。该时钟源只能从PLL输出端获取,可以选择为1.5分频或者1分频,也就是,当需要使用USB模块时,PLL必须使能,并且时钟频率配置为48MHz或72MHz。
另外,STM32还可以选择一个时钟信号输出到MCO脚(PA8)上,可以选择为PLL输出的2分频、HSI、HSE、或者系统时钟。
系统时钟SYSCLK,它是供STM32中绝大部分部件工作的时钟源。系统时钟可选择为PLL输出、HSI或者HSE。系统时钟最大频率为72MHz,它通过AHB分频器分频后送给各模块使用,AHB分频器可选择1、2、4、8、16、64、128、256、512分频。其中AHB分频器输出的时钟送给5大模块使用:
1)送给AHB总线、内核、内存和DMA使用的HCLK时钟。
2)通过8分频后送给Cortex的系统定时器时钟。
3)直接送给Cortex的空闲运行时钟FCLK。
4)送给APB1分频器。APB1分频器可选择1、2、4、8、16分频,其输出一路供APB1外设使用(PCLK1,最大频
率36MHz),另一路送给定时器(Timer)2、3、4倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定
时器2、3、4使用。
5)送给APB2分频器。APB2分频器可选择1、2、4、8、16分频,其输出一路供APB2外设使用(PCLK2,最大频
率72MHz),另一路送给定时器(Timer1)倍频器使用。该倍频器可选择1或者2倍频,时钟输出供定时器1使
用。另外,APB2分频器还有一路输出供ADC分频器使用,分频后送给ADC模块使用。ADC分频器可选择为
2、4、6、8分频。
在以上的时钟输出中,有很多是带使能控制的,例如AHB总线时钟、内核时钟、各种APB1外设、APB2外设等等。当需要使用某模块时,记得一定要先使能对应的时钟。
需要注意的是定时器的倍频器,(定时器时钟之前有一个乘法器,它的操作不是由程序控制的,是由硬件根据前一级的APB预分频器的输出自动选择)当APB的分频为1时(这个乘法器无作用),它的倍频值为1,否则它的倍频值就为2(即将APB预分频器输出的频率乘2,这样可以保证定时器可以得到最高的72MHz时钟脉冲)。
连接在APB1(低速外设)上的设备有:电源接口、备份接口、CAN、USB、I2C1、I2C2、UART2、UART3、SPI2、窗口看门狗、Timer2、Timer3、Timer4。注意USB模块虽然需要一个单独的48MHz时钟信号,但它应该不是供USB模块工作的时钟,而只是提供给串行接口引擎(SIE)使用的时钟。USB模块工作的时钟应该是由APB1提供的。
连接在APB2(高速外设)上的设备有:UART1、SPI1、Timer1、ADC1、ADC2、所有普通IO口(PA~PE)、第二功能IO口。
在单片机系统中,CPU和总线以及外设的时钟设置是非常重要的,因为没有时钟就没有时序,组合电路需要好好理解清楚。
四、FLCK、HCLK和PCLK
1)FLCK、HCLK和PCLK的关系
S3C2440有三个时钟FLCK、HCLK和PCLK
s3c2440官方手册上说P7-8写到:
FCLK is used by ARM920T,内核时钟,主频。
HCLK is used for AHB bus, which is used by the ARM920T, the memory controller, the interrupt controller, the LCD controller, the DMA and USB host block.也就是总线时钟,包括USB时钟。
PCLK is used for APB bus, which is used by the peripherals such as WDT, IIS, I2C, PWM timer, MMC interface,ADC, UART, GPIO, RTC and SPI.即IO接口时钟,例如串口的时钟设置就是从PCLK来的;
那么这三个时钟是什么关系呢?
这三个时钟通常设置为1:4:8,1:3:6的分频关系,也就说如果主频FLCK是400MHz,按照1:4:8的设置,那么HLCK是100MHz,PLCK是50MHz
寄存器CLKDIVN表明并设置了这三个时钟的关系
如果CLKDIVN设置为0x5,那么比例即为1:4:8,前提是CAMDIVN[9]为0.
2)输入时钟FIN与主频FCLK的关系
现代的CPU基本上都使用了比主频低的多的时钟输入,在CPU内部使用锁相环进行倍频。对于S3C2440,常用的输入时钟FIN有两种:12MHz和16.9344MHz,那么CPU是如何将FIN倍频为FCLK的呢?
S3C2440使用了三个倍频因子MDIV、PDIV和SDIV来设置将FIN倍频为MPLL,也就是FCLK
MPLL=(2*m*FIN)/(p*2^s) where m=(MDIV+8), p=(PDIV+2), s="SDIV"
寄存器MPLLCON就是用来设置倍频因子的
理论上,你可以通过设置该寄存器来实现不同的频率,然而,由于实际存在的各种约束关系,设置一个适当的频率并不容易,手册上列出了一些常用频率的表格,
例如,假设输入时钟FIN=16.9344M,MDIV=110, PDIV="3", SDIV="1",
利用上面的公式,FCLK=2*16.9344*(110+8)/((2+3)*2)=399.65
3)关于USB时钟
S3C2440有两个锁相环,一个主锁相环MPLL提供给FCLK的,另外一个UPLL是提供给USB时钟(48MHz)的,与MPLL一样,UPLL的产生也是通过UPLLCON寄存器设置分频因子得到,计算公式稍有不同:
UPLL=(m*FIN)/(p*2^s) where m=(MDIV+8), p=(PDIV+2), s="SDIV",同样,可以通过查表得到一个合适的值。
最后值得一提的是,在CLKDIVN的第三位DIVN_UPLL用来设置USB时钟UCLK和UPLL的关系,如果UPLL已经是48Mhz了,那么这一位应该设置为0,表示1:1的关系,否则是1:2的关系
2410的时钟和电源管理
概述
时钟和电源管理模块由3部分组成:时钟控制、USB控制、电源控制。
时钟控制部分产生3种时钟信号:CPU用的FCLK,AHB总线用的HCLK,APB总线用的PCLK。有2个锁相环,一个用于FCLK HCLK PCLK,另一个用于48MHz的USB时钟。可以通过不使能锁相环来达到慢速省电目的。
电源管理模块提供了4种模式:Normal模式、Slow模式、Idle模式、Power_Off模式。
Normal Mode
该模式下如果所有外围设备都打开时电流消耗最大,允许用户通过软件关闭外围设备达到省电目的。
Slow Mode
不采用PLL的模式,能量消耗仅取决于外时钟的频率。由外部提供的时钟源作FCLK。
Idle Mode
关掉了给cpu的FCLK时钟,但外围设备时钟仍存在,任何到CPU的中断请求可以将cpu唤醒。
Power_off Mode
这种模式关掉了内部供电,仅有给wake_up部分的供电还存在。可以通过外部中断或实时时钟中断可以唤醒。
功能描述
时钟结构:主时钟源来自外部晶振XTlpll或外部时钟EXTCLK。
时钟源选择:通过OM[3: 2]的高低电平选择,现在我们采用00。OM[3:2]的状态在nRESET的上升沿锁存。尽管MPLL在上电复位后就开始工作,但是MPLL输出不作为系统时钟,只有对MPLLCON写入适当的数值后才可以。即使用户不想改变MPLLCON的值,也要重新写一遍才能使其起作用。
时钟控制逻辑:时钟控制逻辑决定要使用的时钟源,当锁相环被设置为一个新的值时,时钟控制逻辑切断FCLK直到PLL输出稳定。时钟控制逻辑在上电复位或从power_down状态启动时使能。
上电复位:注意上电后必须通过设置PLLCON才能使PLL作用。
在正常操作状态下改变PLL设置:通过改变PMS的值来实现。
USB时钟控制:UCLK不起作用直到UPLL被设置。
FCLK、HCLK、PCLK:可以通过HDIVN、PDIVN、CLKDIVN来改变3种时钟的比率,推荐采用1:2:4的比率。在设置完PMS的值后,需要设置CLKDIVN寄存器,该寄存器设置的值在PLL锁定后生效,只需要1.5个HCLK即可完成比率的修改。
电源管理:4种模式及特点。
Power_Off模式:外部中断EINT[15:0]或RTC alarm中断可以从该模式wakeup.
进入PowerOff模式的流程:1。将GPIO端口设置为适当的状态;2。……….
VDDi和VDDiarm的控制:在PowerOff模式,仅VDDi和VDDiarm通过PWREN管脚控制被关闭。如果PWREN为高,VDDi和VDDiarm被外部电源提供,如果为低则关闭。 尽管VDDi,VDDiarm,VDDi_MPLL,VDDi_UPLL可能被关闭,其他电源必须被提供。
EINT[15:0]启动信号: EINTn管脚必须被设置为中断管脚,在启动后,相应的EINTn管脚将不被用作启动,可以被用作外部中断请求。
电池故障信号(nBATT_FLT): 当cpu不在PowerOff模式时,nBATT_FLT将要引起低电平触发的中断。当在PowerOff模式时,nBATT_FLT信号将会禁止芯片从PowerOff模式启动,故所有的wakeup信号被屏蔽,此举用来保护系统电量低时不出现故障。
时钟和电源管理部分寄存器
LOCKTIME: UPLL、 MPLL锁定时间的计数值。
MPLLCON UPLLCON: 这两个寄存器都有MDIV PDIV SDIV设置,对于输入12M的晶振,有相应的推荐值,产生200M和48M的频率。
CLKCON: 为各种外围接口提供时钟。
CLKSLOW: 是否打开2个PLL。
CLKDIVN: 设置CLK、HCLK、PCLK比率的寄存器。