单片机的基本外围电路设计以及相关C语言程序免积分.docx

上传人:b****6 文档编号:6039887 上传时间:2023-01-03 格式:DOCX 页数:97 大小:727.61KB
下载 相关 举报
单片机的基本外围电路设计以及相关C语言程序免积分.docx_第1页
第1页 / 共97页
单片机的基本外围电路设计以及相关C语言程序免积分.docx_第2页
第2页 / 共97页
单片机的基本外围电路设计以及相关C语言程序免积分.docx_第3页
第3页 / 共97页
单片机的基本外围电路设计以及相关C语言程序免积分.docx_第4页
第4页 / 共97页
单片机的基本外围电路设计以及相关C语言程序免积分.docx_第5页
第5页 / 共97页
点击查看更多>>
下载资源
资源描述

单片机的基本外围电路设计以及相关C语言程序免积分.docx

《单片机的基本外围电路设计以及相关C语言程序免积分.docx》由会员分享,可在线阅读,更多相关《单片机的基本外围电路设计以及相关C语言程序免积分.docx(97页珍藏版)》请在冰豆网上搜索。

单片机的基本外围电路设计以及相关C语言程序免积分.docx

单片机的基本外围电路设计以及相关C语言程序免积分

主要学习51单片机的外部引脚和内部结构等,叙述一下。

本书任务驱动教学,引入案例有浅变深,循序渐进,给读者留下思考和发挥空间。

3.1利用单片机的I/O口驱动LED

3.1.1利用单片机的P0.0端口驱动1只LED闪烁

编程的目的是利用C语言控制单片机I/O端口按要求输出矩形波脉冲信号,信号的周期由延时函数决定。

一、电路原理

STC-89C51单片机的P0口采用为OD门输出,不存在拉出电流,因此利用P0驱动负载时有两种接法:

一种是加上拉电阻R2,见图3-1-1,既用1K电阻接电源正极,此时P0口输出高电平时LED亮;另一种电路为P0.7低电平驱动有效,在P0.7输出低电平时,STC-89C51端口灌入电流达20mA,可直接驱动小负载。

图3-3-1中的R3为限流电阻,限制LED2的工作电流。

图3-1-1驱动LED电路原理

单片机的最小系统包括晶体振荡电路,加电复位电路,同时要求单片机的31引脚接高电平。

时钟频率主要由晶体CY决定,C1、C2为独石电容,用于微小调整单片机时钟的振荡频率;R1和C3组成加电复位电路,C3为电解电容器;整个电路由+5V电压供电。

电路使用的元件参数见表3.1.1。

表3.1.13-1-1电路元件表

元件名称

序号

标称

规格(封装,功率电压等参数)

作用

单片机

IC

STC89C51

DIP40

核心芯片

电容器

C1

30PF

独石

振荡

电容器

C2

30PF

独石

振荡

电容器

C3

10F

点解电容器

复位

晶振

CY

12MHz

S型

振荡

电阻

R1

1K

1/4W,金属膜

电容器C3放电电阻

电阻

R2

1K

1/4W,金属膜

端口电位上拉电阻

电阻

R3

1K

1/4W,金属膜

限流电阻

发光二极管

LED1

5

红色高亮

显示

发光二极管

LED2

5

红色高亮

显示

二、程序设计

1.程序设计平台

程序设计采用keilC软件,为了养成一个良好的文件管理习惯,建议:

编程前,在计算机的某个硬盘分区下建立一个目录,目录的名字为你编写程序的主题,然后把keilC产生的所有文件都放在该目录下。

程序设计步骤如下:

(1)运行keilC,创建一个项目。

利用keilC菜单栏中project-newproject创建,项目的名字为你编程的主题,如本案例可以用“LED_1.uv2”或“一个LED闪烁实验.uv2”,存放目录为你的主题目录下;

(2)创建建一个文件,然后以“.c”后缀名,文件存放在你的主题目录下;

