位带及位带别名区的关系:
位带是指在存储区中可以按位操作的地带;
位带别名区(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);//设置时钟
}