嵌入式工作室校级电赛前培训

<p>校电赛前培训—中断<br/></p><p>刚从烟台玩回来就花了两天时间跟大一同学一起准备即将到来的校电赛,花了一些时间准备了教学内容,还是先讲中断。中断在单片机学习系统中算是比较基础的内容,学会的同学可能会觉得很简单,而且我这里举的例子也将非常简单,写这篇的目的还是留着以后工作室新同学学习时使用。</p><p>这次用了一个小程序做例子,来源是同学大创,智能卫生间,需要一个定时冲水的功能,我们这个例子实现的就是,当人体传感器检测到有人经过后,控制蜂鸣器鸣叫一定时间(2s),使用外部中断和定时器中断实现,希望对初学者起到帮助作用。</p><p>本实验的接线情况如下,可以使用独立按键代替人体传感器,发光二极管代替蜂鸣器。</p><p><img src="{#ZC_BLOG_HOST#}zb_users/upload/2019/05/5ccc5faa48d5e871142659.png" alt=""/></p><p>功能和接线都很简单,实现起来也不难。下面放出代码并逐句分析,写写自己的理解,作者水平不高,上课也没认真听,有误之处多多指正。</p><p>&nbsp;</p><p>&nbsp;</p><pre class="prism-highlight prism-language-c">//嵌入式工作室5月2日教学例程

//学习使用外部中断和定时器中断

//此代码适用于51单片机

#include&nbsp;&lt;AT89X52.h&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//调用51单片机的头文件

unsigned&nbsp;char&nbsp;q&nbsp;=&nbsp;0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;

unsigned&nbsp;char&nbsp;p&nbsp;=&nbsp;0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//定义两个变量用于循环计次

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//控制蜂鸣器鸣叫时间,在定时器服务程序中体现

//---------------------------------------

//名称:外部INT0中断服务程序

//---------------------------------------

void&nbsp;INIT0(void)&nbsp;interrupt&nbsp;0&nbsp;

{

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;P0&nbsp;=&nbsp;1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//将P0.0~P0.7引脚置高电平,蜂鸣器鸣叫

&nbsp;&nbsp;&nbsp;&nbsp;q=0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//

&nbsp;&nbsp;&nbsp;&nbsp;p=0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//清空计次变量,实现每次感应到人体蜂鸣器鸣叫的时间相同

}

//---------------------------------------

//名称:定时器T0中断服务程序

//---------------------------------------

&nbsp;

void&nbsp;Timer0(void)&nbsp;interrupt&nbsp;1&nbsp;

{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//在本例中具体多少秒进入定时器中断与单片机所用晶振、定时器初值有关,不详细计算了

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;q++;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//每次进入中断给q加1

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(q&gt;=250)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//给q加1&nbsp;250次之后判断通过

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p++;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//给p加1

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;q=0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//清零q,以备再次被250次加1

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(p&gt;=10)&nbsp;&nbsp;&nbsp;&nbsp;//经过250*10次进入定时器中断后,执行下列代码

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p=0;&nbsp;&nbsp;&nbsp;&nbsp;//清零计次变量p

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P0=&nbsp;0;&nbsp;&nbsp;//关掉蜂鸣器

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;

&nbsp;

&nbsp;

}

&nbsp;

&nbsp;

//---------------------------------------

//名称:&nbsp;主函数

//---------------------------------------

void&nbsp;main(void)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//主函数,单片机开机后就是从这个函数开始运行

