单片机.docx
《单片机.docx》由会员分享,可在线阅读,更多相关《单片机.docx(21页珍藏版)》请在冰豆网上搜索。
![单片机.docx](https://file1.bdocx.com/fileroot1/2022-11/25/e43b882c-8125-4598-8f32-7c434b44ef1f/e43b882c-8125-4598-8f32-7c434b44ef1f1.gif)
单片机
第1讲C语言基础及发光二极管的点亮
1.1单片机C程序的基本组成部分
#include//头文件
sbitLED=P0^0;//引脚定义
intmain(void)//主函数,有且仅有一个
{
……//初始化语句或函数
subfunctionN(Parameter1,……)//子函数参数
while
(1)//死循环
{}
}
1.2单片机C语言的关键词简介
1.2.1数据类型
表1数据类型及相关说明
符号
功能
备注
符号
功能
备注
bit
定义位变量
0,1
unsignedint
整型
16bit
sbit
特殊位类型,位寻址
0,1
unsignedchar
字符型
8bit
sfr
特殊功能寄存器
8位,1Byte
long
长
32bit
sfr16
特殊功能寄存器
16位,2Byte
1.2.2运算符
&位与|位或^异或~取反;&&||条件判断的与或;<>n左移位n,右移位n;
1.5发光二极管的点亮
#include
sbitLED=P0^0;
intmain(void)
{unsignedintn;
while
(1)
{LED=0;
n=10000;
while(n--);
LED=1;
n=10000;
while(n--);}
}
第2讲单片机中断系统及独立按键输入
2.1单片机中断系统介绍
2.1.151单片机的中断源
参考8051中断源
参考中断系统内部结构图
2.1.1与单片机中断有关的寄存器
名称
说明
MSB
LSB
TCON
定时器/计数器控制寄存器
TF1
TR1
TF0
TR0
IE1
IT1
IE0
IT0
SCON
串行中断控制寄存器
SM0
SM1
SM2
REN
TB8
RB8
TI
RI
IE
中断允许控制
EA
X
ET2
ES
ET1
EX1
ET0
EX0
IP
中断优先级
X
X
PT2
PS
PT1
PX1
PT0
PX0
TMOD
定时器模式T1,T0
GATE
C/T
M1
M0
GATE
C/T
M1
M0
TH,TL
T1
T0
2.2单片机C语言中断系统编程
2.2.1与中断有关的关键字
ORG0000H
LJMPMAIN
ORG000BH
LJMPINT0
2B
ORG0030H
MAIN:
MOV
……
INT0:
MOV
……
RETI
1interruptm
interrupt是C51函数说明中非常重要的一个修饰符,用它修饰过的函数就是中断中断函数,这时,C51自动为函数加上汇编代码中断程序头段和尾段,并填写好中断向量表中对应的表项。
在实际程序开发中,使用中断函数是实现系统实时性、提高程序效率的重要手段。
m的取值可以为0~31,0—外部中断0;1—定时器0;2—外部中断1;3—定时器1;4—串行中断。
m*8+3
2usingn
n指中断函数使用的工作寄存器组,51里面一般有4个(R0~R7)寄存器,如果终端函数和别的程序用的不是同一个寄存器组则进入中断的时候就不会将寄存器组压入堆栈,返回时也不会弹出来。
Voiddelay(unsignedint)
VoidTimer0(void)interrupt1using0
{……
Delay(500);
……}
2.2.2中断服务程序的语法规则
中断服务程序的语法规则如下:
函数的返回值函数名([参数])interruptm[usingn]
{函数体;}
对中断程序而言,函数的返回值和参数必须为void。
interruptm中m的取值为0~31的常数,不允许用表达式,表示中断向量的编号。
usingn中n的取值为0~3的常数,不允许用表达式表示内部RAM中的工作寄存器。
外部中断INT0:
voidintsvr0(void)interrupt0using0
定时/计数器T0:
voidtimer0(void)interrupt1using0
外部中断INT1:
voidintsvr1(void)interrupt2using0
定时/计数器T1:
voidtimer1(void)interrupt3using0
串口中断:
voidserial0(void)interrupt4using0
2.2.3定时中断服务例程
利用定时中断T0的方式1,让P0.0口的发光二极管亮1秒灭1,单片机晶振为12MHz。
定时时间的计算
一个机器周期为1us,1S=1us*106=20*5*104us=20*50ms,通过定时中断定时50ms,然后软件计数器计数20次即可。
初值为216-5*104=65536-50000=15536
转化成十六进制为3CB0TH0=3C,TL0=B0;
GATA=0;C/T=0;M1M0=00;GATA=0;C/T=0;M1M0=01;TMOD=0X01
ET0;EA;TR0;
//===============================================================
//定时器0操作实验
//文件描述:
对P0口外接的1个LED灯进行操作,使其亮1秒灭1秒
//文件名:
Time.c
//硬件连接:
LED0——P0
//作者:
Sandy
//时间:
2010.06.07
//说明:
利用定时方式实现LED灯亮1秒灭1秒
//备注:
单片机晶振12MHz
//===============================================================
#include
#defineNum20
VoidINT_Initial(void);
sbitLED=P0^0;
unsignedcharTimeNum=0;
intmain(void)
{
INT_Initial();
while
(1)
……;
}
VoidINT_Initial(void)
{
TMOD=0x01;//定时器0工作方式1
TH0=0x3C;//T0赋初值,定时50ms
TL0=0XB0;
ET0=1;//开定时器0中断
EA=1;//开总中断
TR0=1;//开始计数
}
voidtimer0(void)interrupt1using0//定时器0中断
{
TH0=0x3C;//T0赋初值,定时50ms
TL0=0XB0;
TimeNum++;
if(!
(TimeNum^Num))//判断是否计时到0.5秒
{
TimeNum=0;
LED^=1;
}
}
2.4独立按键的检测程序
对于独立按键去抖动的方法一般有软件和硬件两种方式,在此只介绍软件方法。
//===============================================================
//独立按键操作实验
//文件描述:
检测独立按键
//文件名:
KEY.c
//硬件连接:
DIG1~DIG4--P1.0~P1.3,KEY1~KEY4--P3.3~P3.6
//作者:
Sandy
//时间:
2010.06.07
//说明:
独立按键,并且利用数码管显示按键值
//备注:
单片机晶振12MHz
//===============================================================
#include
unsignedcharKey=0;//Key全局变量
unsignedchardisplay[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,
0xf8,0x80,0x90};//0~9十个数字的LED编码
//===============================================================
//函数名称:
voiddelay(unsignedintN)
//函数功能:
延时程序
//入口参数:
N延时时间的长短
//出口参数:
无
//===============================================================
voiddelay(unsignedintN)
{
while(N--)
{;}
}
//===============================================================
//函数名称:
voidkey_scan(void)
//函数功能:
键盘扫描程序
//入口参数:
无
//出口参数:
无
//===============================================================
voidkey_scan(void)
{01111000P3=0110000001110000
if((P3&0x78)!
=0x78)
{
delay(1000);//去抖延时
if((P3&0x78)!
=0x78)
while((P3&0x78)!
=0x78);
Key=P3&0x78;
}
}
//===============================================================
//函数名称:
intmain(void)
//函数功能:
主程序
//入口参数:
无
//出口参数:
无
//===============================================================
intmain(void)
{
P1=0x00;//4个数码管选通
//P0=0x00;
while
(1)
{
key_scan();
switch(Key)
{
case0x70:
//K1的键值,显示1
P0=display[1];
break;
case0x68:
//K2的键值,显示2
P0=display[2];
break;
case0x58:
//K3的键值,显示3
P0=display[3];
break;
case0x38:
//K4的键值,显示4
P0=display[4];
break;
default:
P0=display[0];//无按键时,显示0
break;
}
}
}
2.5外中断和独立按键程序
//===============================================================
//单片机外部中断操作实验
//文件描述:
对外部中断进行操作,使外部中断控制LED的亮灭
//文件名:
INT1.c
//硬件连接:
KEY1--P3.3
//作者:
Sandy
//时间:
2010.06.07
//说明:
程序运行后,按一次P3.3外接的K1键,则数码管的状态改变一次
//备注:
单片机晶振12MHz
//===============================================================
#include//51芯片管脚定义头文件
#include//内部包含延时函数_nop_();
unsignedcharNum=0;
unsignedchardisplay[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,
0xf8,0x80,0x90};//0~9十个数字的LED编码
intmain(void)
{
IT1=1;//负跳变方式产生中断
EX1=1;//开外部中断1
EA=1;//开总中断
P1=0x00;
P0=display[0];
while
(1)
{
_nop_();
}
}
voidint1()interrupt2using0//外部中断1
{
Num++;
P0=display[Num];//P0状态标志
Num%=9;
}
第3讲数码管相关编
3.1数码管硬件电路
3.2单个数码管显示
3.3.1延时方式
//===============================================================
//单个数码管显示程序
//文件描述:
对数码管进行操作,使单个数码管从0~9循环显示
//文件名:
LEDS.c
//硬件连接:
无
//作者:
Sandy
//时间:
2010.06.09
//说明:
无
//备注:
无
//===============================================================
#include//51芯片管脚定义头文件
unsignedchardisplay[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,
0xf8,0x80,0x90};//0~9十个数字的LED编码
sbitDIG1=P1^0;//定于数码管的片选
voiddelay(unsignedintN)//延时程序
{
while(N--);
}
voidmain()
{
unsignedchari;
P0=0xff;//端口初始化
P1=0xff;
DIG1=0;//数码管片选有效
while
(1)
{
//for(i=0;i<10;i++)
//{
P0=display[i];
i++;
i%=10;
delay(30000);//80ms
//}
}
}
3.3.1定时方式
//===============================================================
//数码管操作实验
//文件描述:
对P0口外接的数码进行操作
//文件名:
LEDS.c
//硬件连接:
P0
//作者:
Sandy
//时间:
2010.06.09
//说明:
利用定时方式单个数码管显示,10MS点亮一次
//备注:
单片机晶振12MHz
//===============================================================
#include
#defineNum100
sbitDIG1=P1^0;
unsignedcharTimeNum=0;Show_Num=0;
unsignedchardisplay[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,
0xf8,0x80,0x90};//0~9十个数字的LED编码
intmain(void)
{
TMOD=0x01;//定时器0工作方式1
TH0=0XD8;//T0赋初值,定时50ms
TL0=0XF0;
ET0=1;//开定时器0中断
EA=1;//开总中断
TR0=1;//开始计数
DIG1=0;
while
(1);
}
voidtimer0(void)interrupt1using0//定时器0中断
{
TH0=0XD8;//T0赋初值,定时10ms
TL0=0XF0;
TimeNum++;
if(!
(TimeNum^Num))//判断是否计时到0.5秒
{
TimeNum=0;
Show_Num++;
Show_Num%=10;
P0=display[Show_Num];
}
}
3.3数码管动态扫描
//===============================================================
//数码管操作实验
//文件描述:
对P0口外接的数码进行操作
//文件名:
LEDS.c
//硬件连接:
P0
//作者:
Sandy
//时间:
2010.06.09
//说明:
利用定时方式单个数码管显示,10MS点亮一次
//备注:
单片机晶振12MHz
//===============================================================
#include
#defineNum20
sbitDIG1=P1^0;
sbitDIG2=P1^1;
sbitDIG3=P1^2;
sbitDIG4=P1^3;
unsignedcharTimeNum=0,Time=0,Hour=0,Min=0;
unsignedintShow_Num=0;
unsignedcharData[]={0,0,0,0};
unsignedchardisplay[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,
0xf8,0x80,0x90};//0~9十个数字的LED编码
intmain(void)
{
TMOD=0x01;//定时器0工作方式1
TH0=0X3C;//T0赋初值,定时50ms
TL0=0XB0;
TH1=0X1E;//T1赋初值,定时3ms
TL1=0X0C;
ET0=1;//开定时器0中断
ET1=1;//开定时器1中断
TR0=1;//开始计数
TR1=1;//开始计数
EA=1;//开总中断
DIG1=0;
while
(1)
{
;
}
}
voidtimer0(void)interrupt1using0//定时器0中断
{
TH0=0X3C;//T0赋初值,定时10ms
TL0=0XB0;
TimeNum++;
if(!
(TimeNum^Num))//判断是否计时到0.5秒
{
TimeNum=0;
Show_Num++;
Show_Num%=10000;
Data[0]=Show_Num/1000;
Data[1]=(Show_Num%1000)/100;
Data[2]=(Show_Num%100)/10;
Data[3]=Show_Num%10;
}
}
voidtimer1(void)interrupt3using0//定时器0中断
{
TH1=0X1E;//T0赋初值,定时10ms
TL1=0X0C;
switch(Time)
{
case0:
DIG4=1;
DIG1=0;
break;
case1:
DIG1=1;
DIG2=0;
break;
case2:
DIG2=1;
DIG3=0;
break;
case3:
DIG3=1;
DIG4=0;
break;
}
P0=display[Data[Time]];
Time++;
Time%=4;
}
3.4基于单片机定时器的数字钟
//===============================================================
//数码管操作实验
//文件描述:
对P0口外接的数码进行操作
//文件名:
LEDS.c
//硬件连接:
P0
//作者:
Sandy
//时间:
2010.06.09
//说明:
利用定时方式单个数码管显示,10MS点亮一次
//备注:
单片机晶振12MHz
//===============================================================
#include
#defineNum1200
voiddelay(unsignedintN);
voidkey_scan(void);
sbitDIG1=P1^0;
sbitDIG2=P1^1;
sbitDIG3=P1^2;
sbitDIG4=P1^3;
sbitDot=P0^7;
bitDot_t;
unsignedcharTime=0,Key,Hour=8,Min=40;
unsignedintTimeNum=0,Show_Num=0;
unsignedcharData[]={0,0,0,0};
unsignedchardisplay[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,
0xf8,0x80,0x90};//0~9十个数字的LED编码
intmain(void)
{
TMOD=0x01;//定时器0工作方式1
TH0=0X3C;//T0赋初值,定时50ms
TL0=0XB0;
TH1=0X0C;//T1赋初值,定时3ms
TL1=0X78;
ET0=1;//开定时器0中断
ET1=1;//开定时器1中断
TR0=1;//开始计数
TR1=1;//开始计数
EA=1;//开总中断
Data[0]=Hour/10;
Data[1]=Hour%10;
Data[2]=Min/10;
Data[3]=Min%10;
while
(1)
{
//key_scan();
switch(Key)
{
case0x70:
//K1的键值,显示1
Min++;
Min%=60;
break;
case0x68:
//K2的键值,显示2
if(Min)Min--;