[51 마이크로컨트롤러 시리즈] C51의 인터럽트 시스템 확장 실험

이 기사는 51 마이크로컨트롤러 인터럽트 시스템에 대한 확장된 실험입니다.

1. 확장 실험 1: 외부 인터럽트 0을 사용하여 부저를 제어하고 외부 인터럽트 1을 사용하여 DC 모터를 제어합니다.

외부 인터럽트 확장 실험 1에서 구현된 기능: 외부 인터럽트 0을 사용하여 부저 소리를 울리거나 울리지 않도록 제어하고, 외부 인터럽트 1을 사용하여 DC 모터의 회전/정지를 제어합니다.

부저의 내용을 보면 부저가 능동부저와 수동부저로 나누어져 있음을 알 수 있는데, 부저에는 2개의 핀이 있는데, 부저가 울리려면 부저에 전류가 흘러야 하는데, 즉 핀의 한쪽 끝에는 전류가 흐르게 되어 있다. 양극에 연결되고 핀의 다른 쪽 끝은 음극에 연결됩니다. 능동형 부저가 울리려면 특정 전압만 필요한 반면, 수동형 부저는 소리를 내려면 특정 주파수의 펄스가 필요합니다. 여기에는 두 개의 버저가 설계되어 있으며 둘 다 외부 인터럽트 0에 의해 제어됩니다.

DC 모터는 부저와 유사한 방식으로 구동됩니다.

프로테우스의 하드웨어 설계는 다음과 같으며, 부저 소리를 표시하기 위해 부저 소리 여부를 표시하는 LED를 사용한다. 부저의 한쪽 끝은 전원 공급 장치에 연결되고 다른 쪽 끝은 ULN2003 칩을 통해 P1.5 포트에 연결됩니다.P1.5=0일 때 부저가 울리고 DC 모터의 한쪽 끝은 ULN2003 칩에 연결됩니다. 전원 공급 장치, 다른 쪽 끝은 ULN2003을 통해 P1.0 포트에 연결되며, P1.0=0일 때 모터가 회전합니다. 인터럽트를 반영하려면 P3.2, P3.3 포트에 독립된 버튼 모듈을 연결하여 사용하며, 버튼을 누르면 부저가 울리거나 모터가 회전합니다.

Proteus 디자인 외부 인터럽트 제어 부저 및 DC 모터

소프트웨어 설계는 다음과 같습니다.

/*
	实现功能:外部中断0控制蜂鸣器发声,外部中断1控制直流电机转动
		- 与外部中断0和外部中断1有关的有两个寄存器IE和TCON,
		- IE是中断允许控制寄存器,TCON是中断请求标志寄存器。
		- IE中包括了
			- 总中断允许位(EA)
			- 外部中断0/1允许位(EX0/EX1)
			- 定时器0/1允许位(ET0/ET1)
			- 串口中断允许位(ES);
		- TCON中的低四位是外部中断允许和触发方式控制位,包括了
			- IT0/IT1是外部中断0/1触发方式控制位,0表示低电平触发,1表示下降沿触发;
			- IE0/IE1是外部中断0/1请求标志位
	[2023-12-19] zoya
*/

#include "reg52.h"
#include "typedef.h"
#include "Delay.h"

sbit BEEP = P1^5;
sbit MOTOR = P1^0;
sbit CTR_INT0 = P3^2;
sbit CTR_INT1 = P3^3;

/*************************************************************************
* 函数名:		IntInit
* 函数功能:	外部中断0/1初始化,设置中断触发方式为边沿触发
* 输入:			void
* 输出:			void
**************************************************************************/
void IntInit()
{
    
    
	// 1. 设置中断触发方式
	IT0=1;
	IT1=1;
	// 2. 打开外部中断0/1
	EX0=1;
	EX1=1;
	// 3. 打开总中断
	EA=1;
}


void main()
{
    
    
	MOTOR=0;
	BEEP=0;
	IntInit(); 
	while(1);
}

