一 寄存器
1.1 地址映射和寄存器映射原理
地址映射:
为了使CPU执行指令能够准确无误的访问正确的存储单元,需将用户程序中的逻辑地址转换为由机器直接寻址的物理地址,这一过程称为地址映射
寄存器映射:
寄存器映射是在地址映射的基础上运行的。以STM32为例,在存储器片上外设区域,四字节为一个单元,每个单元对应不同的功能。我们可以通过控制这些单元时来完成相应的功能。我们可以找到每个单元的起始地址,然后通过C 语言指针的操作方式来访问这些单元。但这些单元的地址繁琐冗长容易出错,因此就以功能为名给这个内存单元取一个代号,这个别代号实质上就是寄存器名字。综上,给已分配好地址的能完成相应功能的内存单元取代号的过程就叫寄存器映射。
1.2 寄存器
寄存器是CPU内部用来存放数据的一些小型存储区域,用来存放二进制数据或代码的信息
二 GPIO
2.1 GPIO端口的初始化设置
GPIO端口的初始化设置一共分为三个步骤:
1.打开GPIO口的时钟
GPIO地址:
时钟地址:
2.设置低电平
三.流水灯的仿真与实现
3.1 对GPIOA的A7、GPIOB的B9、GPIOC的C15设置:
//--------------APB2使能时钟寄存器------------------------
#define RCC_AP2ENR *((unsigned volatile int*)0x40021018)
//----------------GPIOA配置寄存器 ------------------------
#define GPIOA_CRL *((unsigned volatile int*)0x40010800)
#define GPIOA_ORD *((unsigned volatile int*)0x4001080C)
//----------------GPIOB配置寄存器 ------------------------
#define GPIOB_CRH *((unsigned volatile int*)0x40010C04)
#define GPIOB_ORD *((unsigned volatile int*)0x40010C0C)
//----------------GPIOC配置寄存器 ------------------------
#define GPIOC_CRH *((unsigned volatile int*)0x40011004)
#define GPIOC_ORD *((unsigned volatile int*)0x4001100C)
//-------------------简单的延时函数-----------------------
void Delay_ms( volatile unsigned int t)
{
unsigned int i;
while(t--)
for (i=0;i<800;i++);
}
void A_LED_LIGHT(){
GPIOA_ORD=0x0<<7; //PA7低电平
GPIOB_ORD=0x1<<9; //PB9高电平
GPIOC_ORD=0x1<<15; //PC15高电平
}
void B_LED_LIGHT(){
GPIOA_ORD=0x1<<7; //PA7高电平
GPIOB_ORD=0x0<<9; //PB9低电平
GPIOC_ORD=0x1<<15; //PC15高电平
}
void C_LED_LIGHT(){
GPIOA_ORD=0x1<<7; //PA7高电平
GPIOB_ORD=0x1<<9; //PB9高电平
GPIOC_ORD=0x0<<15; //PC15低电平
}
//------------------------主函数--------------------------
int main()
{
int j=100;
RCC_AP2ENR|=1<<2; //APB2-GPIOA外设时钟使能
RCC_AP2ENR|=1<<3; //APB2-GPIOB外设时钟使能
RCC_AP2ENR|=1<<4; //APB2-GPIOC外设时钟使能
//这两行代码可以合为 RCC_APB2ENR|=1<<3|1<<4;
GPIOA_CRL&=0x0FFFFFFF; //设置位 清零
GPIOA_CRL|=0x20000000; //PA7推挽输出
GPIOA_ORD|=1<<7; //设置PA7初始灯为灭
GPIOB_CRH&=0xFFFFFF0F; //设置位 清零
GPIOB_CRH|=0x00000020; //PB9推挽输出
GPIOB_ORD|=1<<9; //设置初始灯为灭
GPIOC_CRH&=0x0FFFFFFF; //设置位 清零
GPIOC_CRH|=0x30000000; //PC15推挽输出
GPIOC_ORD|=0x1<<15; //设置初始灯为灭
while(j)
{
A_LED_LIGHT();
Delay_ms(10000000);
B_LED_LIGHT();
Delay_ms(10000000);
C_LED_LIGHT();
Delay_ms(10000000);
}
}
3.2 Protues仿真图
3.3建立工程文件
四.最终效果
五.实验心得
在编写代码以及仿真过程中高低电平没有分清,导致仿真很多次连接错误,很多次没有做出来。以及寄存器的使用方式开始并不熟悉,还有GPIO端口的初始化设置和工作模式开始并没有掌握太多,最后通过查询优快云解决掉了部分错误。