嵌入式软件--51单片机 DAY 4

news/2024/12/23 4:51:43/

一、蜂鸣器

当电流通过线圈时会产生电磁场,电磁场与永磁体相互作用,从而使金属膜产生震动而发声。为使金属膜持续震动,蜂鸣器需要使用震荡电路进行驱动。有些蜂鸣器元件内部自带震荡驱动电路,这种蜂鸣器叫做有源蜂鸣器(Active Buzzer,自激式蜂鸣器);而有些则不带震荡驱动电路,这种蜂鸣器叫做无源蜂鸣器(Passive Buzzer,它激式蜂鸣器)。

1.原理图

2.软件实现

Int_Buzzer.h

#ifndef __INT_BUZZER_H__
#define __INT_BUZZER_H__
#include <STC89C5xRC.H>
#define BUZZ P46/*** @brief 蜂鸣器响0.1s**/
void Int_Buzzer_Buzz();#endif /* __INT_BUZZER_H__ */

 Int_Buzzer.c

#include "Int_Buzzer.h"
#include "Util.h"void Int_Buzzer_Buzz()
{unsigned char counter = 100;while (counter) {BUZZ = ~BUZZ;Delay1ms(1);--counter;}
}

main.c 

#include "Int_DigitalTube.h"
#include "Int_MatrixKey.h"
#include "Int_Buzzer.h"
int main()
{u8 key_pressed = 0;Int_DigitalTube_Init();Int_DigitalTube_DisplayNum(key_pressed);while (1) {key_pressed = Int_MatrixKey_CheckKey();if (key_pressed) {Int_DigitalTube_DisplayNum(key_pressed);Int_Buzzer_Buzz(); //按键提示音}Int_DigitalTube_Refresh();}
}

 

二、中断系统

1.概念

中断系统是单片机用于处理外部紧急事件的一种机制。中断系统工作的大致流程如下图所示:当CPU正在处理某项任务时,外部发生了某个紧急事件,此时CPU会暂停当前的工作,转而去处理这个紧急事件,处理完之后,再回到原来被中断的位置,继续处理原来的工作。

中断系统使单片机能够实时响应外部事件,提高了系统的灵活性和响应能力。

中断源

中断源是指能够引发中断的事件。

中断标志位

中断标志位用于标识某个中断是否发生,每个中断源都有一个与之对应的中断标志位。当某个中断发生时,相应的中断标位就会置为1,当CPU检测到标志位时,就会处理相应的中断。当中断处理完毕后,中断标志位需要复位(置0),以便接收下一次中断,有些中断源的标志位,会在CPU处理完中断后,自动复位,而有些则需要开发者手动复位,在使用中断时,需要注意查看手册说明。

中断服务程序

中断服务程序指处理中断的逻辑,当某个中断标志位置1时,CPU会自动执行相应的中断服务程序。

中断优先级

中断优先级是指在多个中断同时发生时,单片机响应中断的先后顺序,并且高优先级的中断可以打断低优先级的中断。

中断源:

STC89C52RC共有8个中断源,8个中断源可分为3类,3个类别分别是外部中断(4个)、定时器中断(3个)、串口中断(1个)。

2.外部中断

外部中断是指由单片机外部的紧急事件触发的中断,通过向单片机的特定引脚发送特定的信号触发。STC89C52RC共提供了4个外部中断引脚,分别是INT0,INT1,INT2,INT3,如下图所示。

单片机>51单片机的外部中断支持两种触发方式,分别是低电平触发下降沿触发

3.定时器中断

定时器中断是指由单片机内部的定时器触发的中断。

定时器是大多数单片机都具备的一个功能模块,用于实现定时任务。其用法是,设置一个定时值,然后开始计时,待计时结束后,触发相应的定时器中断,开发者可以在中断服务程序中编写定时任务的逻辑。

STC89C52RC共有三个定时器,分别是Timer0、Timer1、Timer2,每个定时器都有一个相对应的中断。

4.串口中断

串口中断是由单片机串口触发的中断。

串口是单片机用于收发数据的重要接口之一,当单片机通过串口接收到数据或者发送完数据后都会触发相应的中断。

STC89C52RC的串口引脚为TxD和RxD,其中TxD用于发送数据,RxD用于接收数据,如下图所示。


5.中断服务程序

中断服务程序是指用于处理中断的一段代码,当中断发生时,CPU就会暂停当前程序的执行,转而执行对应的中断服务程序,处理完中断后再恢复到原来的程序。

STC89C52RC共有8个中断源,分为4个外部中断、3个定时器中断和1个串口中断,开发者可以为每个中断源声明相应的中断服务程序,中断服务程序的声明语法如下。

6.中断优先级

STC89C52RC共有四个中断优先级,每个中断源都可以单独设置优先级。若多个中断同时发生,优先级高的会被优先处理;若两个中断的优先级相同,则根据其中断号决定处理顺序,中断号越小越优先。

除此之外,高优先级的中断还可以打断低优先级的中断,也就是说当CPU正在处理一个中断时,又发生了另外一个优先级比它还高的中断,此时CPU会暂停原来中断的服务程序,转而去处理这个高优先级的中断,处理完之后,再回到原来低优先级的中断服务程序。这个机制叫做中断嵌套,STC89C52RC支持两级中断嵌套。

三、外部中断

需求:使用外部中断的方式,一键控制LED灯的亮灭。

1.硬件设计

若想通过外部中断的方式检测按钮,必须将按钮接入4个外部中断引脚之一,如下图所示,可以看到SW3可用于触发外部中断0。

2.使用说明

(1)启用中断

默认情况,CPU会屏蔽所有中断请求,也就是说CPU不会响应任何中断请求,要使用中断,必须先进行启用。

每个中断源是否被启用,是由单片机内部的两个寄存器控制的,这两个寄存器分别是IE(Interrupt Enable,中断允许)寄存器和XICON(Auxiliary Interrupt Control,辅助中断控制)寄存器。

从上图可以看出,STC89C52系列的中断系统具有两级控制,首先是EA总控制位,其次是每个中断源各自的控制位。因此若需要启用某个中断,需要先将总控制位EA置位1,再将该中断自身的控制位置为1。//EA=1

(2)配置外部中断触发方式

STC89C52系列的外部中断支持两种触发方式,分别是低电平触发和下降沿触发,4个外部中断各需要1个控制位用于设置触发方式,这4个控制位分布于如下两个寄存器中,分别是XICON(Auxiliary Interrupt Control,辅助中断控制)寄存器中、TCON(Timer 0 and 1 Control寄存器,如下图所示。

4个控制位的具体作用可参考下图(STC89C52系列中断系统结构图)。

(3)配置中断优先级

STC89C52系列的中断系统支持四个优先级,所以每个中断源的优先级都需要通过2个控制位进行配置,8个中断源共需要16个控制位,这16个控制位分布在如下3个寄存器中,分别是IPH(Interrupt Priority High,中断优先级高位)寄存器,IP(Interrupt Priority Low,中断优先级低位)寄存器,XICON(Auxiliary Interrupt Control,辅助中断控制)寄存器。

(4)定义中断服务程序

外部中断0到外部中断3的中断号分别是:0、2、6、7,以外部中断0为例,其中断服务程序应定义为

void INT0_Handler() interrupt 0{}

3.软件设计

实现思路:

(1)启用外部中断0

//打开中断总开关
EA=1;
//打开外部中断0开关
EX0=1;

(2)配置外部中断0的触发方式

下降沿触发

IT0=1;

(3)只有一个中断,优先级不考虑

(4)中断服务程序

void INT0_Func() interrupt 0
{LED0=~LED0;
}

完整代码:

#include <STC89C5xRC.H> //包含STC89C52的头文件#define LED0   P00void Init_INT0()
{// 打开中断总开关EA = 1;// 打开外部中断0开关EX0 = 1;// 配置外部中断为下降沿触发IT0 = 1;
}void main()
{Init_INT0();while (1);
}/*** @brief 中断函数中打开LED0,代表当触发中断时,LED0会打开。*        根据我们之前的设置,当按下SW3时,P32为低电平,此时LED0打开。**        interrupt 0表示0号中断触发时执行该函数的逻辑*        如果用C语言编程,中断查询次序就是中断号*/
void INT0_Func() interrupt 0
{// 中断中打开LED0LED0 = ~LED0;
}

四、定时器中断--闪烁LED灯

1.需求:

使用定时器中断的方式实现LED闪烁,具体要求是使用定时器0令LED1每1秒钟闪烁一次。

定时器的基本工作原理,是使用一个n位的脉冲计数器,对时钟信号的脉冲进行计数,每个脉冲加1,当脉冲计数器达到最大值(2n)时,也就是溢出时,触发定时器中断。

2.启用定时器中断

//中断总开关
EA=1;
//定时器0中断开关
ET0=1;

选择定时器工作模式

M1

M0

工作模式

0

0

工作模式0(13位)

0

1

工作模式1(16位)

1

0

工作模式2(8位自动重装载)

1

1

工作模式3(双8位)

计算脉冲初始值

假如现在需要定时1ms,那么1ms需要的脉冲个数应为0.001/(12/11059200),因此定时器的初始值应为65536-0.001/(12/11059200),大约等于64614。

计算完毕后,需要将该值赋予TL0(低8位)和TH0(高8位),如下。

TL0 = 64614;

TH0 = 64614 >> 8;

启动定时器

在做完上述配置后,还需最后一步——启动定时器,启动之后定时器才会开始工作。定时器的启动可由单片机内部的寄存器控制,也可由单片机的外部引脚控制。具体控制逻辑如下图所示。

当GATE=0时,外部引脚(INT0,P3.2)无效,此时只能由内部寄存器TR0控制,当TR0=1时,脉冲计数器开始计数,TR0=0时,停止计数。

当GATE=1时,外部引脚(INT0,P3.2)生效,此时只有当内部寄存器TR0和外部引脚INT0都为1时,脉冲计数器才开始计数,否则停止计数。

3.定义中断服务程序

void Timer0_Hander() interrupt 1

{

    //编写定时任务逻辑

}

4.软件设计

(1)启用定时器中断

EA=1;
ET0=1;

(2)选择定时器0的工作模式

GATE=0 C/T=0 M1=0 M0=1

C/T是TMOD寄存器中定时器0的控制位,选择定时器C/T应为0.

故,TMOD寄存器低四位是0001,高四位保持原值。

TMOD&=0xF0;//高四位不变,低四位归零。

TMOD|=0x01;//高四位不变,最低位变1.

(3)启动定时器

GATE已经设置为0,只要TR0=1,即可启动。

(4)定义中断服务程序

void Timer0_Hander() interrupt 1
{
static unsigned int count = 0;//重新状态脉冲计数器TL0 = 64614;TH0 = 64614 >> 8;//统计中断次数if (count++ >= 500) {LED1  = ~LED1;count = 0;}
}

5.完整代码

Dri_Timer0.c

#include "Dri_Timer0.h"
#include <STC89C5xRC.H>
void Dri_Timer0_Init()
{EA=1;//总开关ET0=1;//定时器0开关//定时器0工作方式TMOD&=0xF0;TMOD|=0x01;//脉冲计数器初始值TL0=64614;TH0=64614>>8;//启动定时器TR0=1;}

Dri_Timer0.h

#ifndef __DRI_TIMER0_H__
#define __DRI_TIMER0_H__void Dri_Timer0_Init();//定时器0开关,启动函数#endif /* __DRI_TIMER0_H__ */

main.c

#include <STC89C5xRC.H>
#include "Dri_Timer0.h"
#include "Com_Util.h"
#define LED1 P00
void main()
{Dri_Timer0_Init();while(1);
}
//定时中断服务程序
void Timer0_Hander() interrupt 0
{LED1=~LED1;Com_Util_Delay1ms(500);
}

6.定时器封装

为使定时器使用起来更加方便和通用,我们可以将定时器代码进一步封装。

(1)思路

初始化定时器-->中断服务程序,轮询调用函数.


http://www.ppmy.cn/news/1522031.html

相关文章

网恋照妖镜源码搭建教程

文章目录 前言创建网站1.打开网站设置 配置ssl2.要打开强制HTTPS&#xff0c;用宝塔免费的ssl证书即可&#xff0c;也可以使用其他证书&#xff0c;必须是与域名匹配的3.上传文件至根目录进行解压4.解压后&#xff0c;修改文件 sc.php 里面的内容5.其余探索 前言 前俩年很火的…

第92集《大佛顶首楞严经》

讲义209面 我们在正念真如的过程当中&#xff0c;主要有二种的方法&#xff1a;第一个就是依教起观。就是我们根据本经的语言文字的教法&#xff0c;来生起观照。比方说佛陀告诉我们经常能够回光返照&#xff1a;你从什么地方来&#xff1f;从语言文字的引导当中&#xff0c;念…

4.1 数据分析-excel 基本操作

第四节&#xff1a;数据分析-excel 基本操作 课程目标 学会excel 基本操作 课程内容 数据伪造 产生一份招聘数据 import pandas as pd from faker import Faker import random import numpy as np# 创建一个Faker实例&#xff0c;用于生成假数据&#xff0c;指定中文本地…

【视频讲解】Python贝叶斯卷积神经网络分类胸部X光图像数据集实例

全文链接&#xff1a;https://tecdat.cn/?p37604 分析师&#xff1a;Yuanchun Niu 在人工智能的诸多领域中&#xff0c;分类技术扮演着核心角色&#xff0c;其应用广泛而深远。无论是在金融风险评估、医疗诊断、安全监控还是日常的交互式服务中&#xff0c;有效的分类算法都是…

PHP轻量级高性能HTTP服务框架 - webman

摘要 webman 是一款基于 workerman 开发的高性能 HTTP 服务框架。webman 用于替代传统的 php-fpm 架构&#xff0c;提供超高性能可扩展的 HTTP 服务。你可以用 webman 开发网站&#xff0c;也可以开发 HTTP 接口或者微服务。 除此之外&#xff0c;webman 还支持自定义进程&am…

计算机基础知识-2

x86架构的寄存器 AT&T汇编和Intel汇编的区别 每取出完一条指令&#xff0c;PC会自动&#xff0b;"1"&#xff0c;指向下一条要被执行的指令。这里的1是指下一条指令&#xff0c;但是指令本身可能占用多个字节&#xff0c;所以地址可能不是以1叠加 当前执行的是10…

实现简单聊天

管道通信 目的&#xff1a; 实现 xxz 与 zy 之间的通讯聊天 功能&#xff1a; 同一网络下进行的模拟通讯实现 缺点&#xff1a;没有涉及到网络的通信&#xff0c;只是简单的进程之间模拟的通信 采用到的技术点&#xff1a; 1 有名管道 优点&#xff1a; 在文件系统中作为一…

【自然语言处理】调用NLTK数据失败‘wordnet‘和‘punkt‘不存在[Errno 11004]问题解决

wordnet报错 明明已经按照了nltk包&#xff0c;但使用 WordNet 语料库时依然报错提示数据不存&#xff0c;依据以下代码在python中下载wordnet仍然报错&#xff1a; import nltk nltk.download(wordnet)运行后始终提示&#xff1a; [nltk_data] Error loading wordnet: <…