/*************************************************************************
* 函数名:		Int0
* 函数功能:	外部中断0中断服务函数,
* 						控制蜂鸣器发声
* 输入:			void
* 输出:			void
**************************************************************************/
void Int0() interrupt 0
{
    
    
	delayms(10);  // 按键延时消抖
	if(0 == CTR_INT0){
    
    
		BEEP = ~BEEP;
	}
}

/*************************************************************************
* 函数名:		Int1
* 函数功能:	外部中断1中断服务函数,
* 						控制直流电机转动
* 输入:			void
* 输出:			void
**************************************************************************/
void Int1() interrupt 2
{
    
    
	delayms(10);  // 按键延时消抖
	if(0 == CTR_INT1)
	{
    
    
		MOTOR=~MOTOR;
	}
}

시뮬레이션 결과:

외부 인터럽트 제어 부저 및 DC 모터

2. 확장 실험 2: 타이머의 초기값을 수정하고 타이머를 3초로 설정하여 LED 모듈이 깜박이도록 합니다.

타이머의 초기값을 계산하는 방법은 무엇입니까?

12MHz 수정 발진기 주파수를 사용하여 계산되었습니다. 12MHz 수정 발진기를 사용하는 경우 마이크로 컨트롤러의 내부 클록 주파수는 12로 나누어집니다(즉, 12/12MHz=1MHz). 그러면 해당 기계 주기는 1/1MHz=1us입니다. 즉, 12MHz 수정진동자를 사용하는 기계주기는 1us이다.

1ms의 시간을 측정하려면 1ms/1us=1000을 계산해야 합니다. 타이머는 모드 1에서 작동하며 초기 값은 2 16 − 1000 = 64536 2^{16}-1000 = 64536입니다.216-1000=64536 = 0xFC18. 즉, 초기값은 THx=0xfc, TLx=0x18이다.

1s의 시간을 원할 경우 초기값을 통해 타이머를 1ms로 설정하고, 타이머가 종료되면 초기값을 다시 지정하고 글로벌 변수를 설정하여 1ms의 횟수를 누적하게 되며, 글로벌 변수가 1000회 누적되면 타이머가 1초라는 뜻입니다.

3s 시간으로 설정하고자 할 경우 초기값을 통해 타이밍을 3ms로 설정하면 되며, 그 외의 타이밍은 1ms와 동일하다. 타이밍 3ms에는 3ms/1us=3000을 계산해야 합니다. 타이머는 모드 1에서 작동합니다. 초기 값은 2 16 − 3000 2^{16} - 3000입니다.216-3000 = 62536 = 0xF448, 즉 초기값 THx=0xF4, TLx=0x48이다.

이 실험에서는 이전 사용 예를 기반으로 초기 카운팅 값을 변경하면 LED 모듈이 깜박이는 데 3초의 타이밍을 얻을 수 있습니다. LED 모듈은 다음과 같이 proteus로 설계되었으며 타이머 모듈은 마이크로 컨트롤러 내부에 있습니다.

Proteus 디자인 타이머는 LED 모듈 깜박임을 제어합니다.

소프트웨어 설계는 다음과 같습니다.

