51单片机学习笔记
单片机简单介绍
- 内部集成了CPU、RAM、ROM、定时器、中断系统、通讯接口等一系列电脑的常用硬件功能
- 单片机的任务是信息采集(依靠传感器)、处理(依靠CPU)和硬件设备(例如电机,LED等)的控制
- 单片机跟计算机相比,单片机算是一个袖珍版计算机,一个芯片就能构成完整的计算机系统。但在性能上,与计算机相差甚远,但单片机成本低、体积小、结构简单,在生活和工业控制领域大有所用。
- 所属系列:51单片机系列
- 公司:STC公司
- 位数:8位
- RAM:512字节
- ROM:8K(Flash)
- 工作频率:12MHz(本开发板使用)
led模块
led介绍
- 中文名:发光二极管
- 外文名:Light Emitting Diode
- 简称:LED
- 用途:照明、广告灯、指引灯、屏幕
如何控制
点亮一个led
单片机通过P2口控制led模块。
让我们来点亮D1号(最左边)的led,先上代码
while(1)//永远为真的循环,实现常亮
{
P2=0xfe;//1111 1110
}
解析如下:我们所输入的“0xfe”即二进制的1111 1110.这会使P2_1~P2_7端口输出高电平(5V),而P2_8输出低电平(0V)而led模块的另一端为高电平,所以只有P_8连接的D1led能形成电流,实现点亮
所以,只要熟悉进制转换,就能点亮任意的led了。
还有一种方法
P2_1=0;
这样能够单独控制每一个led
led 闪烁
闪烁嘛,无非就是亮一下,暗一下
我们写(抄)一个延时函数
void Delay(unsigned int ms)
{
while(ms--)//这是一个循环一次,延时1ms的循环,传入的参数即为循环次数,也就是循环秒数
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
然后,在主函数循环中加上延时,实现亮灭交替
void main()
{
while(1)
{
P2=0xfe;//1111 1110
Delay(100);
}
}
led流水灯
原理一样,只是主函数循环内部依次点亮
void main()
{
while(1)
{
P2=0xfe;//1111 1110
Delay1ms(100);
P2=0xfd;//1111 1101
Delay1ms(100);
P2=0xfb;//1111 1011
Delay1ms(100);
P2=0xf7;//1111 0111
Delay1ms(100);
P2=0xef;//1110 1111
Delay1ms(100);
P2=0xdf;//1101 1111
Delay1ms(100);
P2=0xbf;//1011 1111
Delay1ms(100);
P2=0x7f;
Delay1ms(100);
}
}
还有一种更简洁的控制方法,用<<
(按位左移)运算符,这在后面会介绍。
独立按键
原理
轻触按键:相当于是一种电子开关,按下时开关接通,松开时开关断开,实现原理是通过轻触按键内部的金属弹片受力弹动来实现接通和断开
如何控制
独立按键控制led亮灭
控制独立按键的端口是P3
值得注意的是,P3_0控制K2按键,P3_1控制K1按键。(为什么要这样设计呢,,)
void main()
{
while(1){
if(P3_1==0)P2_0=0;//假如K1被按下,D8亮起
else P2=0xff;//全灭
}
}
C51中的常用运算符
&
按位与:拆开每位,有0即0
|
按位或:拆开每位,有1即1
<<
按位左移<<1100 1010=1001 0100
>>
按位右移>>1100 1010=0110 0101
^
按位异或异即为1,同即为0
~
按位取反~1100 1010=0011 0101
消抖
当机械触点断开、闭合时,由于机械触点的弹性作用,会伴随一连串的抖动。
所以要用到上面写的延时函数。检测到按下,延时20ms,再执行按下后的指令。检测到松手时也一样,实现消抖。
void main()
{
while(1){
if(P3_1==0){//若按下
Delay(20);//消抖
while(P3_1==0);//按着就停在这条
Delay(20);//松键消抖
P2_0=~P2_0;//取反控制亮灭
}
}
}
独立按键控制led显示二进制
通过led的亮灭显示二进制数,从零开始加一
void main()
{
unsigned char led=0;
while(1){
if(P3_1==0){
Delay(20);
while(P3_1==0);
Delay(20);
P2=~led;//注意0是亮,注意取反
led++;
}
}
}
独立按键控制led位移
按下K1,led向左移动;按下K2,led向右移动。
char LEDNum;
void main()
{
LEDNum=~0x01;//初始化,用来记录led的位置
while(1){
if(P3_1==0){//控制左移
Delay(20);
while(P3_1==0);
Delay(20);
LEDNum++;
if(LEDNum==8)
LEDNum=0;//移到边边,下一次按应在另一端
P2=~(0x01<<LEDNum);
}
else if(P3_0==0){//控制右移
Delay(20);
while(P3_0==0);
Delay(20);
LEDNum--;
if(LEDNum<0)
LEDNum=7;
P2=~(0x01<<LEDNum);
}
}
}
数码管
简介
- LED数码管:数码管是一种简单、廉价的显示器,是由多个发光二极管封装在一起组成“8”字型的器件
控制原理
数码管有共阴极连接和共阳极连接
我们所用的数码管连接方式为上者,也就是共阴极连接
由图可知,每个数码管的八个led共用阴极(P2_2 P2_3 P2_4),
这里由于内部设置了一个“38编码器,只需要三位二进制数来表示十进制的0~7,实现对八个数码管的控制”
switch(loc){//定位
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;
}
且它们相同位置的led共阳极(P0)
也就是说,我们通过给特定数码管的阴极低电平,来点亮特定数码管
然后通过给阳极高电平来diy它的形状,可以是数字或字母
一些P0口的实例如下:
0 1 2 3 4 5 6 7 8 9
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F, 0x6F
A B C D E F 空
0x77,0x7C,0x39,0x5E,0x79,0x71,0x00,
静态数码管显示
#include <REGX52.H>
//用一个数组来存储数码管所要显示的数字
char NixieTable[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
//独立函数,实现某个数码管显示已定义的形状
void Nixie(int loc,int num)
{
switch(loc){//定位
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[num];//定型
}
void main()
{
while(1)
{
Nixie(4,7);
}
}
消影
当我们要实现数码管的动态显示时,是通过快速循环交替的定位,定形来实现的
这时,由于定位,定形这个交替过程太快,就会出现“来不及换位就显示”,出现残影。
所以,要想解决这个问题,只要在每次定位、定形后,停顿1ms,并熄灭一次(这个过程很短很短),就能保证稳定的显示了
void Nixie(int loc,int num)
{
switch(loc){//定位
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[num];//定形
Delay(1);//停顿
P0=0x00;//消影
}
动态数码管显示
如上述,快速交替显示,便能呈现出同时显示的效果
void main()
{
while(1){
Nixie(1,1);
Nixie(2,2);
Nixie(3,3);
Nixie(4,4);
Nixie(5,5);
Nixie(6,6);
Nixie(7,7);
Nixie(8,8);
}
}