天祥单片机文件 | 小白的云盘

STC89C52单片机名称含义

  • STC:表示芯片为STC公司生产的产品

  • 8:表示该芯片为8051内核芯片

  • 9:表示内部含 FlashE²PROM 寄存器

  • C:表示该器件为CMOS产品

  • 52:5固定不变,2表示存储空间的大小(1为4KB,2为8KB,以此类推)

点亮第一个LED

#include <REGX51.H>  //51单片机头文件

//主函数,程序的入口
void main() {
  P1=0xFE;  //P1端口,0xFE是一个十六进制数
}

进制表:1—15数字进制表

电路板上有8个LED,0xFE十六进制值,转换为二进制是11111110,在这个二进制中0表示低电平,而1表示高电平,P1端口连接了8个LED灯,对应的LED如果是低电平会亮,高电平会灭。

LED闪烁

#include <REGX52.H>  //51单片机头文件
#include <INTRINS.H>  //用于定义_nop_函数

void Delay500ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();  //空函数,没有任何作用,纯消耗时间
	_nop_();
	i = 22;
	j = 3;
	k = 227;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
//主函数,程序的入口
void main()
{
	while(1)  //死循环
	{
		P1=0xFE;	//二进制1111 1110
		Delay500ms();  //调用Delay500ms函数(延时函数)
		P1=0xFF;	//二进制1111 1111
		Delay500ms();
	}
}

注意点:如果不加延迟或延迟太低,会导致LED闪烁过快,使肉眼无法看到闪烁(出现依旧常亮的情况)

自定义延迟

正常情况可以依靠STC-ISP工具里的软件延时计算器生成对应的延迟时长的代码,但是如果不同时间的延迟过多,那种方法会导致代码不简洁且难维护,这时候就需要一个自定义延时的函数来完成这个任务

#include <REGX52.H>
#include <INTRINS.H>
//其他头文件...
void Delay1ms(unsigned int xms);	//函数声明,如果函数在主函数之前,可以不声明

void Delay1ms(unsigned int xms)		//@11.0592MHz
{
	unsigned char i, j;
	while(xms)
	{
		_nop_();
		_nop_();
		i = 2;
		j = 15;
		do
		{
			while (--j);
		} while (--i);
        xms--;
	}
}
//其他代码

调用方法:

Delay1ms(1000);  //1000代表延迟1000毫秒,循环执行1ms函数1000次

大概原理:Delay1ms函数中,每执行一次约1毫秒,用while来实现循环执行,每执行一次变量xms自减,直到变量xms的值为零,循环结束。

注意点:注意声明函数的位置

LED流水灯

#include <REGX52.H>
#include <INTRINS.H>

void Delay500ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 22;
	j = 3;
	k = 227;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void main()
{
	while(1)
	{
		P1=0xFE;//1111 1110
		Delay500ms();
		P1=0xFD;//1111 1101
		Delay500ms();
		P1=0xFB;//1111 1011
		Delay500ms();
		P1=0xF7;//1111 0111
		Delay500ms();
		P1=0xEF;//1110 1111
		Delay500ms();
		P1=0xDF;//1101 1111
		Delay500ms();
		P1=0xBF;//1011 1111
		Delay500ms();
		P1=0x7F;//0111 1111
		Delay500ms();
	}
}

和LED闪烁代码差不多,只不过是延时后的十六进制数发生改变

独立按键控制LED亮灭

#include <REGX52.H>
#include <INTRINS.H>

sbit	key_1	= P3^4;  //设定声明开关
sbit	led_1	= P1^1;  //设定声明led

void Delay1ms(unsigned int xms)		//@11.0592MHz(自定义延时函数)
{
	unsigned char i, j;
	while(xms)
	{
		_nop_();
		_nop_();
		i = 2;
		j = 15;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}

int key()
{
	if(key_1 == 0)  //判断按钮是否被按下
	{
		Delay1ms(100);  //延时100ms
		if(key_1 == 0)  //再判定一次是否被按下(防止短时间的点击)
		{
			led_1 = !led_1;  //led取反,设定led的亮灭
			while(!key_1);  //按键取反,中断读取(防止出现led闪烁)
		}
	}
}

void main()
{
	while(1)
	{
		key();  //调用key函数
	}
}

按键控制LED灯位移

#include <REGX52.H>
#include <INTRINS.H>

sbit	key_1	= P3^4;
sbit	key_2	=	P3^5;
sbit led	=	P1^1;

void Delay1ms(unsigned int xms)		//@11.0592MHz
{
	unsigned char i, j;
	while(xms)
	{
		_nop_();
		_nop_();
		i = 2;
		j = 15;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}

int key()
{
	if(key_1 == 0)
	{
		Delay1ms(100);
		if(key_1 == 0)
		{
			P1	=	_crol_(P1,1);  //左移1个led
			while(!key_1);
		}
	}
	
		if(key_2 == 0)
	{
		Delay1ms(100);
		if(key_2 == 0)
		{
			P1	=	_cror_(P1,1);  //右移1个led
			while(!key_2);
		}
	}
}

void main()
{
	led	= 0;  //初始化led
	while(1)
	{
		key();
	}
}

_crol_ 函数控制向左位移,_cror_ 函数控制向右位移。

静态数码管显示

dpjmgb.jpg

编码表:共阴极数码管编码表

#include <REGX52.H>

sbit w =	P2^7;	//定义位选
sbit d =	P2^6;	//定义段选

int main()
{
	w=1;  //开启位选
	P0=0xfe;  //1111 1110
	w=0;  //锁定位选
	
	d=1;  //开启段选
	P0=0x71;  //数码管显示F(对应见编码表)
	d=0;  //锁定段选
	while(1);	//停止(死循环)
}

数码管位选数组

uchar wtab[] = {0xC0, 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF}; // 0为全部,其余依次选中第1~6位数码管

数码管段选数组

uchar dtab[]={
	0x3f,0x06,0x5b,0x4f,
	0x66,0x6d,0x7d,0x07,
  0x7f,0x6f,0x77,0x7c,
  0x39,0x5e,0x79,0x71};

数组每个值的含义可参考上方的 共阴极数码管编码表

段选和位选需要记忆的数值过多时,使用数组可以方便我们的调用,一定程度上减少记忆的成本。

数组使用方法示例:

P0=tab[1];  //表示使用上面数组中第二个值,设定为数码管的值
  • 上面演示使用的tab 需要替换成你需要调用的数组名,如上面位选的wtab 或段选的dtab

  • 例如P0=wtab[1]; 等于位选数组的第二个值,代码意思与P0=0xFE; 相同