51单片机
第一章:C51单片机最小系统
1.1 单片机内部硬件结构
AT89C51
1.2 硬件参数
AT89C51 | AT89C52 |
---|
8位微处理器(CPU:运算器,控制器) | 8位微处理器(CPU:运算器,控制器) | 数据存储器(128B RAM) | 数据存储器(512B RAM) | 程序存储器(4KB Flash ROM) | 程序存储器(8KB Flash ROM) | 4个8位可编程并行I/O口(P0、P1、P2和P3) | 4个8位可编程并行I/O口(P0、P1、P2和P3) | 1个全双工异步串行口 | 1个全双工异步串行口 | 2个可编程的16位定时器/计数器(T0、T1) | 3个可编程的16位定时器/计数器(T0、T1、T2) | 中断系统具有5个中断源、5个中断向量 | 中断系统具有8个中断源、8个中断向量 |
直插型芯片实物图:
贴片型芯片实物图:
常见的其他型号:
不同型号的51单片机有不同的资源,后面涉及的资源全部以经典型号AT89C51为准
1.3 单片机各引脚引脚功能
P0口:P0.0-P0.7引脚
为漏极开路的8位并行I/O口。作为输出口时,每个引脚可驱动8个LS型TTL负载。AT89C52扩展外部存储器及I/O脚芯片时,P0口为分时复用的低8位地址/数据总线。在向P0口写入"1"后就成为高阻态输入口。
当P0为通用I/O口使用时,需外加上拉电阻,这时为准双向口
P1口:P1.0-P1.7引脚
为准双向I/O口,引脚内部有上拉电阻。
P2口:P1.0-P1.7引脚
为准双向I/O口,引脚内部有上拉电阻。
当单片访问外部存储器时,P2作为高8位地址总线使用,输出高8位地址。
P3口:P1.0-P1.7引脚
P3口通用I/O口,内部有上拉电阻。它还具有第二种功能
引脚 | 第二功能 |
---|
P3.0 | PXD (串行口输入) | P3.1 | RTXD (串行口输出) | P3.2 | INT0 (外部中断0输入) | P3.3 | INT1 (外部中断1输入) | P3.4 | T0 (定时器/记数器0的外部输入) | P3.5 | T1 (定时器/记数器1的外部输入) | P3.6 | WR (片外数据存储器 “写选通控制” 输出) | P3.7 | RD (片外数据存储器 “读选通控制” 输出) |
1.4 C51单片机最小系统
电源电路: | 供电:VCC为+5V电源,VSS接地 |
---|
时钟电路: | XTAL1、XTAL2:接晶振(常用频率:12MHZ、11.0592)和30pf的电容。 | 复位电路: | RST:复位信号输入,在引脚加上持续时间大于2个机器周期的高电平,可使单片机复位。正常工作时,此引脚为低电平。 | 选择ROM: | EA:片内片外程序存储器选择。当EA=1;选择片内程序存储器。EA=0;选择片外程序存储器。 |
1.5 C51单片机的时钟
时钟周期 | 时钟控制信号的基本时间单位。若单片使用的晶振频率为Fosc,则时钟周期Tosc=1/Fosc。如fosc=12MH,Tosc=1/12us |
---|
状态周期 | 每两个时钟周期为一个状态周期。即S=Tosc*2 | 机器周期 | CPU完成一个基本操作所需要时间为机器周期。每12个时钟周期为一个机器周期。晶振为12MHZ,则机器周期为 T=12 * 1/fosc =1us | 指令周期 | 执行条指令所需的时间。简单的字节指令,只需一个指令周期,而有些复杂的指令(如乘、除指令)需要两个或多个指令周期。 |
第二章:IO口控制应用
2.1 IO口控制
单片机IO口的状态总是0和1(高电平和低电平)
2.1.1 控制1位IO口
方法1:(推荐)
sbit 引脚名=端口寄存器^位置
sbit LED=P1^4
LED=0;
LED=1;
方法2
P1 |=(1<<5) //为P1并行口第5为引脚置位为1
P1 &=~(1<<5) //为P1并行口第5为引脚置位为0
2.1.2 引脚输入检测
if(LED==1) {执行代码}
if(LED==0) {执行代码}
2.1.3 延时函数
void delay_ms(unsigned int xms)
{
unsigned char i,j;
for(i=0;i<xms;i++)
for(j=0;j<110;j++);
}
2.2 简易流水灯
各有千秋。
方法1 一位一位去控制
#include <reg51.h>
sbit LED0=P1^0;
sbit LED1=P1^1;
sbit LED2=P1^2;
sbit LED3=P1^3;
sbit LED4=P1^4;
sbit LED5=P1^5;
sbit LED6=P1^6;
sbit LED7=P1^7;
void delay_ms(unsigned int xms);
void main()
{
while(1)
{
LED0=0;
delay_ms(200);
LED0=1;
delay_ms(200);
LED1=0;
delay_ms(200);
LED1=1;
delay_ms(200);
LED2=0;
delay_ms(200);
LED2=1;
delay_ms(200);
LED3=0;
delay_ms(200);
LED3=1;
delay_ms(200);
LED4=0;
delay_ms(200);
LED4=1;
delay_ms(200);
LED5=0;
delay_ms(200);
LED5=1;
delay_ms(200);
LED6=0;
delay_ms(200);
LED6=1;
delay_ms(200);
LED7=0;
delay_ms(200);
LED7=1;
delay_ms(200);
}
}
void delay_ms(unsigned int xms)
{
unsigned char i,j;
for(i=0;i<xms;i++)
for(j=0;j<110;j++);
}
方法2 数组的方式去控制
#include <reg51.h>
#define LED P1
void delay_ms(unsigned int xms);
char ledDat[8] ={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
unsigned char i = 0;
void main()
{
while(1)
{
for(i=0;i<8;i++)
{
LED=ledDat[i];
delay_ms(200);
LED=0xff;
delay_ms(200);
}
}
}
void delay_ms(unsigned int xms)
{
unsigned char i,j;
for(i=0;i<xms;i++)
for(j=0;j<110;j++);
}
方法3 位运算的方式去控制
#include <reg51.h>
#define LED P1
void delay_ms(unsigned int xms);
unsigned char i = 0;
void main()
{
while(1)
{
unsigned char t = 1;
for(i=0;i<8;i++)
{
LED=~(t);
delay_ms(200);
LED=0xff;
delay_ms(200);
t=t<<1;
}
}
}
void delay_ms(unsigned int xms)
{
unsigned char i,j;
for(i=0;i<xms;i++)
for(j=0;j<110;j++);
}
2.3 独立按键控制LED灯
按键按下后、led亮,按键再次按下,led灭。
#include <reg51.h>
sbit KEY1=P2^0;
sbit LED1=P1^0;
void delay_ms(unsigned int xms);
unsigned char ledFlag = 0;
void main()
{
while(1)
{
if(KEY1 == 0)
{
delay_ms(10);
if(KEY1 == 0)
{
while(KEY1==0);
ledFlag = !ledFlag;
}
}
if(ledFlag)
{
LED1 = 0;
}
else
{
LED1=1;
}
}
}
void delay_ms(unsigned int xms)
{
unsigned char i,j;
for(i=0;i<xms;i++)
for(j=0;j<110;j++);
}
2.4:数码管
2.4.1 单位数码管
八位共阳极数码管:逐渐显示0-f
#include <reg51.h>
#define SEGCA P1
void delay_ms(unsigned int xms);
unsigned char segcaDat[16] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};
unsigned char i=0;
void main()
{
while(1)
{
for(i=0;i<16;i++)
{
SEGCA=segcaDat[i];
delay_ms(200);
SEGCA=0xff;
delay_ms(200);
}
}
}
void delay_ms(unsigned int xms)
{
unsigned char i,j;
for(i=0;i<xms;i++)
for(j=0;j<110;j++);
}
2.4.2多位数码管动态显示
四位共阳极PNP驱动数码管
头文件
#ifndef __SEG_H__
#define __SEG_H__
#include <reg51.h>
#define Duan_PORT P1
sbit WEI1=P2^0;
sbit WEI2=P2^1;
sbit WEI3=P2^2;
sbit WEI4=P2^3;
void display_four(int displayNum, unsigned char delay_ms);
void display_float(int displayNum, unsigned char float_position,unsigned char delay_ms);
void display_data(int displayNum, unsigned char display_position,unsigned char delay_ms);
#endif
c文件
#include "seg.h"
#include "delay.h"
unsigned char seg_dat[] = {0xC0,0xF9,0xA4,0xB0,0x99,
0x92,0x82,0xF8,0x80,0x90};
void display_four(int displayNum,unsigned char delay_ms)
{
WEI1=0;
Duan_PORT=seg_dat[displayNum/1000%10];
delay_xms(delay_ms);
WEI1=1;
Duan_PORT=0xff;
WEI2=0;
Duan_PORT=seg_dat[displayNum/100%10];
delay_xms(delay_ms);
WEI2=1;
Duan_PORT=0xff;
WEI3=0;
Duan_PORT=seg_dat[displayNum/10%10];
delay_xms(delay_ms);
WEI3=1;
Duan_PORT=0xff;
WEI4=0;
Duan_PORT=seg_dat[displayNum%10];
delay_xms(delay_ms);
WEI4=1;
Duan_PORT=0xff;
}
void display_float(int displayNum, unsigned char float_position,unsigned char delay_ms)
{
WEI1=0;
if(float_position == 1) {Duan_PORT=seg_dat[displayNum/1000]&0x7f;}
else {Duan_PORT=seg_dat[displayNum/1000];}
delay_xms(delay_ms);
WEI1=1;
Duan_PORT=0xff;
WEI2=0;
if(float_position == 2) {Duan_PORT=seg_dat[displayNum/100%10]&0x7f;}
else {Duan_PORT=seg_dat[displayNum/100%10];}
delay_xms(delay_ms);
WEI2=1;
Duan_PORT=0xff;
WEI3=0;
if(float_position == 3) {Duan_PORT=seg_dat[displayNum/10%10]&0x7f;}
else {Duan_PORT=seg_dat[displayNum/10%10]; }
delay_xms(delay_ms);
WEI3=1;
Duan_PORT=0xff;
WEI4=0;
Duan_PORT=seg_dat[displayNum%10];
delay_xms(delay_ms);
WEI4=1;
Duan_PORT=0xff;
}
void display_data(int displayNum, unsigned char display_position,unsigned char delay_ms)
{
if(display_position == 1)
{
WEI1=0;
Duan_PORT=seg_dat[displayNum];
delay_xms(delay_ms);
WEI1=1;
} else if(display_position == 2) {
WEI2=0;
Duan_PORT=seg_dat[displayNum];
delay_xms(delay_ms);
WEI2=1;
}else if(display_position == 3) {
WEI3=0;
Duan_PORT=seg_dat[displayNum];
delay_xms(delay_ms);
WEI3=1;
} else if(display_position == 4) {
WEI4=0;
Duan_PORT=seg_dat[displayNum];
delay_xms(delay_ms);
WEI4=1;
}
Duan_PORT=0xff;
}
2.5:LCD1602液晶屏
2.6:矩阵键盘
|