开发环境
首先学习51单片机我们需要
1.开发软件Keil5
2.烧录软件stcisp
3.普中51单片机开发板
然后开始
1.创建开发环境:打开stc-isp添加芯片,注意我们的芯片型号(STC89C52RC)和扫描串口的选择
2.创建工程:在Keil5中创建新project添加至新建文件夹(最好放到桌面),接着在弹出的窗口Search找AT89C52,最后右击Source Group 1创建main.c文件。
单片机(MCU)控制设备的方式
MCU中包含CPU,代码在CPU中执行;MCU中又有寄存器,它们以8个为一组,每一位寄存器后面的导线连接驱动器,导线最终连接至IO口(1为高电平,0为低电平)。
点亮LED
1.LED的特性
电流从正极(长引脚)进,负极(短引脚)出。LED 模块示意图如下
LED两侧电阻起限流作用(限流电阻,防止LED因电流过大而烧毁)
由二极管的特性可知,控制LED即为控制单片机引脚输出高低电平,当输出为低电平时,LED处有电流通过则亮起。
2.编写程序
P2是单片机控制LED的IO口,控制LED的亮灭即控制P2口输出的0和1。
如果写程序的时候直接输入2进制数据,程序会把它识别成10进制数据,所以需要把二进制数据转换成16进制写入
#include <REGX52.H>//添加单片机对应的头文件使程序识别相应接口
void main()
{
P2=0xFE;//2进制为1111 1110
//10进制为245
3.实现点亮
点击图标,创建hex文件->点击build图标->在stc-isp中打开hex文件->单片机冷启动
LED闪烁
1.LED不断闪烁
#include <REGX52.H>
void main()
{
while(1)
{
P2=0xFE;
P2=0xFF;
}
}
看到的现象是LED常亮,但亮度不如第一次,其实是因为LED在快速闪烁,为了让现象更加明显,需要添加延时。
2.添加延时
在stc-isp软件延时计算器中,根据单片机的类型选择系统频率和8051指令集,然后复制生成的代码
#include <REGX51.H>
#include <INTRINS.H>
void Delay500ms(void) //@11.0592MHz
{
unsigned char data i, j, k;
_nop_();//需要添加头文件#include <INTRINS.H>
i = 4;
j = 129;
k = 119;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
while(1)
{
P2=0xFE;//点亮LED
Delay500ms();//调用函数点亮500ms
p2=0xFF;//熄灭LED
Delay500ms();//调用函数熄灭500ms
}
}
3.利用延时实现流水灯
#include <REGX51.H>
#include <INTRINS.H>
void Delay(unsigned int xms) //@11.0592MHz
{
unsigned char data i, j, k;
while(xms)
{
i = 4;
j = 129;
k = 119;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
xms--;
}
}
void main()
{
while(1)
{
P2=0xFE;
Delay(500);
p2=0xFD;
Delay(500);
P2=0xFB;
Delay(500);
P2=0xF7;
Delay(500);
P2=0xEF;
Delay(500);
P2=0xDF;
Delay(500);
P2=0xBF;
Delay(500);
P2=0x7F;
Delay(500);
}
}
独立按键控制LED
轻触按键:相当于是一种电子开关,按下是开关接通,松开时开关断开,实现原理是通过轻触按键内部的金属弹片受力弹动来实现接通和断开。
左右两边的两个触点分别连接,按下时金属片被压扁,将左右两组触点相连,此时相当于四个触点相连。当按键按下时,IO口为低电平0;按键松开时,IO口为高电平1。
按下独立按键LED亮起
GND为接地线,当K1被按下的时候P3_1的值应该为0,需要检测P3_1的值就能知道k1是否被按下
void main() { while(1) { if(P3_1==0) { P2_0=0; else { P2_0=1; } } } }
独立按键控制LED状态
独立按键是一个机械按键,操作时会发生抖动,可以硬件消抖和软件消抖,一般用软件消抖即用代码实现。
void main()
{
while(1)
{
if(P3_1==0)
{
Delay(20);
while(P3_1==0);//检测是否松手
Delay(20);
P2_0=~P2_0;//~为取反操作
//即一次松手操作跳出while循环,P2_0的值改变一次
}
}
}
独立按键控制LED显示二进制
void main()
{
unsigned char LEDNum=0;//
while(1)
{
unsigned char LEDNum=0;//引入一个变量,相当于一个寄存器,都是八位
if(P3_1==0)
{
Delay(20);
while(P3_1==0);
Delay(20);
LEDNum++;
P2=~LEDNum;//P2默认为1111 1111即全为高电平,不能直接操作
}
}
}
独立按键控制LED移位
unsigned char LEDNum;
void main()
{
P2=~(0x01);//1111 1110
while(1)
{
if(P3_1==0)
{
Delay(20);
while(P3_1==0);
Delay(20);
LEDNum++;
if(LEDNum>=8)//避免自增时发生越界
{
LEDNum=0;
}
P2=~(0x01<<LEDNum);
}
if(P3_0==0)
{
Delay(20);
while(P3_0==0);
Delay(20);
//避免自减时发生越界
if(LEDNum==0)
LEDNum=7;
else
LEDNum--;
P2=~(0x01<<LEDNum);
}
}
}
数码管
LED数码管:数码管是一种简单、廉价的显示器,是由多个发光二极管封装在一起组成“8”字型的器件。引脚分为共阴极和共阳极,我们使用的开发板是共阴极的。
一位数码管
四位一体数码管
138译码器
输入端A、B、C(C是高位、B是中位、A是低位)为二进制,右侧输出端Y0、Y1、Y2、Y3、Y4、Y5、Y6、Y7分别对应二进制转化成十进制的1、2、3、4、5、6、7、8。
静态数码管显示
part1:想点亮哪个数码管。
输出端Y0、Y1、Y2、Y3、Y4、Y5、Y6、Y7分别对应LED1、LED2、LED3、LED4、LED5、LED6、LED7、LED8,结合它们与输入端的关系(共阴极端全是高电平即1,想要点亮LED,要通过输入端A、B、C的值将其变为低电平0),注意LED8实际上是第一个数码管。
part2:想让点亮的数码管呈现什么。
LED的a、b、c、d、e、f、g、dp是段码,想要显示不同数字对应的十六进制如下
#include <REGX52.H>
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//对应数字0 1 2 3 4 5 6 7 8 9
void Nixie(unsigned char Location,Number)
{
switch(Location)//选择点亮哪个位置的数码管
{
case 1:P2_4=1;P2_3=1;P2_2=1;break;
case 2:P2_4=1;P2_3=1;P2_2=0;break;
case 3:P2_4=1;P2_3=0;P2_2=1;break;
case 4:P2_4=1;P2_3=0;P2_2=0;break;
case 5:P2_4=0;P2_3=1;P2_2=1;break;
case 6:P2_4=0;P2_3=1;P2_2=0;break;
case 7:P2_4=0;P2_3=0;P2_2=1;break;
case 8:P2_4=0;P2_3=0;P2_2=0;break;
}
P0=NixieTable[Number];
}
void main()
{
Nixie(2,3);//表示点亮第二个数码管(LED7),使其显示3
while(1)
{
}
}
动态数码管显示
由于数码管显示的时候单片机速度很快,在段选->位选时,段选是所有数字共用的,数字选中后直接被下一个段选显示了,因此要进行消影才能出现清晰的数字。
位选 段选 清零 位选 段选 清零 位选 段选 清零 位选
#include <REGX52.H>
unsigned char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
void Delay(unsigned char xms) //@11.0592MHz
{
unsigned char data i, j;
while(xms--)
{
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
void Nixie(unsigned char Location,Number)
{
switch(Location)//位选
{
case 1:P2_4=1;P2_3=1;P2_2=1;break;
case 2:P2_4=1;P2_3=1;P2_2=0;break;
case 3:P2_4=1;P2_3=0;P2_2=1;break;
case 4:P2_4=1;P2_3=0;P2_2=0;break;
case 5:P2_4=0;P2_3=1;P2_2=1;break;
case 6:P2_4=0;P2_3=1;P2_2=0;break;
case 7:P2_4=0;P2_3=0;P2_2=1;break;
case 8:P2_4=0;P2_3=0;P2_2=0;break;
}
P0=NixieTable[Number];//段选
//清零操作
Delay(1);//显示之后延迟一毫秒,立刻清零数码管会变暗
P0=0x00;
}
void main()
{
while(1)
{
Nixie(1,1);
// Delay(20);
Nixie(2,2);
// Delay(20);
Nixie(3,3);
// Delay(20);
}
}
数码管驱动方式
单片机直接扫描:硬件设备简单,但会耗费大量的单片机CPU时间。
专用驱动芯片:内部自带显存、 扫描电路,单片机只需告诉它显示什么即可。