Stm32F407——LED闪烁(2)

位带及位带别名区的关系:
位带是指在存储区中可以按位操作的地带;
位带别名区(Bit Band Alias)是指存储区的另一个区域,该区域中的每1个字与位带中的1个位一一对应。

对位带区的1个位的操作和对对应的别名区中的】个字的操作结果一样,但对位带别名区操作代码效率更高。STM32F407中有两个区域支持位带,一个是SRAM区的最低1MB范围(0x2000 0000~0x200FFFFF),另一个是片内外设区的最低1MB范围(0x4000 0000~0x400F FFFF)。这两个区中的地址除了可以像普通的 RAM一样使用,它们还都有自己的“位带别名区”,位带别名区把位带区的每个位膨胀成一个32 位的字,即每个位带别名区有 32MB。其中,SRAM的位带别名区的地址范围为:0x22000000~0x23FF FFFF;片内外设的位带别名区的地址范围为:0x4200 0000~0x43FF FFFF。

GPIOF_ODR的bit9映射到位带别名区的地址的计算:
0x4002 1414&0xf000 0000 + 0x200 0000 +(0x4002 1414&0xfffff)<<5 + 9<<2 = 0x4242 82A4
> 故定义:
#define LED0 (*(volatile unsigned *)0x424282A4)
方便以下LED0的使用.

LED0定义宏

 #define LED0 (*(volatile unsigned *)0x424282A4)

main.c

//GPIOF口相关寄存器的定义
/*将项目2-1中的7)、regdef.h文件下//GPIOF口相关寄存器的定义拷贝过来*/
//注意,只需复制定义,不用复制条件编译
//GPIOF口相关寄存器的定义
	#define GPIOF_MODER    (*(volatile unsigned *)0x40021400) //端口x输入输出模式配置寄存器,控制位=00输入,=01通用输出,=10复用,=11模拟
	#define GPIOF_OTYPER    (*(volatile unsigned *)0x40021404) //端口输出类型配置寄存器。=0推挽输出,=1开漏输出
	#define GPIOF_OSPEEDR    (*(volatile unsigned *)0x40021408) //端口x输出速度配置寄存器。=00,2MHz;=01,25M;=10,50M;=11,30pF时为100M.
	#define GPIOF_PUPDR    (*(volatile unsigned *)0x4002140C)  //端口上拉下拉配置寄存器。=00无上下拉,=01上拉,=10下拉,=11保留
	#define GPIOF_ODR    (*(volatile unsigned *)0x40021414) //端口输出数据寄存器,某位=0对应端口输出低电平,=1输出高电平。
	//时钟系统相关寄存器的定义
	#define RCC_CR  		  (*(volatile unsigned *)0x40023800)
	#define RCC_PLLCFGR    (*(volatile unsigned *)0x40023804)
	#define RCC_CFGR   	  (*(volatile unsigned *)0x40023808)
	#define RCC_CIR        (*(volatile unsigned *)0x4002380C)
	#define RCC_AHB1ENR   (*(volatile unsigned *)0x40023830)  //外设时钟使能寄存器。=1对应外设时钟使能
	#define RCC_APB1ENR   (*(volatile unsigned *)0x40023840)   
	//电源系统相关寄存器
	#define PWR_CR        (*(volatile unsigned *)0x40007000)      
	//FLASH系统相关寄存器
	#define FLASH_ACR      (*(volatile unsigned *)0x40023C00)

/*GPIOF_ODR的bit9映射到位带别名区的地址的计算
  0x4002 1414&0xf000 0000 + 0x200 0000 + (0x4002 1414&0xfffff)<<5 + 9<<2
	= 0x4242 82A4  */
