51单片机学习笔记(1)
一.单片机简介
单片机(MCU),内部集成CPU、RAM、ROM、定时器、中断系统、通讯接口等一系列电脑的常用硬件功能;
51单片机系列
CPU:单片机核心,处理信息;
位数:8位;
RAM:随机存储器(掉电丢失)==内存条,512字节
ROM:只读存储器(掉电不丢失)==硬盘,8K
工作频率:取决于单片机给的时钟(晶振)
电平:高电平5V,低电平0V;
二.LED
1. 点亮一个LED
该LED模块中LED左端连接VCC,为高电平,若要点亮LED则要使LED另一端(右侧)为低电平;即可通过控制P2管脚的电平控制LED的亮灭;
控制管脚:值为0为低电平,值为1为高电平;
代码:让P2以16进制形式展示8个管脚的电平;
P2=0xFE; <==>1 1 1 1 1 1 1 0
由于数据的高位对应端口的高位,如P2_7对应第一个1;所以P2=0xFE意味着P2_0=0,剩余端口为1,即仅D1会亮
#include <REGX52.H>
void main()
{
P2=0x7f;
}
而上述代码将点亮D8。
2.LED闪烁
利用stc-isp中的软件延时计算器实现LED闪烁;
生成延时代码时确保选择的系统频率与单片机时钟频率一致;
若软件延时计算器生成的代码带有_nop_函数,需加上头文件#include <INTRINS.H>
#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)
{
P2=0xFE;
Delay500ms();//达到闪烁效果
P2=0xFE;
}
}
可对延时函数进行修改使延时的长短可更改;先生成1ms的延时函数,传参进入函数后对函数内部设置参数次数的循环。
void Delayxms(unsigned int xms) //@11.0592MHz
{
unsigned char i, j;
while(xms--){
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
3.流水灯
将LED闪烁的代码进行修改,即LED熄灭后替换下一个亮起的LED可逐个点亮LED;
亦可设置为双向流水灯:
void main()
{
unsigned int xms;//利用变量传参便于修改
xms=100;
while(1)
{
P2=0x7E;
Delayxms(xms);
P2=0xBD;
Delayxms(xms);
P2=0xDB;
Delayxms(xms);
P2=0xE7;
Delayxms(xms);
P2=0xDB;
Delayxms(xms);
P2=0xBD;
Delayxms(xms);
}
}
三. 独立按键
1.控制LED亮灭
单片机端口默认电平为高电平,按下按键接通时由于另一端连接GND,相应的端口转变为低电平。
在循环中使用判断语句,以按键的电平状态控制LED;仅按住按键时灯亮
#include <REGX52.H>
void main()
{
// P2_0=0;
while(1)
{
if(P3_1==0){
P2_0=0;
}else{
P2_0=1;
}
}
}
2.控制LED状态
按键按下或松开瞬间会发生颤抖,影响按键的稳定,此时需要延时来消除颤抖带来的影响;
~表示按位取反,如 ~10010001==01101110
void main()
{
while(1){
if(P3_1==0){
Delay(20);
while(P3_1==0);//按住按键时一直再此循环中,避免按键时长的影响;
Delay(20);
P2_0=~P2_0;//电平取反,控制亮灭
}
}
}
3.控制LED显示二进制
①使P2按照从零开始的二进制形式进行逐次递加1可以显示二进制形式,但是此时移动的是1,而点亮LED所需电平为0,此时可运用取反符;
unsigned char num;//取反的对象
void main()
{
while(1){
if(P3_1==0){
Delay(20);
while(P3_1==0);
Delay(20);
num++;
P2=~num;
}
}
}
②P2口默认每个接口为高电平,即初始形式为1111 1111;此时令P2–即可实现二进制的显示;
while(1){
if(P3_1==0){
Delay(20);
while(P3_1==0);
Delay(20);
P2--;
}
4.控制LED移位
<<:按位左移; 0001 0100<<2即往左位移两位,新位补零,为0101 0000;>>按位右移类似
由按位移动可通过按键控制LED位移显示;
void main()
{
while(1){
if(P3_1==0||P3_0==0||P3_2==0||P3_3==0){
Delay(20);
while(P3_1==0||P3_0==0||P3_2==0||P3_3==0);
Delay(20);
P2_0=0;
break;
}//设置启动(任意一个按键点亮)
}
while(1){
if(P3_0==0){
Delay(20);
while(P3_0==0);
Delay(20);
numofLED++;
if(numofLED==8){
numofLED=0;}//当超出LED个数时刷新
P2=~(0x01<<numofLED);//取反让0移位
}else if(P3_1==0){
Delay(20);
while(P3_1==0);
Delay(20);
numofLED--;//减少向左移的个数,相对右移;
if(numofLED==-1){
numofLED=7;}
P2=~(0x01<<numofLED);
}
}
}
四.数码管
数码管管脚分为共阴极和共阳极;
共阴极位选时选中即电平为0;
共阳极位选时选中及电平为1;
位选:通过P2_2,P2_3,P2_4三个端口控制要点亮的LED,此三个端口数值拼接显示的二进制数对应十进制数的LED接通,此时也遵循数据高位对端口的高位;如
P2_4=1;P2_3=1;P2_2=0;对应的十进制值为6,即Y6对应的LED7被选中;电平为0,其他LED电平为默认值1
每次只能选择一个LED
段选:P0输入控制信号通过74HC245放大,驱动LED;
此处可看作8个LED共用一套管脚,即信号传输到每个LED,但只有位选中的LED显示;
由于位选时是共阴极,要让LED对应区域亮则需令其为1;
以16进制输入P0数值,同样遵循高位端口对应高位数字;
1.静态显示
#include <REGX52.H>
unsigned char key[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};//输入数组下标对应的“显示码”
void Nixie(unsigned char LED,num)//通过输入对应的LED号和显示的数字达到显示静态显示的效果
{
switch(LED){
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=key[num];//段选
}
void main()
{
Nixie(2,0);
while(1){
}
}
2.动态显示
通过余辉和视觉残留显示多个数字;
连续重复位选和段选的操作可实现动态显示,
即 位选 段选 位选 段选… …
但是由于程序按顺序自上而下逐步进行,在前一个段选仍执行,下一个位选开始执行而下一个段选未执行时,会在下一个位选的位置显示上一个段选的数字,所以需要在段选和位选中间将段选归零;
#include <REGX52.H>
#include <INTRINS.H>
void Delay(unsigned int xms) //@11.0592MHz
{
unsigned char i, j;
while(xms--){
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
}
unsigned char key[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
void Nixie(unsigned char LED,num)
{
switch(LED){
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=key[num];Delay(1);P0=0x00;//延时一毫秒为了显示得更清楚
}
void main()
{
while(1){
Nixie(1,5);
Nixie(2,2);
Nixie(3,0);
Nixie(4,1);
Nixie(5,3);
Nixie(6,1);
Nixie(7,4);
Nixie(8,0);
}
}
以上图片采自普中单片机原理图