目的:
利用单片机开发板,实现一个简单的点灯程序。目的是:
- 了解软件如何驱动硬件;
- 寄存器的工作原理;
- 单片机点灯的code具体内容,已经如何优化code;
背景知识:
1. CPU如何通过寄存器、硬件控制器,控制二极管灯。基本原理如下:
2. 本文后续开发板基本资料
(1)CPU中SFR所占内存地址:0x1000_0000 ~ 0x1400_0000;
(2)GPX2_7引脚如果是0,灯灭;引脚GPX2_7如果是1,灯亮。
(3)GPX2_7引脚与GPIO控制器对应,而GPIO控制器被GPIO寄存器控制。需要两个寄存器GPX2CON(地址 0x1100_0C40)和GPX2DAT(地址 0x1100_0C44)。
(4)将GPX2CON[7]的第28~31位是用来设置GPX2_7引脚的,需要令 0001 0000 0000 0000 0000 0000 0000 0000 = 0x 1000 0000;
(5)将GPX2DAT的第7位也是用来设置GPX2_7引脚的,需要令 0001 0000 0000 0000 0000 0000 0000 0000 = 1000 1;
实现过程:
1. 最简单实现逻辑如下(表达下基本意思,语法肯定不对)
#include <reg52.h> //包含寄存器相关的.h文件
int main(void)
{
while(1)
{
P1=1; //寄存器P1赋值1,灯亮
delay(1000ms); //灯亮持续1s
P1=0; //寄存器P1赋值0,灯灭
delay(1000ms);
}
}
2. 结合开发板基本资料,分析得到如下基本code。(方法一:无封装)
int main(void)
{
//寄存器GPX2CON的第28~31位赋值1, GPX2_7引脚能输出高低电平
*(unsigned int *)0x11000C40 = 0x10000000;
while(1)
{
*(unsigned int *)0x11000C44 = 0x80; //GPX2DAT的第7位赋值1,灯亮
delay(1000ms); //灯亮持续1s
*(unsigned int *)0x11000C44 = 0x00; //灯灭
delay(1000ms);
}
}
3. 上述2中代码存在可读性差,维护麻烦的重大问题。更新后如下(方法二:宏定义封装)
#define GPX2CON *(unsigned int *)0x11000C40
#define GPX2DAT *(unsigned int *)0x11000C44
int main(void)
{
//寄存器GPX2CON的第28~31位赋值1, GPX2_7引脚能输出高低电平
GPX2CON = 0x10000000;
while(1)
{
GPX2DAT = 0x80; //GPX2DAT的第7位赋值1,灯亮
delay(1000ms); //灯亮持续1s
GPX2DAT = 0x00; //灯灭
delay(1000ms);
}
}
4. 利用结构体封装两个寄存器(方法三:结构体封装)
typedef struct
{
unsigned int CON;
unsigned int DAT;
}gpx2;
#define GPX2 *(gpx2 *)0x11000C40 //GPX2表示该结构体指针
int main(void)
{
GPX2.CON = 0x10000000;
while(1)
{
GPX2.DAT = 0x80; //GPX2DAT的第7位赋值1,灯亮
delay(1000ms); //灯亮持续1s
GPX2.DAT = 0x00; //灯灭
delay(1000ms);
}
}