#define LED0 (*(volatile unsigned *)0x424282A4)
#define u8 unsigned char
#define u16 unsigned short
#define u32 unsigned int
void Led_Init(void);
void delay(void);
void Stm32_Clock_Init(u32 plln,u32 pllm,u32 pllp,u32 pllq);
u8 Sys_Clock_Set(u32 plln,u32 pllm,u32 pllp,u32 pllq);
int main(void)
{
    
     
		Stm32_Clock_Init(336,8,2,7);//设置时钟,168Mhz
		Led_Init();				//初始化LED接口,LED0接PF9
		while(1)
		{
    
    
			LED0 = 0; //LED0亮
			delay();  //延时       
			LED0 = 1; //LED0灭
			delay();  //延时
		}
}
//-----------------led0初始化函数定义-------------------
/*将项目1-1中的函数void Led_Init()拷贝过来*/
//补充函数void Led_Init(void)
//-----------------led0初始化函数定义-------------------
void Led_Init(void)
{
    
        	 
		RCC_AHB1ENR |= 1<<5;         //使能PORTF时钟 
		GPIOF_MODER &= ~(3<<(9*2));  //将配置PF9引脚相关位bit18,bit19清0
		GPIOF_MODER |= (1<<(9*2));   //配置PF9为输出
		GPIOF_OTYPER &= ~(1<<9);     //电路工作方式为推挽
		GPIOF_OSPEEDR &= ~(3<<(9*2));//对应位清0
		GPIOF_OSPEEDR |= (2<<(9*2)); //响应速度50M,其他值亦可
		GPIOF_PUPDR &= ~(3<<(9*2));  //清0
		GPIOF_PUPDR |= (1<<(9*2));   //上拉有效
}
//---------------------延时函数定义---------------------
void delay(void)
{
    
    
	u32 i, j;
	for(i=0; i<2000; i++)
		for(j=0; j<5000; j++);
}
/*将项目1-1中的函数Sys_Clock_Set()和Stm32_Clock_Init()拷贝过来*/
//函数Sys_Clock_Set(u32 plln,u32 pllm,u32 pllp,u32 pllq)
//函数Stm32_Clock_Init(u32 plln,u32 pllm,u32 pllp,u32 pllq)
//----------------------------------------------------------	 
u8 Sys_Clock_Set(u32 plln,u32 pllm,u32 pllp,u32 pllq)
{
    
     
		u16 retry=0;
		u8 status=0;
		RCC_CR |= 1<<16;				//HSE 开启 
		while(((RCC_CR&(1<<17))==0)&&(retry<0X1FFF)) retry++;//等待HSE RDY
		if(retry==0X1FFF) status=1;	    //HSE无法就绪
		else   
		{
    
    
			RCC_APB1ENR |= 1<<28;	   //电源接口时钟使能
			PWR_CR |= 3<<14; 		   //高性能模式,时钟可到168Mhz
			RCC_CFGR |= (0<<4)|(5<<10)|(4<<13);//HCLK 不分频;APB1 4分频;APB2 2分频. 
			RCC_CR &= ~(1<<24);	  //关闭主PLL
			RCC_PLLCFGR = pllm|(plln<<6)|(((pllp>>1)-1)<<16)|(pllq<<24)|(1<<22);//配置主PLL,PLL时钟源来自HSE
			RCC_CR |= 1<<24;			//打开主PLL
			while((RCC_CR & (1<<25))==0);//等待PLL准备好 
			FLASH_ACR |= 1<<8;		    //指令预取使能.
			FLASH_ACR |= 1<<9;		    //指令cache使能.
			FLASH_ACR |= 1<<10;		//数据cache使能.
			FLASH_ACR |= 5<<0;		    //5个CPU等待周期. 
			RCC_CFGR &= ~(3<<0);		//清零
			RCC_CFGR |= 2<<0;		    //选择主PLL作为系统时钟	 
			while((RCC_CFGR&(3<<2))!=(2<<2));//等待主PLL作为系统时钟成功. 
		} 
		return status;
} 
//----------------------------------------------------------
void Stm32_Clock_Init(u32 plln,u32 pllm,u32 pllp,u32 pllq)
{
    
      
		RCC_CR|=0x00000001;		//设置HSISON,开启内部高速RC振荡
		RCC_CFGR=0x00000000;		//CFGR清零 
		RCC_CR&=0xFEF6FFFF;		//HSEON,CSSON,PLLON清零 
		RCC_PLLCFGR=0x24003010;	//PLLCFGR恢复复位值 
		RCC_CR&=~(1<<18);			//HSEBYP清零,外部晶振不旁路
		RCC_CIR=0x00000000;		//禁止RCC时钟中断 
		Sys_Clock_Set(plln,pllm,pllp,pllq);//设置时钟 
}

猜你喜欢

转载自blog.csdn.net/weixin_53391957/article/details/117421233