控制组单片机学习笔记(一)
一、初识单片机
单片机(Single-Chip Microcomputer)是一种集成电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、定时器/计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电路)集成到一块硅片上构成的一个小而完善的微型计算机系统,在工业控制领域广泛应用。从上世纪80年代,由当时的4位、8位单片机,发展到现在的300M的高速单片机。开发板原理图
单片机内部结构图
单片机都有8051微处理器,周围的设备也大体相同,可能会因型号不同而略有差别
所有的外接设备都连在一根总线上,只要CPU连接到总线就可以访问设备
管脚图
Vcc—通电时连接电源正极
Gnd—通电时连接电源负极或接地
P0/P1/P2/P3—l口,对应着LED灯及数码管等外设元件
XTAL—晶振
Vcc电源正极,Gnd电源负极
晶振用于驱动程序继续运行
复位:让程序从第一条开始运行或重新运行(高电平复位)
(接通电路时电容充电时相当于短路,此时为高电平,当电容充满后,相当于短路,此时电路通过电阻,为低电平)
二、LED
首先需要用到以下两个软件
基本认识
内部图
从图中可以看到,我们所能控制的P2_ l口连接在二极管的负极,单片机给电后另一端VCC一般为5V。图中的RP7和RP9为定值电阻,用于限流分压,保护二极管。
void main(void)
{
while(1){
if(P3_1==0)
P2=0xFE;
else
P2=0;
}
P2代表着LED,0x指16位方便程序对编写的代码编译,P3代表着独立按键。
我们也可以通过P2_0或者P3_1这样的形式来单独指向某一个LED或者独立按键
独立按键
注意P3_0在P3_1和P3_2的中间
编写程序
点亮一个LED
#include <REGX52.H>
#include <INTRINS.H>
void main()
{
P2=FE;//1111 1110
while(1){
}
这样我们便令最后一个LED亮起,这里的使用while循环是因为程序会在执行完毕后重复执行,所以我们会用到一个死循环来让程序终止
LED闪烁
#include <REGX52.H>
#include <INTRINS.H>
#include <STC89C5xRC.H>
#include <INTRINS.H>
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);
}
void main()
{
while(1)
{
P2 = 0xFE;
Delay500ms();
P2 = 0xFF;
Delay500ms();
}
}
我们可以注意到代码中多了delay函数,其原理为执行语句会花费一定时间,只要能计算出大量语句执行所使用的时间就可以起到延时效果,
在该函数中执行main函数首先进入循环并延时0.5s接着点亮了一个LED,随后延时0.5s后执行了LED熄灭的语句,并在while循环中重复此过程,这样表现的结果变成了LED的最后一个灯每一秒闪烁一次。
LED流水灯
#include <REGX52.H>
#include <INTRINS.H>
void Delay500ms() //@12.000MHz
{
unsigned char i, j, k;
_nop_();
i = 4;
j = 205;
k = 187;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
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();
}
}
这是最简单的LED闪烁方法,只需要依次执行语句就可以起到LED流水的效果
我们可以使用位运算符起到相同的效果
这样我们只需要初始化P2=FE再使用左移运算符就可以令LED流动
独立按键控制LED闪烁
#include<REGX52.H>
void Delay(unsigned int xms) //@12.000MHz
{
unsigned char data i, j;
while(xms > 0)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
void main(void)
{
while(1)
{
if(P31 == 0)
{
Delay(20);
// 按键消抖
while(P31 == 0);
Delay(20);
//该while循环的作用是防止按键还没松开就进行下一步操作即保证在松手后发生改变
P2_0 = ~P2_0;
}
}
}
数码管
LED数码管:数码管是一种简单、廉价的显示器,是由多个发光二极管封装在一起组成“8”字型的器件
一个数码管是由a、b、c、d、e、f、g、dp八个二极管组成,八个LED一端接在一起,另一端引脚引出来。二极管如果阳极连在一起,就是共阳极数码管,阴极连在一起,就是共阴极数码管。
上图为共阴极连接,下图为共阳极连接(即连接3或8都可),控制高低电平的0和1即为段码
在同一时刻只能有一个数码管被使用,即使有多个,也显示相同数字(有利于减少利用的引脚,只引出12个就可以操作32个二极管)
静态数码显示
#include<STC89C5xRC.H>
void main()
{
P2_4 = 1;
P2_3 = 0;
//此时LED3、4亮起(引脚冲突)
P2_2 = 0;
//控制74HC138
P0 = 0x3F;
//控制74HC245
//第四个数码管显示0
while(1)
{
}
}
动态数码显示
数码管的动态显示:数码管的动态显示又叫做数码管的动态扫描。动态显示的特点是:将所有位数码管段选线并联在一起,,由位选控制是哪一位数码管有效。所谓动态扫描显示即轮流向各位数码管送出字型码和相应的位选,利用发光管的余晖和人眼视觉暂留作用,使人感觉好像各位数码管同时都在显示,而实际上多位数码管是一位一位轮流显示的,只是轮流的速度比较快,人眼已经无法分辨出来。
关于数码管以及74HC573锁存器的分析
#include <reg51.h> //51单片机头文件
sbit WE = P2^7; //位选信号的锁存器控制 位定义 WE为标识符 代表着位选 P2^7为地址符 申明U8锁存器的锁存端
sbit DU = P2^6; //段选信号的锁存器控制 位定义 DU为标识符 代表着段选 P2^7为地址符 申明U9锁存器的锁存端
#define uchar unsigned char //宏定义(预处理指令,不是语句,后面不用加分号)其中直接用uchar替换了unsigned char 此时我们可以用uchar num等价于unsigned char num;
#define uint unsigned int //宏定义(用法和上面类似)
uchar code table[] = { //显示0~f的码表
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void delay(uint z) //延时函数
{
unsigned int x,y;
for(x = z;x>0;x--)
for(y=144;y>0;y--);
}
int main() //主函数
{
while(1) //大循环
{
P0 = 0xff; //在进行位选择时候,先关闭所有显示,防止打开位选时,P0口还保持原来的数据
WE = 1; //打开U8锁存器
P0 = 0xfe; //第1个数码管显示
WE = 0; //关闭U8锁存器
DU = 1; //打开U9锁存器
P0 = table[0]; //调用数组
delay(1); //调用延时函数
P0 = 0xff;
WE = 1;
P0 = 0xfd; //第2个数码管显示
WE = 0;
DU = 1;
P0 = table[1]; //调用数组,显示数字
delay(1); //调用延时函数
P0 = 0xff;
WE = 1;
P0 = 0xfb; //第3个数码管显示
WE = 0;
DU = 1;
P0 = table[2]; //调用数组,显示数字2
delay(1); //调用延时函数
P0 = 0xff;
WE = 1;
P0 = 0xf7; //第4个数码管显示
WE = 0;
DU = 1;
P0 = table[3]; //调用数组,显示数字3
delay(1); //调用延时函数
P0 = 0xff;
WE = 1;
P0 = 0xef; //第5个数码管显示
WE = 0;
DU = 1;
P0 = table[4]; //调用数组,显示数字4
delay(1); //调用延时函数
P0 = 0xff;
WE = 1;
P0 = 0xdf; //第6个数码管显示
WE = 0;
DU = 1;
P0 = table[5]; //调用数组,显示数字5
delay(1); //调用延时函数
P0 = 0xff;
WE = 1;
P0 = 0xbf; //第7个数码管显示
WE = 0;
DU = 1;
P0 = table[6]; //调用数组,显示数字6
delay(1); //调用延时函数
P0 = 0xff;
WE = 1;
P0 = 0x7f; //第8个数码管显示
WE = 0;
DU = 1;
P0 = table[7]; //调用数组,显示数字7
delay(1); //调用延时函数
}
}