(3)把c文件添加在你的项目中,在projectworkspace窗口利用addfiletogroup…实现。

如果软件界面不显示这个窗口,运行keilC菜单栏中的view-projectwindow。

(4)设置编译器,是编译过程中能生成“.hex”文件。

默认文件名与主题名字相同。

运行project-optionfor‘target1’-output窗口下点击createHEXfile。

(5)在编程区域写你的程序,结束后存储文件并编译,要做检查,尽量避免警告出现,直到程序编译无误为止。

(6)程序烧写并试运行。

这个过程称为软件和硬件联合调试,如果实验板无误,程序编译通过,但在硬件上运行不成功是常用的事情,需要对程序进行多次调试。

在没有实验板的情况下,可以利用proteus软件仿真调试,也可以检验你的程序设计结果。

2.程序设计

(1)利用P0.0口驱动LED闪烁,高电平有效

/*****************************************************************************/

#include//包含头文件

sbitLED=P0^0;//LED接P0.0。

在kellC51软件中,定义P0.0为P0^0,

voiddelay(unsignedcharx)//延时函数

{

unsignedchari,j;

for(i=0;i

for(j=0;j<200;j++);

}

voidmain(void)//主函数

{

While

(1)//程序死循环

{

LED=0;//P0.0输出低电平,LED灭

voiddelay(100);//调用延时函数,延时一段时间,约0.3秒,不精确

LED=1;//P0.0输出高电平,LED亮

voiddelay(100);

}

}

/*****************************************************************************/

(2)利用P0.7端口驱动LED闪烁,低电平有效

/*****************************************************************************/

#include//包含头文件,程序为小5号字

sbitLED=P0^7;

voiddelay(unsignedcharx)//延时函数

{

unsignedchari,j;

for(i=0;i

for(j=0;j<1000;j++);

}

voidmain(void)//主函数

{while

(1)

{

LED=~LED;//LED初始状态为灭,执行一次,LED改变一次状态

voiddelay(100);//延时一段时间

}

}

/*****************************************************************************/

三、程序说明

1.应为使用的单片机芯片为STC89C51,因此程序开始处加入#include,文件reg51.h中包含了51芯片所有特殊功能寄存器的名称定义和相对应的地址值;

2.单片机程序单步顺序执行,先执行主函数,在主函数可以调用分函数,分函数可以调用分函数,但分函数不能调用主函数,程序执行一条命令再执行下一条,单片机等待的过程是执行了一个循环命令或一个浪费时间的程序,实际执行过程永远不会结束。

delay()为函数延,单片机在执行此函数相关指令时占用的时间过长,在执行过程中,如果没有中断,单片机只能忙这一件事情。

利用delay()不能得到精确的延时。

延时函数还可以利用下面的函数实现。

/**************************/

voiddelay(unsignedintx)

{

while(x)

x--;

}

/**************************/

3.利用位定义命令让LED等价于P0.0或P0.7,等于先sbitP0_0=P0^0,然后#definedLEDP0_0,也在程序前面不做此类定义,在程序里面直接写成P0^0=1或P0^0=0,先定义是为了增加程序的可读性。

程序执行P0^0=1后,P0.0对以的单片机内部位寄存器就设置为高电平,同时P0.0端口也输出高电平,单片机的所有I/O口都可位未定义,也可以字节定义。

4.单片机C语言程序设计需要的C语言关键字不多,并且在keilC中用到的关键字是独有的,因此对于没有学习过C语言的人学习单片机C语言程序设计困难并不是很大,主要掌握单片机C语言书写格式,怎样用C语言控制单片机的硬件资源,另外在编程时,还要有清晰的逻辑思维头脑和认真实践,由浅逐步深入学习,当你坚持到最后时,单片机C语言程序设计实际上很简单。

5.每个人在编写程序时都有自己的风格。

一般情况下,函数的字符左行距为0,其下每条语句前留一个“tab”键空。

算数逻辑符号的左右留一个空格,关键语句要有中文或英文说明,每一个函数有时也可以用“/**.....**/”上下隔开这样有助于提高程序的层次感和可读性。

3.1.2利用P0口驱动8个LED,产生跑马灯或流水灯效果

一、参考电路

实验电路见图3-3-2所示,在单片机的最小系统的基础上,P0口依次接入8个LED,P0口的上拉电阻可以使用8个1K电阻。

图3-1-2流水灯电路

在利用Proteus软件仿真时,可以用电阻排代替。

单片机最小系统在单片机元件放置后已经默认,即C1、C2、C3、CY、R1可以省略。

其它元件选取见表3.1.2所示。

表3.1.13-1-2电路Proteus软件元件表

元件名称component

总类Category

分类Sub-Category

结果Results

模型Modeltype

单片机

MicoroprocessorIC

8051Family

80C51

电阻排

Resistor

ResistorPack

RESPACK-8

ANALOG

发光二极管

Optoelectronics

LEDs

led-red

DIGITAL

二、参考程序

/*****************************************************************************/

#include

voiddelay(void)

{

unsignedchari,j;

for(i=0;i<255;i++)for(j=0;j<255;j++);

}

voidmain(void)

{

unsignedcharj=0x01;

while

(1)

{

j=j<<1;

if(j==0x00)j=0x01;

P0=j;

delay();

}}

/*****************************************************************************/

三、程序说明

1.语句j=j<<1,执行的目的是控制P0整个字节的数据在循环时左移变化,程序循环第一次,P0=0x02,P0.1连接的LED亮,其它灭;循环第七次,P0.7连接的LED亮,其它灭;循环第八次,j=0x00,if语句条件满足,j=0x01,P0.0连接的LED亮,其它灭,然后依次变化下去。

如果P0口驱动8个LED低电平有效,如下修该:

/**********************/

voidmain(void)

{

unsignedcharj=0xfe;

while

(1)

{

j=(j<<1)|0x01;

if(j=0xff)j=0xfe;

P0=j;

delay();

}}

2.delay()函数无形参,延时时间不能设置。

3.1.3利用P0口驱动一个数码管,显示0–9,并循环

一、参考电路

实验电路在单片机的最小系统基础上,P0口接一只共阳数码管,见图3-1-3。

带小数点的数码管是由8个LED组成,七个LED组成数字,另一只LED用来显示小数点。

如果数码管内部的8只LED的正极接在一起,负极分别引出,引脚依次命名为a、b、c、d、e、f、g和dot,称为带小数点的7段共阳极性数码管。

图3-1-3单片机驱动共阳数码管电路

单片机的P0.0-P0.7口分别接数码管的a-dot引脚,如果让数码管显示1,数码管b、c段亮,程序控制P0输出0xbe十六进制编码即可,因此共阳数码管显示0-9十进制数字,需要利用10个显示码组成的数组。

对于共阴数码管,也有相应的编码要求。

小数点在不用时一般不让显示,高位端口P0.7输出高电平即可。

由于P0每个端口的灌电流达20mA,数码管每段LED正常显示5mA即可,因此需要R2~9用来限制数码管每一段电流,以防止驱动电流过大而烧毁器件。

利用Proteus软件仿真时,数码管采用Optoelectronics元件库中7-SegmentDisplays下的7-SEG-COM-ANODE。

二、参考程序

/*****************************************************************************/

#include

codeunsignedcharseven_seg[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

voiddelay(void)/*时间延迟函数*/

{

unsignedchari,j;

for(i=0;i<255;i++)for(j=0;j=255;j++);

}

voidmain(void)

{

unsignedchari;/*变量i用来储存0~9*//*无穷循环*/

while

(1)

{

for(i=0;i<10;i++)

{

P0=seven_seg[i];/*输出0~9到共阳七段显示器*/

delay();/*调用时间延迟函数delay*/

}}}

/*****************************************************************************/

三、程序说明

1.当程序中使用常量数据时,可以把数据存储在单片机的程序存储器中,对此类数据声明时,前面需要加上关键字code或const,如本实验中的共阳数码管数字显示需要的编码,表3-1-3是共阳数码管编码,表3-1-4是共阴数码管编码。

单片机驱动液晶显示器显示的汉字也是一种常量数据。

表3-1-3共阳数码管显示编码

显示数字

dot

g

f

e

d

c

b

a

16进制

0

1

1

0

0

0

0

0

0

0xc0

1

1

1

1

1

1

0

0

1

0xf9

2

1

0

1

0

0

1

0

0

0xa4

3

1

0

1

1

0

0

0

0

0xb0

4

1

0

0

1

1

0

0

1

0x99

5

1

0

0

1

0

0

1

0

0x92

6

1

0

0

0

0

0

1

0

0x82

7

1

1

1

1

1

0

0

0

0xf8

8

1

0

0

0

0

0

0

0

0x80

9

1

0

0

1

0

0

0

0

0x90

表3-1-4共阴数码管显示编码

显示数字

dot

g

f

e

d

c

b

a

16进制

0

0

0

1

1

1

1

1

1

0x3f

1

0

0

0

0

0

1

1

0

0x06

2

0

1

0

1

1

0

1

1

0x5b

3

0

1

0

0

1

1

1

1

0x4f

4

0

1

1

0

0

1

1

0

0x66

5

0

1

1

0

1

1

0

1

0x6d

6

0

1

1

1

1

1

0

1

0x7d

7

0

0

0

0

0

1

1

1

0x07

8

0

1

1

1

1

1

1

1

0x7f

9

0

1

1

0

1

1

1

1

0x6f

2.本程序数码管显示使用了一个for循环,让变量i依次由0递增到9,并将数字显示码送到P0,需要注意,seven_seg[10]有10各数据,seven_seg[0]为第一个数据,seven_seg[9]为第10个数据。

数码管显示的数据变化时间由延时函数决定。

for循环体嵌套在while循环体中,数码管回循环显示0~9,永不结束,除非电路断电。

利用数码管也可以显示日期和时间,在以后的程序设计案例中就可以学到。

3.2单片机定时器/计数器应用

3.2.1利用Timer0中断产生1秒延时,让数1个码管显示秒计数

本案例主要目的是熟练掌握单片机内部Timer0或Timer1的编程控制方法,会利用Timer0或Timer1中断精确定时。

同时掌握数码管动态显示原理,学会6位数字显示的程序设计。

本案例使用的电路为图3-1-3。

一、程序设计

/*****************************************************************************/

#include

codeunsignedcharseven_seg[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

unsignedcharcp,i;//声明全局变量

voidtimer0_isr(void)interrupt1//timer0中断服务函数

{

TR0=0;//停止计数

TL0=0x11;//TL0重新预置

TH0=0xee;//TH0重新预置

TR0=0;//开始计数

cp++;//timer0中断1次,变量cp加1

if(cp==200)//中断200次,时间刚好为1秒

{cp=0;i++;}

if(i==10)i=0;

P0=seven_seg[i]//P0输出显示数据

}

voidtimer0_initialize(void)//timer0中断初始化函数

{

EA=0;//设置中断允许寄存器IE中的EA位,关闭中断总开关

TMOD=0x01;//设置计时器模式控制寄存器,Time0工作在定时方式1

TR0=0;//设置计时器控制寄存器TCON寄存器的TR0位为0,Timer0

//停止计数

TL0=0x11;

TH0=0xee;//Timer0的16位计数器初始值为0xee11,12MHz晶体振

//频率,单片机的机器周期为1微妙,Timer0每1微秒加1

//计数,加满溢出变产生中断,从计数到中断刚好为5毫秒

PT0=1;//设置中断优先次序寄存器IP中的PT0位,Timer0中断优先

ET0=1;//设置中断允许寄存器IE中ET0的位,开启中断小开关

EA=1;//打开中断总开关

TR0=1;//开始计数

}

voidmain(void)

{

timer0_initialize()//timer0初始化,为中断做好准备

while

(1);//等待中断

}

/*****************************************************************************/

二、程序说明

1.中断服务函数名中,interruput为关键字,1为timer0中断号。

在reg51.h头文件中已经定义,表3.2.1为单片机常用中断的中断号。

在使用中断服务函数时,直接在名后加interruput和中断号即可。

表3.2.1reg51.h中单片机常用中断号定义

中断源

中断触发原因

中断号

INT0

外部INT0引脚有低电平或下降沿信号输入

0

Timer0

Timer0计数溢出

1

INT1

外部INT0引脚有低电平或下降沿信号输入

2

Timer1

Timer1计数溢出

3

串行中断

串口缓存SBUF写入数据或读出数据

4

2.timer0可以用作计数,也可以用来定时,由由TMOD寄存器中

为决定,作为计数器使用时,接受单片机外部引脚P3.4输入的脉冲加计数;作为定时器使用时,接受单片机内部的机器周期脉冲。

如果单片机的振荡频率为,振荡周期为

,则机器周期为

本案例中

MHz,则

微秒,timer0工作在模式1为16为加计数器,当计数器初始值为0xee11时,则从开始计数到产生中断需要的时间为0xffff—0xee11个微秒,刚好为5000微秒,也即5毫秒。

本案例timer0的初装也可以利用下面语句完成:

/**********************************/

#definedTEMOR0_COUNT0xee11

TL0=TEMOR0_COUNT&0x00ff;//取TEMOR0_COUNT的低字节并装入TL0

TH0=TEMOR0_COUNT>>8;//TEMOR0_COUNT左移8位,并将低字节装入TEMOR0_COUNT

/**********************************/

利用定时器/计数器定时时,需要现设置工作模式,并计算它的初装值,计算初装值不好计算,常利用计算机中的计算器工具辅助。

timer0工作在模式1可以最大65535微秒中断1次,如工作模式2,最大256微秒中断1次。

3.当程序中只涉及一个中断时,可以不对中断的优先级进行设置,因此在本案例中语句PT0=1可以省略。

程序中有多个中断但没有进行优先级设定的情况下,单片机中断优先级默认按终端号递增而依次降低。

4.数码管显示语句放在了timer0中断服务函数里面,由于5毫秒中断1次,因此数码管显示的数据会每5毫秒更新1次。

1秒内更新200次,更新过程是把原来的数据覆盖,但显示数据1秒内变化1次。

3.2.2利用4个数码管,实现秒信号加计数

一、电路原理

图3-2-1所示的电路中,4位七段数码管采用4只单个数码管组成,可以显示0000~9999,数据输入端并联后接P0口,位选即每个数码管的阳极分别接P2口,中间加非门驱动。

因为P2口反相驱动,因此,如果千位数码管显示,P2.7输出低电平,P2的其它端口输出高电平,并且此时P0输出千位数据。

在利用Proteuse软件仿真时,数码管SEVEN_SEG使用7SEG-MPX4-CA,非门NOT选用74HCseries类型中Gates&Inverters分类下的74HC04。

电阻R2~9是限流电阻。

图3-2-14位七段数码管显示

二、程序设计

/*****************************************************************************/

#include

#definedunsignedcharuchar

#definedunsignedintuint

codeucharseven_seg[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

codeucharseg_scan[4]={0xef,0xdf,0xbf,0x7f};//各个数码管对应的位选数据

ucharcounter[4]={0,0,0,0};//个位、十位、百位和千位数

uintcp,i;

voidtimer0_isr(v

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1