/*
	实现功能:定时器0定时3s实现LED模块亮灭
		- 与定时/计数器工作有关的寄存器有IE、TCON、TMOD、THx、TLx
		- IE是中断允许控制寄存器,TCON是中断请求标志寄存器,TMOD是定时/计数器工作方式寄存器
		- THx和TLx是计数初值赋值寄存器。
		
		- IE中包括了
			- 总中断允许位(EA)
			- 外部中断0/1允许位(EX0/EX1)
			- 定时器0/1允许位(ET0/ET1)
			- 串口中断允许位(ES);
		
		- TCON中的高四位用于控制定时/计数器的启动和中断申请,包括TR0/1、TF0/1
			- TR0/TR1是T0/T1运行控制位,TR0=1时开始工作,TR0=0时停止工作,TR1与TR0类似;
			- TF0/TF1是T0/T1溢出中断请求标志位,溢出时由硬件自动置位,CPU响应中断后由硬件自动清0
				可随时查询该位状态,也可软件置1或清0.
				
		- TMOD高四位控制T1,低四位控制T0,高四位和低四位分别为有GATE、C/T、M1M0
			- GATE是门控位,
				- GATE=0表示不受外部中断信号影响,仅TR0/TR1控制定时/计数器工作,
				- GATE=1表示受外部中断信号影响,即TR0/TR1+INT0控制定时/计数器工作
			- C/T是定时/计数器模式选择位,C/T=0为定时模式,C/T=1为计数模式;
			- M1M0是工作方式设置位,有四种方式:00 01 10 11
	[2023-12-20] zoya
*/

#include "reg52.h"
#include "typedef.h"
#include "Delay.h"

#define GPIO_LED P2
/*************************************************************************
* 函数名:		Timer0Init
* 函数功能:	定时器0初始化,工作方式1定时3ms,仅TR0启动或停止计数
* 输入:			void
* 输出:			void
**************************************************************************/
void Timer0Init()
{
    
    
	// 1. 设置工作方式1,仅TR0控制
	TMOD |= 0x01;
	// 2. 设置定时3ms的初值,0xf448
	TH0 = 0xf4;
	TL0 = 0x48;
	// 3. 打开中断允许位
	EA = 1;
	ET0 = 1;
	// 4. 置位TR0,开始计数
	TR0 = 1;
}


void main()
{
    
    
	Timer0Init(); 
	while(1);
}


/*************************************************************************
* 函数名:		Timer0
* 函数功能:	定时器0中断服务函数,定时3s控制LED模块亮灭
* 输入:			void
* 输出:			void
**************************************************************************/
void Timer0() interrupt 1
{
    
    
	static u16 i;
	// 重新赋初值
	TH0 = 0xf4;
	TL0 = 0x48;
	i++;
	if(1000 == i)
	{
    
    
		i=0;
		GPIO_LED = ~GPIO_LED;
	}
}

시뮬레이션 결과:

타이머 0은 LED 모듈을 3초 동안 켜고 끄도록 제어합니다.

3. 확장 실험 3: 타이머 1과 디지털 튜브를 사용하여 디지털 시계 설계

타이머 설정에 대해서는 확장 실험 2를 참조하세요.

디지털 시계는 24시간 형식을 사용하며 "00-00-00" 형식으로 표시됩니다.

여기에서 디지털 튜브는 8 비트 공통 음극 디지털 튜브를 사용하고 칩 74HC138은 디지털 튜브의 비트 선택을 제어하는 ​​데 사용되며 칩 74HC245는 디지털 튜브의 세그먼트 선택을 제어하는 ​​데 사용됩니다. P0 포트는 74HC245의 입력, P2.2 ~ P2.4는 74HC138의 입력을 제어합니다. 프로테우스 디자인은 다음과 같습니다.

Proteus는 디지털 시계를 구현하기 위해 타이머 1과 디지털 튜브를 설계합니다.

소프트웨어 설계는 다음과 같습니다.