{

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//***定时器Timer0初始化***

&nbsp;&nbsp;&nbsp;&nbsp;TMOD&amp;=0xF0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//将TMOD的低4位定时器0控制部分清零

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//达到重置TMOD目的,清除其原有值

&nbsp;&nbsp;&nbsp;&nbsp;TMOD|=0x02;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置定时器0为方式2&nbsp;&nbsp;0000&nbsp;0010

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//这里用|=是为了不改变其他已经因为其他需求被置1的位

&nbsp;&nbsp;&nbsp;&nbsp;TL0=0x47;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置定时器0初值,每次内部脉冲都会使此寄存器加1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0100&nbsp;0111

&nbsp;&nbsp;&nbsp;&nbsp;TH0=0x47;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设定重装初值,在工作模式2下,每次定时器溢出就会将此值重装至TL0

&nbsp;&nbsp;&nbsp;&nbsp;TR0=1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//启动定时器0,即启动计时

&nbsp;&nbsp;&nbsp;&nbsp;ET0=1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//Timer0中断允许,允许定时器T0向CPU发送中断请求

&nbsp;&nbsp;&nbsp;&nbsp;//**********************

&nbsp;&nbsp;&nbsp;&nbsp;//***外部中断INT0初始化***

&nbsp;&nbsp;&nbsp;&nbsp;IT0=1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置下降沿触发方式,因为使用的传感器是触发时低电平

&nbsp;&nbsp;&nbsp;&nbsp;EX0=1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//外部INT0中断允许

&nbsp;&nbsp;&nbsp;&nbsp;//**********************

&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;//***开全局中断设置****

&nbsp;&nbsp;&nbsp;&nbsp;//外部中断INT0设置了中断允许,此处要开全局中断

&nbsp;&nbsp;&nbsp;&nbsp;EA=1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//开全局中断

&nbsp;&nbsp;&nbsp;&nbsp;//*********************

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P0&nbsp;=&nbsp;0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//开机后51单片机每个引脚默认是高电平,需要一步操作置低电平

&nbsp;&nbsp;&nbsp;&nbsp;while(1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//死循环,单片机初始化后,将一直运行这个死循环

&nbsp;&nbsp;&nbsp;&nbsp;{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//在其他程序中,便可以添入自己所需要的代码,本实验功能完全由中断实现

&nbsp;&nbsp;&nbsp;&nbsp;}

}</pre><p>进一步学习单片机的中断知识,这里附上一个资料:</p><p><a href="https://www.cnblogs.com/wxer/p/6815204.html?tdsourcetag=s_pcqq_aiomsg">https://www.cnblogs.com/wxer/p/6815204.html?tdsourcetag=s_pcqq_aiomsg</a></p><p>以及8051的引脚封装图(注意框内部分)</p><p><img src="{#ZC_BLOG_HOST#}zb_users/upload/2019/05/5ccc5faa74054997303076.png" alt=""/></p><p>以及留下一道练习题,感兴趣的同学可以做一做,这里用到了1602液晶,学会使用它可以说是必要的,不同的教程里教法不同,显示函数的写法也不同,大家还是花点时间认真阅读自己手头上的教程。</p><p><span style="font-family:方正楷体_GBK">练习题<br/>1、 使用51\PIC单片机设计完成系统,需要自己编制程序,硬件使用开发板或核心板。<br/>2、 基本要求:按键按下5次之后使用1602液晶显示ABCDE,此后再按下五次之后显示屏幕为空。使用外部中断对按键进行检测(注意按键接入单片机的引脚),使用内部计时器(也可以称为计数器)对按键次数进行记录。<br/>3、 扩展要求:将空屏内容替换为分、秒时钟,即使用按键按五次,LCD显示内容在字母和时钟之间切换。<br/>说明:练习题是根据去年电赛的三个题目总结出做比赛大概率会用到的知识拟出,希望认真对待,基本要求尽量完成,扩展要求选做

</span></p><p>&nbsp;</p><p>最后,附上PIC实现这个功能的代码,格式和注释都比较乱,但功能是一样的。</p><p>&nbsp;</p><pre class="prism-highlight prism-language-c">//嵌入式工作室5月2日教学例程

//学习使用外部中断和定时器中断

//此代码适用于PIC单片机

&nbsp;

#include&nbsp;&lt;pic.h&gt;

__CONFIG(HS&amp;WDTDIS&amp;LVPDIS);

unsigned&nbsp;char&nbsp;q&nbsp;=&nbsp;0;

unsigned&nbsp;char&nbsp;p&nbsp;=&nbsp;0;

int&nbsp;Fout&nbsp;=&nbsp;0;

&nbsp;

void&nbsp;interrupt&nbsp;ISR(void)&nbsp;&nbsp;&nbsp;//PIC单片机的所有中断都是这一个入口

{

if(INTF&nbsp;==&nbsp;1)

{

TMR0=0x13;

INTF&nbsp;=&nbsp;0;

q=0;

p=0;

PORTC=0B11111111;

INTE=0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置RB0/INT中断不允许

//&nbsp;&nbsp;T0IE=1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//TMR0中断允许

&nbsp;

}

if(T0IF==1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//需要进一步判断是否是T0中断

{

TMR0=0x13;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//定时器中断后,要重置初值,以备下次中断

T0IF=0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//清中断标志位,以备下次中断

q++;

&nbsp;

if(q&gt;250)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//2000us中断一次,再计次250次后就是500毫秒

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{

p++;

q=0;

if(p&gt;10)

{

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p=0;

PORTC=0B00000000;

INTE=1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置RB0/INT中断允许

}

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}

}

}

&nbsp;

//---------------------------------------

//名称:&nbsp;主函数

&nbsp;

//---------------------------------------

void&nbsp;main(void)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//主函数,单片机开机后就是从这个函数开始运行

{

TRISC=0B11111011;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//初始化RC7-RC0的输入输出方向

PORTC=0B00000000;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//初始化RC7-RC0的数值

TRISB=0B11111111;

PORTB=0B11111111;

&nbsp;&nbsp;&nbsp;&nbsp;//***外部中断RB0/INT初始化***

INTEDG=0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置RB0/INT为下降沿触发

INTF=0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//清除RB0/INT的中断标志

INTE=1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置RB0/INT中断允许

//***定时器TMR0初始化***

T0CS=0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//TMRO时钟源选择内部指令周期时钟(Fosc/4)

PSA=0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//预分频器分配给TMR0模块

PS0=0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//TMR0预分频比1:8,PS0=0

PS1=1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//TMR0预分频比1:8,PS1=1

PS2=0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//TMR0预分频比1:8,PS2=0

TMR0=0x13;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//定时2000微秒,置初值为256-250+13

T0IF=0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//清除TMR0的中断标志

T0IE=1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//TMR0中断部允许

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

//***开全局中断设置****

//定时器T0设置了中断允许,此处要开全局中断

GIE=1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//开全局中断

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

while(1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//死循环,单片机初始化后,将一直运行这个死循环

{

&nbsp;

}

}</pre><p>&nbsp;</p>

Q.E.D.