目录
一、单片机介绍
单片机是一种可通过编程控制的微型处理器。
单片机芯片本身不能单独运用于某种工程或产品上,他必须要依靠外围数字期间或模拟期间的协调才可发挥其自身的强大功能,所以我们在学习单片机知识的同时不能仅仅学习单片机的一种芯片,还要循序渐进地学习它外围的数字及模拟单片机知识,还要学习常用到的外围电路的设计与调试方法等。
官方描述:
1.STC89C52单片机
2.单片机的结构:
3.单片机管脚图
4.单片机的最小系统
二、点亮一个LED
LED介绍
单片机上的LED模块
vcc电源正极,用二进制表示为1,左边接入到单片机芯片,常规情况下属于高频,对应为1,要LED点亮,则需左边变为低频,即等于0.
代码:
void main()
{
P2=0xFE; //用16进制来表示8个LED的状态
while(1){}
}
注意:代码下载前要勾选如下,才有文件可供下载到单片机中。
三、LED闪烁
需要用到延时代码,因为正常情况下,闪烁的时间太快,人眼看不到。
延示代码:
void Delay500ms(void) //@12.000MHz
{
unsigned char data i, j, k;
_nop_();
i = 4;
j = 205;
k = 187;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
代码:
注意:用到的延时代码中若包括_nop_(),要包括头文件<INTRINS.H>
四、LED流水灯
1.逐个遍历
代码:
void main()
{
while(1)
{
P2=0xFE;//1111 1110
Delay500ms();
P2=0xFD;//1111 1101
Delay500ms();
P2=0xFB;//1111 1011
Delay500ms();
P2=0xF7;//1111 0111
Delay500ms();
P2=0xEF;//1110 1111
Delay500ms();
P2=0xDF;//1101 1111
Delay500ms();
P2=0xBF;//1011 1111
Delay500ms();
P2=0x7F;//0111 1111
Delay500ms();
}
}
2.对于LED闪烁的时长的随意控制,则可以通过改变延时代码来实现,具体思路:
先生产一个1ms的代码,再对它进行改写。
修改后的代码:(更加灵活)
void Delay1ms(unsigned int xms)
{
unsigned char data i, j;
while(xms){ //当xms=0时循环就停止了,所以需要xms--,一共循环了xms次,延时1*xms
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
五、独立按键控制LED亮灭
独立按键:按键按照结构原理科分为两类,一类是触点式开关按键,如机械式开关、导电橡胶式开关灯;另一类是无触点式开关按键,如电气式按键,磁感应按键等。前者造价低,后者寿命长。
思路:接电时所有L口都是高电频,相当于1,而按下按键后是低电频,相当于0,电源相当于1,所以当L口是低电频时才可以正常工作
代码:
#include <REGX52.H>
void main()
{
while(1)
{
if(P3_1==0)
{
P2_7=0;
}
else
{
P2_7=1;
}
}
}
C51数据运算:
按位左移:向左高位移除,低位补0。
按位右移:向右高位移除,低位补0。
按位与:0与0是0,0与1是0,1与1是1。
例如:0001 1010 & 0010 1000 -> 0000 1000
按位或:0与0是0,0与1是1,1与1是1。
例如:0001 1010 | 0010 1000 -> 0011 1010
按位异或:一样是0,不一样是1。
例如:0001 1010 ^ 0010 1000 -> 0011 0010
按位取反:0变1,1变0。
例如:~0001 1010 -> 1110 0101
注意:按位与,按位或,按位异或,按位取反都是对两个数据,而按位取反只对一个数据作用。
六、独立按键控制LED状态
1.按键抖动,松手消抖
当机械触点断开,闭合时,由于机械触点的弹性作用,一个开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开,所以在开关闭合及断开的瞬间会伴随一连串的抖动。
硬件解决方法:
加滤波器等进行滤波。
软件解决方法:
用delay可以延时来跳过抖动时间段。
代码:
#include <REGX52.H>
void Delay1ms(unsigned int x)
{
unsigned char data i, j;
while(x) /*这里不能用1,因为x代表多少毫秒,表示循环多少个1ms,用1的话因为不对1做出改变,所以会一直循环,而用x只要x最终=0就会停止*/
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
x--;
}
}
void main()
{
if(P3_1==0)
{
Delay1ms(20); //按键消抖
while(P3_1==0); //一直按着就不断循环,灯不会亮,直到松手跳出循环,灯才会亮
Delay1ms(20); //松手消抖
P2_0=~P2_0; /*用取反是因为要按、松两个动作灯亮,再进行一次就会灭,如果只P2_0==0,那么按下去亮了以后,再按一次还是亮的,状态不会改变*/
}
}
七、独立按键控制LED显示二进制
#include <REGX52.H>
void Delay1ms(unsigned int xms)
{
unsigned char data i, j;
while(xms)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
void main()
{
unsigned char LEDnumber=0;
/*char型占一个字节,8个位,二进制的长度和P2一样,相同可以用来替换*/
while(1)
{
if(P3_1==0)
{
Delay1ms(20);
while(P3_1==0);
Delay1ms(20);
LEDnumber++;
//这里实际上是二进制的运算
P2=~LEDnumber; /*对二进制取反这样每一次P2只有一种运算即等于LEDnumber的反码,P2就会按照正常二进制进行运算,实际上储存的unsigned char类型的数据也是二进制的数据所以本身他就是可以自动变成2进制比较*/
}
}
不用P2++; P2=~P2;的原因:
P2原先是1111 1111,加一的话会溢出就变成0000 0000,再取反又变成1111 1111,这样无限循环根本不会亮。所以要用一个变量引导,从而使得P2正常以二进制的方式运算。
八、独立按键控制LED移位
一个按键控制移动:
代码:
#include <REGX52.H>
void Delay1ms(unsigned int xms)
{
unsigned char data i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
unsigned char LEDnum; //unsigned char是一个字节的变量
void main()
{
P2=~0x01; //若不加这个,则按红色的复位键时,P2会回到上一次最后时刻的状态
while(1)
{
if (P3_1==0)
{
Delay1ms(20);
while(P3_1==0);
Delay1ms(20);
LEDnum++;
if(LEDnum>=8)
LEDnum=0;
P2=~(0x01<<LEDnum); //当LEDnum==0时,P2刚好复位等于0x01
}
}
}
两个按键控制左移右移:
代码:
#include <REGX52.H>
void Delay1ms(unsigned int xms)
{
unsigned char data i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
unsigned char LEDnum;
void main()
{
P2=~0x01;
while(1)
{
if (P3_1==0)
{
Delay1ms(20);
while(P3_1==0);
Delay1ms(20);
LEDnum++;
if(LEDnum>=8)
LEDnum=0;
P2=~(0x01<<LEDnum);
}
if (P3_0==0)
{
Delay1ms(20);
while(P3_0==0);
Delay1ms(20);
if(LEDnum==0)
LEDnum=7;
else
LEDnum--;
P2=~(0x01<<LEDnum); //减完后从0x01重新左移
}
}
}