一、P1 单片机设计与开发—概述
1.单片机内核资源
2.单片机基本组成
二、P2—LED灯的基本控制
1.蓝桥杯单片机LED接口
(要通过锁存器的选通,不能直接通过P0口,还要通过译码器)
2.74HC138译码器(三八译码器):
三个输入控制八路互斥的低有效输出
功能表记忆:CBA对应421,二进制转十进制
3.74HC573锁存器(573)
八路3态输出的非反转透明锁存器;当锁存使能端LE为高时,这些器件的锁存对于数据是透明的(也就是说输出同步)。当锁存使能变低时,符合建立时间和保存时间的数据会被锁存。
即LE为高电平H时,输出端打通,D1~B8=Q1~Q8
LE为低电平L时,输出端锁存,无论D1~B8如何变化,Q1~Q8始终不变
(H高电平,L低电平,X任意电平)
4.LED指示灯电路原理
或非门输出1→Y4输入0(WR接地是0,先或之后再取反输出)
整体逻辑:P25P26P27控制Y4的值,Y4通过或非门控制Y4C的值,Y4C决定573输出端是否接通,从而才可通过改变P0端控制LED
LED阳极接电源,阴极接573→输出0点亮LED灯
5.代码
1)头文件+管脚定义
#include "reg52.h"
sbit HC138_A=P2^5;
sbit HC138_B=P2^6;
sbit HC138_C=P2^7;
2)DELAY函数
void Delay(unsigned int t)
{
while(t--);
while(t--);
}
3)LED运行函数
void LEDRunning()
{
//使得Y4口输出为0,通过或非门使得Y4C输出1,使得573处于输出同步状态(未锁存)
HC138_C=1;
HC138_B=0;
HC138_A=0;
//控制LED全部循环闪烁
P0=0x00;
Delay(60000);
Delay(60000);
P0=0xff;
Delay(60000);
Delay(60000;)
//LED流水灯(点亮版本)
for(i=1;i<=8;i++)
{
P0=0xff<<i;
Delay(60000);
Delay(60000);
}
//LED流水灯(熄灭版本)
for(i=1;i<=8;i++)
{
P0=~(0xff<<i);
Delay(60000);
Delay(60000);
}
}
三、P3—蜂鸣器与继电器的基本控制
1.蜂鸣器和继电器电路
蜂鸣器正极接到电源(VCC),另一个管脚给·低电平蜂鸣器就会叫高电平就不会
继电器控制端(N RELAY)给低电平,继电器就会吸合(二极管起保护作用)
2.ULN2003(达林顿管)
起到缓冲和驱动的作用,可理解为一个放大倍数比较大的三极管
中间是非门:输入1输出0,输入0输出1
3.整体思路:
改变P25P26P27→Y5输出低电平→通过或非门使得Y5C高电平→LE高电平,573输出端属于接通状态→可用P0口控制达林顿管→使对应输出端变为高电平1(N RELAY/N BUZZ)→蜂鸣器叫/继电器吸合
4.代码
1)初始化无关设备
void InitSystem()
{
//Y5输出低电平
HC138_C=1;
HC138_B=0;
HC138_A=1;
//蜂鸣器和继电器不接通
P0=0x00;
}
2)锁存器函数
void InitHC138(unsigned char n)
{
switch(n)
{
case 4:
HC138_C=1;
HC138_B=0;
HC138_A=0;
break;
case 5:
HC138_C=1;
HC138_B=0;
HC138_A=1;
break;
case 6:
HC138_C=1;
HC138_B=1;
HC138_A=0;
break;
case 7:
HC138_C=1;
HC138_B=1;
HC138_A=1;
break;
}
}
简化代码:
void InitHC138(unsigned char n)
{
switch(n)
{
case 4:
P2=(P2&0x1f)|0x80;
break;
case 5:
P2=(P2&0x1f)|0xa0;
break;
case 6:
P2=(P2&0x1f)|0xc0;
break;
case 7:
P2=(P2&0x1f)|0xe0;
break;
}
}
3)573/P0口输出函数
void OutPutP0(unsigned char channel,unsigned char dat)
{
InitHC138(channel);
P0= dat;
}
四、P4—共阳数码管的静态显示
1.数码管的电路分析
Y7C、Y6C=138译码器的Y7和Y6输出(Y7控制段码,Y6控制公共端)
com口:要高电平才能点亮
2.数码管显示
共阳:所有数码管的阳极都接在一起,要点亮数码管就要把数码管的阴极接低电平
3.代码
1)段码
//0-9+B-F+-+.
unsigned char code SMG_duanma[18]=
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,
oxbf,ox7f};
2)点亮数码管
void ShowSMG_Bit(unsigned char dat,unsigned int pos)
{
//数码管的位置
InitHC138(6);
P0=0x01<<pos;
//数码管的内容
InitHC138(7);
P0=dat;
}
五、共阳数码管的动态显示
1.运用人眼的视觉暂留现象以及发光二极管的余晖效应
2.代码
1)138译码器的通道选择(即选择锁存器)(决定公共端)
void SelectHC573(unsigned char channel)
{
switch(channel)
{
case 4:
P2=(P2&0x1f)|0x80;
break;
case 5:
P2=(P2&0x1f)|0xa0;
break;
case 6:
P2=(P2&0x1f)|0xc0;
break;
case 7:
P2=(P2&0x1f)|0xe0;
break;
}
}
2)数码管静态显示
void DisplaySMG_Bit(unsigned char value,unsigned char pos)
{
//接通公共端,选择点亮哪个数码管
SelectHC573(6);
P0=0x01<<pos;
//接通段码端,选择数码管显示的数字
SelectHC573(7);
P0=value;
}
3)数码管的延时函数
void DelaySMG(unsigned char t)
{
while(t--);
}
4)数码管的动态显示
void Display_Dynamic()
{
DisplaySMG_Bit(SMG_duanma[2],0);
DelaySMG(500);
DisplaySMG_Bit(SMG_duanma[0],1);
DelaySMG(500);
DisplaySMG_Bit(SMG_duanma[1],2);
DelaySMG(500);
DisplaySMG_Bit(SMG_duanma[8],3);
DelaySMG(500);
}
5)避免中断,进行判断
void Delay(unsigned char t)
{
while(t--)
{
Display_Dynamic();
}
}
void main()
{
while(1)
{
Display_Dynamic();
yu++;
yu%12;
Delay();
}
}
六、P6—独立按键的基本操作与扩展应用
1.启用独立按键:
首先将J5处的跳帽接到2~3引脚,使按键S4~S7四个按键的另一端接地从而成为四个独立键盘。在扫描按键的过程中,发现有按键触发信号后,先做去抖动处理,当确认为按键按下时,才进行相应的功能处理
2.独立按键的电路:
按下为低电平,松开为高电平
3. 代码
1)定义管脚
//定义独立按键
sbit S7=P3^0;
sbit S6=P3^1;
sbit S5=P3^2;
sbit S4=P3^3;
//定义LED
sbit L1=P0^0;
sbit L2=PO^1;
sbit L3=P0^2;
sbit L4=P0^3;
sbit L5=P0^4;
sbit L6=P0^5;
2)延时函数
void DelayK(unsigned char t)
{
while(t--);
}
3)独立按键扫描
void ScanKeys_Alone()
{
if(S7==0)
{
DelayK(100);
if(S7==0)
{
L1=0;
while(S7==0);//按键松手检测
L1=1;
}
}
}
4)定义状态量
unsigned char stat_k=0;
void ScanKeys_Alone()
{
if(S7==0)
{
DelayK(100);
if(S7==0)
{
if(stat_k==0)
{
L1=0;
stat_k=1;
}
else if(stat_k==1)
{
L1=1;
stat_k=0;
}
}
while(S7==0);
}
}
七、P7—矩阵键盘的扫描原理与基本应用
1.启用矩阵键盘
首先将J5处的跳帽接到1~2引脚,使按键S4~S19按键组成4X4的矩阵键盘。在扫描按键的过程中,发现有按键触发信号后(不做去抖动),待按键松开后,在数码管的第一位显示相应的数字。
2.矩阵键盘的电路图
3.按键的内部结构
按键按下是什么电平取决于单片机I/O口(即图中左侧I/O口的电平)
4.结构图
输出低电平0即选中,即对应按键按下
5.代码
1)矩阵键盘扫描
//使R1、R2、R3、R4轮流为0,判断C1C2C3C4有无低电平
sfr P4=0xc0;
sbit R1=P3^0;
sbit R2=P3^1;
sbit R3=P3^2;
sbit R4=P3^3;
sbit C4=P3^4;
sbit C3=P3^5;
sbit C2=P4^2;
sbit C1=P4^4;
unsigned char key_num;
void ScanKeysMulti()
{
R1=0;
R2=R3=R4=1;
C1=C2=C3=C4=1;
if(C1==0)
{
while(C1==0)
key_num=1;
}
else if(C2==0)
{
while(C2==0)
key_num=2;
}
else if(C3==0)
{
while(C3==0)
key_num=3;
}
else if(C4==0)
{
while(C4==0)
key_num=4;
}
R2=0;
R1=R3=R4=1;
C1=C2=C3=C4=1;
if(C1==0)
{
while(C1==0)
key_num=5;
}
else if(C2==0)
{
while(C2==0)
key_num=6;
}
else if(C3==0)
{
while(C3==0)
key_num=7;
}
else if(C4==0)
{
while(C4==0)
key_num=8;
}
R3=0;
R1=R2=R4=1;
C1=C2=C3=C4=1;
if(C1==0)
{
while(C1==0)
key_num=9;
}
else if(C2==0)
{
while(C2==0)
key_num=10;
}
else if(C3==0)
{
while(C3==0)
key_num=11;
}
else if(C4==0)
{
while(C4==0)
key_num=12;
}
R4=0;
R1=R2=R3=1;
C1=C2=C3=C4=1;
if(C1==0)
{
while(C1==0)
key_num=13;
}
else if(C2==0)
{
while(C2==0)
key_num=14;
}
else if(C3==0)
{
while(C3==0)
key_num=15;
}
else if(C4==0)
{
while(C4==0)
key_num=16;
}
}
八、P8—中断系统与外部中断应用
1.相关概念
中断服务函数:内核响应中断后执行的相应处理程序
中断向量:中断服务程序的入口地址。每个中断源都对应一个固定的入口地址。当内核响应中断请求时,就会暂停当前的程序执行,然后跳转到该入口地址执行代码
2.中断的响应过程
3.中断源(自然优先级由高到低)
1)外部中断0:INT0
2)定时/计数器0:TF0
3)外部中断1:INT1
4)定时/计数器1:TF1
5)串口中断:R1/T1
(定时对内部,计数对外部脉冲计数)
4.中断系统的结构
IT=1时,选择变沿(下降沿信号)触发;IT=0时,选择电平(低电平信号)触发
1)IE:中断控制寄存器(中断的开关)
EA:总开关,总中断
5.中断号
0→INTO
1→TF0
2→INT1
3→TF1
4→R1/T1
6.中断相关的寄存器
每个寄存器都是可以位寻址的
1)控制寄存器
2)中断请求标志
7.中断服务函数程序的编写
1)中断函数没有返回值,也不能带参数
2)函数名后要跟一个关键字interrupt,说明这是一个中断服务函数
3)在关键字interrupt后面要跟上中断号,说明这个中断服务函数是为那个中断
4)格式:
void 函数名() interrupt 中断号
{
——————函数体——————
}
8.引脚图
9.代码
1)初始化函数
void Init_INT0()
{
IT0=1;//下降沿触发
EX0=1;//中断使能打开
EA=1;//总中断打开
}
2)中断服务函数
void ServiceINT0() interrupt 0
{
L8=0;
Delay(60000);
L8=1;
}
3)中断服务函数中更改变量,查询中断
只会在L8熄灭时执行中断函数←在L8=1函数后面查询中断
适用于需完成整个程序再进行中断
unsigned char stat_int=0;
void ServiceINT0() interrupt 0
{
stat_int=1;
}
void LEDINT()
{
if(stat_int==1)
{
L1=1;
Delay(60000);
L1=0;
}
stat_int=0;
}
int main()
{
L8=0;
Delay(60000);
L8=1;
LEDINT();
}
九、P9—定时器的原理和基本应用
1.组成:
有两个定时/计数器T0和T1,为16位加法计数器,由低8位TLx和高8位THx两个寄存器组成,最大计数值位65535个计数脉冲
2.使用计数器(计算计数初值)
高8位/,低8位%
3.相关寄存器
1)TMOD模式控制寄存器
不能进行位寻址,只能字节操作
2)TCON中断标志寄存器
4.编程思路
1)初始化函数
a.配置工作模式,即对TMOD寄存器编程。
b.计算技术初值,即对THx和TLx寄存器进行赋值。
c.使能定时/计数器中断,即ETO或ET1置1
d.打开总中断,即EA =1
e.启动定时器,即TRO或TR1置1
2)中断服务函数
a.如果不是自动重装模式,需要对THx和TLx重新赋值。
b.进行间隔定时到达的逻辑处理 (越少越好)。
5.代码
1)初始化函数
void InitTimer0()
{
TMOD=0x01;
//单次计时50ms
THO=(65535-50000)/256;
TLO=(65535-50000)%256;
ET0=1;
EA=1;
TR0=1;
}
2)中断服务函数
//长计时实行累加的方法
unsigned char count=0;
void ServiceTimer0() interrupt 0
{
//重新初始化计数初值
THO=(65535-50000)/256;
TLO=(65535-50000)%256;
count++;
if(count==10)
{
L1=~L1;
count=0;
}
}
十、P11—PWM脉宽调制信号的发生与控制
1.概念:
脉冲宽度调制:利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术
占空比:指高电平在周期中的占比
2.代码(用定时器实现)
//每次中断是100us,一共有100次中断(100us*100=10000us=10ms=0.01s=100hz),若占空比=60%,那高电平占60次中断,低电平占40份
//定义占空比
unsigned char pwm_duty;
if(count<=pwm_duty)
{
L1=0;
}
else if(count<100)
{
L1=1;
}
else if(count==100)
{
L1=0;
count=0;
}
十一、P12—串口通信的基本原理与应用
1.串行通信概述:
1)微控制器与外部设备的数据通信,根据连线结构和传送方式的不同,可以分为两种:
并行通信和串行通信
a.并行通信:
数据的各位同时发送或接收,每个数据位使用一条导线
b.串行通信:
数据一位接一位地顺序发送或接收
2)分类:
SPI、IIC、UART(大多数)
3)制式:
单工、半双工、全双工(RS485总线是半双工)(发送和接收数据)
4)主要方式:
同步和异步
a.同步串行通信:
使用同一个时钟,以数据块为单位传送数据
b.异步串行通信:
每个设备都有自己的时钟信号,通信中双方的波特率要保持一致,以字符为单位进行数据帧传送,一次传送一个帧
2.关于波特率的计算
波特率:串口每秒钟传输的位数
51单片机的串口通信,模式1和模式3的波特率是可变的,取决于定时器1的溢出率,也就是说定时器1每溢出1次,串口就发送一次数据
通常使用定时器1的工作模式2(8位自动重装)来产生波特率,TL1作为脉冲计数寄存器,TH1作为自动重装寄存器,当计数到最大值溢出时,TH1的值会自动装到TL1中
3.UART口的数据发送与接收
4.串口控制寄存器SCON
SMO、SM1、SM2:设置工作模式(对应最下面四行)
异步8位UART并且允许接收:SCON=0x50;
对于IAP15F2K61S2单片机,还要对辅助寄存器AUXR(0x8e)进行设置
5.代码
1)初始化
sfr AUXR=0x8e;//定义辅助寄存器
void InitUart()
{
//用高8位计时器(T1计时器)
TMOD=0x20;
TH1=0xfd;
TL1=0xfd;
TR1=1;
SCON=0x50;
AUXR=0x00;
ES=1;
EA=1;
}
2)中断服务函数
unsigned char urdat;
void ServiceUart() interrupt 4
{
if(RI==1)
{
RI=0;
urdat=SBUF;
}
}
3)发送查询
//dat:为16进制形式
void SendByte(usnigned char dat)
{
SBUF=dat;
while(T1==0);
TI=0;
}