/*
	实现功能:定时器1和数码管设计一个数字时钟
		- 与定时/计数器工作有关的寄存器有IE、TCON、TMOD、THx、TLx
		- IE是中断允许控制寄存器,TCON是中断请求标志寄存器,TMOD是定时/计数器工作方式寄存器
		- THx和TLx是计数初值赋值寄存器。
		
		- IE中包括了
			- 总中断允许位(EA)
			- 外部中断0/1允许位(EX0/EX1)
			- 定时器0/1允许位(ET0/ET1)
			- 串口中断允许位(ES);
		
		- TCON中的高四位用于控制定时/计数器的启动和中断申请,包括TR0/1、TF0/1
			- TR0/TR1是T0/T1运行控制位,TR0=1时开始工作,TR0=0时停止工作,TR1与TR0类似;
			- TF0/TF1是T0/T1溢出中断请求标志位,溢出时由硬件自动置位,CPU响应中断后由硬件自动清0
				可随时查询该位状态,也可软件置1或清0.
				
		- TMOD高四位控制T1,低四位控制T0,高四位和低四位分别为有GATE、C/T、M1M0
			- GATE是门控位,
				- GATE=0表示不受外部中断信号影响,仅TR0/TR1控制定时/计数器工作,
				- GATE=1表示受外部中断信号影响,即TR0/TR1+INT0控制定时/计数器工作
			- C/T是定时/计数器模式选择位,C/T=0为定时模式,C/T=1为计数模式;
			- M1M0是工作方式设置位,有四种方式:00 01 10 11
		
		使用一个八位一体的共阴极数码管显示时间,74HC138芯片控制数码管的位选,74HC245控制数码管的段选。
	[2023-12-20] zoya
*/

#include "reg52.h"
#include "typedef.h"
#include "Delay.h"

#define GPIO_DISPLAY P0
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

// 共阴极数码管的码表,0-9以及:
u8 code smg[] = {
    
    0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x67, 0x40};

static u16 h, m, s;

/*************************************************************************
* 函数名:		Timer0Init
* 函数功能:	定时器0初始化,工作方式1定时3ms,仅TR0启动或停止计数
* 输入:			void
* 输出:			void
**************************************************************************/
void Timer1Init()
{
    
    
	// 1. 设置工作方式1,仅TR0控制
	TMOD |= 0x10;
	// 2. 设置定时1ms的初值,0xFC18
	TH1 = 0xFC;
	TL1 = 0x18;
	// 3. 打开中断允许位
	EA = 1;
	ET1 = 1;
	// 4. 置位TR1,开始计数
	TR1 = 1;
}

void DigDisplay()
{
    
    

	LSA=0; LSB=0; LSC=0; GPIO_DISPLAY = smg[h/10];
	delayms(1);
	LSA=1; LSB=0; LSC=0; GPIO_DISPLAY = smg[h%10];
	delayms(1);
	LSA=0; LSB=1; LSC=0; GPIO_DISPLAY = smg[10];
	delayms(1);
	LSA=1; LSB=1; LSC=0; GPIO_DISPLAY = smg[m/10];
	delayms(1);
	LSA=0; LSB=0; LSC=1; GPIO_DISPLAY = smg[m%10];
	delayms(1);
	LSA=1; LSB=0; LSC=1; GPIO_DISPLAY = smg[10];
	delayms(1);
	LSA=0; LSB=1; LSC=1; GPIO_DISPLAY = smg[s/10];
	delayms(1);
	LSA=1; LSB=1; LSC=1; GPIO_DISPLAY = smg[s%10];
	delayms(1);
}

void main()
{
    
    
	GPIO_DISPLAY = 0x00;
	Timer1Init(); 
	while(1)
	{
    
    
		DigDisplay();
	}
}

/*************************************************************************
* 函数名:		Timer1
* 函数功能:	定时器1中断服务函数,控制数码管显示
* 输入:			void
* 输出:			void
**************************************************************************/
void Timer1() interrupt 3
{
    
    
	static u16 j;
	// 重新赋初值
	TH1 = 0xFC;
	TL1 = 0x18;
	j++;
	if(1000 == j)
	{
    
    
		j=0;
		s++;
		if(60 == s)
		{
    
    
			s=0; m++;
			if(60 == m)
			{
    
    
				m=0; h++;
				if(24 == h)
				{
    
    
					h=0;
				}
			}
		}
	}
}

시뮬레이션 결과:

타이머 1과 디지털 튜브가 디지털 시계를 구현합니다.

추천

출처blog.csdn.net/sinat_41752325/article/details/135108419