单片机学习笔记---红外遥控红外遥控电机调速(完结篇)

目录

低电平触发中断和下降沿触发中断的区别

红外遥控

Int0.c

Int.h

Timer0.c

Timer0.h

IR.c

IR.h

main.c 

红外遥控电机调速

Timer1.c

Timer.h

Motor.c

Motor.h

main.c


上一节讲了红外发送和接收的工作原理,这一节开始代码演示!

提前说明,本节代码演示中会涉及定时器和中断系统!

如果不懂定时器和中断系统的话,建议去看看我之前已经详细写过的中断系统和定时器的博客,也写的比较全面的了,看过后肯定能让你明白中断系统和定时器的工作原理!

单片机学习笔记---中断系统(含外部中断)-CSDN博客

单片机学习笔记---定时器/计数器(简述版!)_定时计数器ea-CSDN博客

单片机学习笔记---定时器和中断系统如何连起来工作-CSDN博客

低电平触发中断和下降沿触发中断的区别

在正式演示红外遥控的代码之前我们先来看看配置外部中断时,选择低电平触发和下降沿触发有什么区别?

我们用外部中断INT0来举个例子:

我们单片机的原理图上,INT0接的是单片机的P32口,

而独立按键K3正好也是P32口。

那么我们按下K3的时候就相当于给单片机的P32口一个下降沿

那么我们现在来写一个程序验证一下选择低电平触发和下降沿触发有什么区别:

先创建一个工程文件,把我之前的博客中讲过的LCD1602的程序文件添加进来

然后在主程序main.c中调用这个函数来显示中断触发的现象

首先是选择下降沿触发:

#include <REGX52.H>
#include "LCD1602.h"unsigned char Num;void main()
{LCD_Init();//初始化液晶屏//配置中断系统IT0=1;//选择下降沿触发方式IE0=0;//中断标志位清零EX0=1;//打开中断EA=1;//打开总中断PX0=1;//一般都选择高优先级中断//跳转到中断函数//中断函数执行完进入while循环while(1){LCD_ShowNum(1,1,Num,3);}
}//中断函数
void Init0_Routine(void) interrupt 0
{Num++;
}

下降沿触发的话,你按下的时候加一次,松开再按下的时候才再加一次。“松开状态再按下”这一个过程就是给一个下降沿的过程。

效果请看视频:

选择下降沿触发中断的结果现象

再来看看选择低电平触发:

#include <REGX52.H>
#include "LCD1602.h"unsigned char Num;void main()
{LCD_Init();//初始化液晶屏//配置中断系统IT0=0;//选择低电平触发方式IE0=0;//中断标志位清零EX0=1;//打开中断EA=1;//打开总中断PX0=1;//一般都选择高优先级中断//跳转到中断函数//中断函数执行完进入while循环while(1){LCD_ShowNum(1,1,Num,3);}
}//中断函数
void Init0_Routine(void) interrupt 0
{Num++;
}

而如果是低电平触发的话,只要按键按下这个中断会一直处于触发状态,当中断函数结束之后它会再次进入,直到变成高电平为止。那它的现象就是按下不松的时候,这个数值是一直加的,直到松手,数值才停止加。

效果请看视频:

选择低电平触发中断的结果现象

以上就是低电平触发中断和下降沿触发中断的区别

而本节红外遥控的示例代码要用的是下降沿触发中断的这种方式!

红外遥控

现在开始正式演示代码:

新创建一个工程文件:红外遥控

将我之前的博客讲过的程序模块直接添加进来

然后先创建Int0.c,Int.h,IR.c,IR.h和main.c文件

开始代码讲解:

首先写一个初始化中断系统的函数

Int0.c

#include <REGX52.H>void Int0_Init(void)
{IT0=1;//选择下降沿触发中断IE0=0;//中断标志位清零EX0=1;//把中断打开EA=1;//打开总中断PX0=1;//选择高优先级中断
}

声明一下这个函数

Int.h

#ifndef __INT0_H__
#define __INT0_H__void Int0_Init(void);#endif

Timer0.c

接下来我们把Timer0.c文件的程序改造一下

将计时器初始化函数中的中断系统配置部分删掉,将初值清零,并且关闭计时

#include <REGX52.H>
//定时器0初始化
void Timer0_Init(void)
{TMOD &= 0xF0;		//设置定时器模式TMOD |= 0x01;		//设置定时器模式TL0 = 0;		//设置定时初值TH0 = 0;		//设置定时初值TF0 = 0;		//清除TF0标志TR0 = 0;		//定时器0不计时
}

单独写一个给定时器0设置初值的函数

//定时器0设置计数器值
void Timer0_SetCounter(unsigned int Value)
{TH0=Value/256;//取出高八位赋值给TH0TL0=Value%256;//取出低八位赋值给TH0
}
//Value,要设置的计数器值,范围:0~65535

定时器0设置好初值后,再写一个获取定时器0当时的计数器值的函数

 //定时器0获取计数器值,范围:0~65535
unsigned int Timer0_GetCounter(void)
{return (TH0<<8)|TL0;//将TH0的8位数据左移8位,然后和TL0的8位数据组合成16位数据作为返回值
}

然后再写一个函数用来控制定时器的开始和结束

//定时器0启动停止控制
//Flag 启动停止标志,
//在TMOD寄存器中的GATE位等于0的情况下,TR0是定时器0在方式1的工作模式下的启停控制位
//1为启动,0为停止void Timer0_Run(unsigned char Flag)
{TR0=Flag;
}

将这几个函数声明一下

Timer0.h

#ifndef __TIMER0_H__
#define __TIMER0_H__void Timer0_Init(void);
void Timer0_SetCounter(unsigned int Value);
unsigned int Timer0_GetCounter(void);
void Timer0_Run(unsigned char Flag);#endif

接下来写一下红外解码的程序函数

IR.c

先定义好一些变量,后面会用到

#include <REGX52.H>
#include "Timer0.h"
#include "Int0.h"unsigned int IR_Time;//上一次中断到此次中断的时间
unsigned char IR_State;//接收的状态unsigned char IR_Data[4];//数据,4个字节,32位
unsigned char IR_pData;//告知当前是在第几位,每次进来pData++,告诉告知现在收到第几位了,收满32位之后就结束了unsigned char IR_DataFlag;//收到连发帧标志位
unsigned char IR_RepeatFlag;//重发标志
unsigned char IR_Address;//存的是地址
unsigned char IR_Command;//存的是命令码(就是遥控上的键码)

然后写一个红外遥控初始化函数

void IR_Init(void)
{Timer0_Init();//初始化定时器0Int0_Init();//初始化外部中断0
}

红外遥控获取收到数据帧标志位
返回值:是否收到数据帧,1为收到,0为未收到

unsigned char IR_GetDataFlag(void)
{if(IR_DataFlag){IR_DataFlag=0;//将收到连发帧标志位置0,方便下一次进行return 1;//代表已经收到了}return 0;//如果IR_DataFlag=0,直接return 0
}

红外遥控获取收到连发帧标志位
返回值:是否收到连发帧,1为收到,0为未收到

unsigned char IR_GetRepeatFlag(void)
{if(IR_RepeatFlag){IR_RepeatFlag=0;return 1;}return 0;
}

红外遥控获取收到的地址数据
返回值: 收到的地址数据

unsigned char IR_GetAddress(void)
{return IR_Address;
}

红外遥控获取收到的命令数据
返回值:收到的命令数据

unsigned char IR_GetCommand(void)
{return IR_Command;
}

外部中断0中断函数,下降沿触发执行 

这部分主要是根据这张图定义的函数

void Int0_Routine(void) interrupt 0
{//第一次进入中断函数时if(IR_State==0)				//状态0,空闲状态{Timer0_SetCounter(0);	//定时计数器清0Timer0_Run(1);			//定时器启动IR_State=1;				//置状态为1}//下一次进入中断函数时else if(IR_State==1)		//状态1,等待Start信号或Repeat信号{IR_Time=Timer0_GetCounter();	//获取上一次中断到此次中断的时间Timer0_SetCounter(0);	//定时计数器清0,方便下次计时//计数器每加1就是1微秒,1000us=1ms//如果计时为13.5ms即13500us,则接收到了Start信号(判定值在12MHz晶振下为13500,在11.0592MHz晶振下为12442)//因为有一些误差,所以有可能不是13500us整,需允许波动的范围//13500-11250=2250,允许波动的范围不能超过2250,可以给上下500的范围,上下500即1000的波动范围//所以给个上下500波动的范围即13500-500~13500+500合理if(IR_Time>13500-500 && IR_Time<13500+500){IR_State=2;			//置状态为2,下次再来中断就要开始解码数据}//如果计时为11.25ms,则接收到了Repeat信号(判定值在12MHz晶振下为11250,在11.0592MHz晶振下为10368)else if(IR_Time>11250-500 && IR_Time<11250+500){//如果接收到这个信号就说明一帧已经结束了,后面就不用数据了IR_RepeatFlag=1;	//置收到连发帧标志位为1Timer0_Run(0);		//定时器停止IR_State=0;			//置状态为0}else					//接收出错{IR_State=1;			//置状态为1,继续收Start信号或者repeat信号}}//以上情况执行完就接收完了起始信号//那再次进入中断函数来就要开始解码else if(IR_State==2)		//状态2,接收数据{IR_Time=Timer0_GetCounter();	//获取上一次中断到此次中断的时间Timer0_SetCounter(0);	//定时计数器清0,方便下次计时//如果计时为1120us,则接收到了数据0(判定值在12MHz晶振下为1120,在11.0592MHz晶振下为1032)if(IR_Time>1120-500 && IR_Time<1120+500){//收到0之后就要把数据写进去IR_Data[IR_pData/8]&=~(0x01<<(IR_pData%8));	//数据对应位清0//假设pData的范围是0~7,即一个字节长度//那么如果要将第一个字节的8位对应位清零//可以写成IR_Data[0]&=~(0x01<<IR_pData);//但是我们是要4个字节,把pData定义为告知32位数据中的哪一位数据,变化范围是0~31//要将pData的范围0~31拆成4个字节,也就是4个数组元素,一个字节8位//那么每8位就是一个数组元素,所以左移的范围要限制在一个字节中//因此左移的范围要限制在0~7,则IR_pData%8//4个数组元素范围是IR_Data[0]~IR_Data[3],则IR_pData/8,//这样程序就可以自动跳到下一个元素的第0位IR_pData++;			//数据位置指针自增}//如果计时为2250us,则接收到了数据1(判定值在12MHz晶振下为2250,在11.0592MHz晶振下为2074)else if(IR_Time>2250-500 && IR_Time<2250+500){IR_Data[IR_pData/8]|=(0x01<<(IR_pData%8));	//数据对应位置1IR_pData++;			//数据位置指针自增}else					//接收出错{IR_pData=0;			//数据位置指针清0IR_State=1;			//置状态为1}//32位数据解码完成后,开始验证if(IR_pData>=32)		//如果接收到了32位数据{IR_pData=0;			//数据位置指针清0if((IR_Data[0]==~IR_Data[1]) && (IR_Data[2]==~IR_Data[3]))	//数据验证{IR_Address=IR_Data[0];	//转存数据IR_Command=IR_Data[2];IR_DataFlag=1;	//置收到连发帧标志位为1}Timer0_Run(0);		//定时器停止IR_State=0;			//置状态为0}}
}

IR.h

声明一下这些函数,并且把键码重定义,方便主程序调用,不用每次都查找对应的键码

#ifndef __IR_H__
#define __IR_H__#define IR_POWER		0x45
#define IR_MODE			0x46
#define IR_MUTE			0x47
#define IR_START_STOP	0x44
#define IR_PREVIOUS		0x40
#define IR_NEXT			0x43
#define IR_EQ			0x07
#define IR_VOL_MINUS	0x15
#define IR_VOL_ADD		0x09
#define IR_0			0x16
#define IR_RPT			0x19
#define IR_USD			0x0D
#define IR_1			0x0C
#define IR_2			0x18
#define IR_3			0x5E
#define IR_4			0x08
#define IR_5			0x1C
#define IR_6			0x5A
#define IR_7			0x42
#define IR_8			0x52
#define IR_9			0x4Avoid IR_Init(void);
unsigned char IR_GetDataFlag(void);
unsigned char IR_GetRepeatFlag(void);
unsigned char IR_GetAddress(void);
unsigned char IR_GetCommand(void);#endif

main.c 

#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "IR.h"unsigned char Num;
unsigned char Address;
unsigned char Command;void main()
{LCD_Init();LCD_ShowString(1,1,"ADDR  CMD  NUM");LCD_ShowString(2,1,"00    00   000");IR_Init();while(1){if(IR_GetDataFlag() || IR_GetRepeatFlag())	//如果收到数据帧或者收到连发帧{Address=IR_GetAddress();		//获取遥控器地址码Command=IR_GetCommand();		//获取遥控器命令码LCD_ShowHexNum(2,1,Address,2);	//显示遥控器地址码LCD_ShowHexNum(2,7,Command,2);	//显示遥控器命令码,即键码if(Command==IR_VOL_MINUS)		//如果遥控器VOL-按键按下{Num--;						//Num自减}if(Command==IR_VOL_ADD)			//如果遥控器VOL+按键按下{Num++;						//Num自增}LCD_ShowNum(2,12,Num,3);		//显示Num}}
}

效果请看视频:

红外遥控显示键码值

注意:如果程序没有出凑,但是没有结果反应的话,请查看一下自己的开发板的晶振到底是12MHz还是11.0592MHz,这两种晶振的机器周期是不一样的,要在IR.c文件中的程序对应修改,要修改的地方在IR.c文件程序中已经给出了注释,请认真查看并修改!

红外遥控电机调速

新创建一个工程:红外遥控电机调速

这个程序是建立在之前写的直流电机调速的那个程序的基础上改造的,之前是用独立按键用控制电机的运转的速度,这次改为用红外遥控来控制电机的运转速度。

复用到的程序:

Delay函数

数码管

中断系统配置,定时器0配置,红外解码

Timer1.c

由于红外解码部分用了定时器0,所以我们要加一个定时器1程序,即将Timer0.c复制一份并且对应的地方改成定时器

#include <REGX52.H>void Timer1_Init(void)
{TMOD &= 0x0F;		//设置定时器模式TMOD |= 0x10;		//设置定时器模式TL1 = 0x9C;		//设置定时初值TH1 = 0xFF;		//设置定时初值TF1 = 0;		//清除TF1标志TR1 = 1;		//定时器1开始计时ET1=1;EA=1;PT1=0;
}

Timer.h

#ifndef __TIMER1_H__
#define __TIMER1_H__void Timer1_Init(void);#endif

Motor.c

写一个驱动电机的模块

#include <REGX52.H>
#include "Timer1.h"//引脚定义
sbit Motor=P1^0;unsigned char Counter,Compare;//电机初始化
void Motor_Init(void)
{Timer1_Init();
}//电机设置速度
//Speed 要设置的速度,范围0~100
void Motor_SetSpeed(unsigned char Speed)
{Compare=Speed;
}//定时器1中断函数
void Timer1_Routine() interrupt 3
{TL1 = 0x9C;		//设置定时初值TH1 = 0xFF;		//设置定时初值Counter++;Counter%=100;	//计数值变化范围限制在0~99if(Counter<Compare)	//计数值小于比较值{Motor=1;		//输出1}else				//计数值大于比较值{Motor=0;		//输出0}
}

Motor.h

#ifndef __MOTOR_H__
#define __MOTOR_H__void Motor_Init(void);
void Motor_SetSpeed(unsigned char Speed);#endif

main.c

#include <REGX52.H>
#include "Delay.h"
#include "Key.h"
#include "Nixie.h"
#include "Motor.h"
#include "IR.h"unsigned char Command,Speed;void main()
{Motor_Init();//初始化电机(定时器1初始化)IR_Init();//红外遥控初始化(定时器0和中断系统初始化)while(1){if(IR_GetDataFlag())	//如果收到数据帧{Command=IR_GetCommand();		//获取遥控器命令码//将命令码/键码和遥控上的数字对应起来if(Command==IR_0){Speed=0;}		//根据遥控器命令码设置速度if(Command==IR_1){Speed=1;}if(Command==IR_2){Speed=2;}if(Command==IR_3){Speed=3;}//Motor_SetSpeed相当于PWM输出中用到的比较值if(Speed==0){Motor_SetSpeed(0);}	//速度输出if(Speed==1){Motor_SetSpeed(50);}if(Speed==2){Motor_SetSpeed(75);}if(Speed==3){Motor_SetSpeed(100);}}Nixie(1,Speed);						//数码管显示速度}
}

 效果请看视频:

红外摇控调档速的小风扇

注意:如果程序没有出凑,但是没有结果反应的话,请查看一下自己的开发板的晶振到底是12MHz还是11.0592MHz,这两种晶振的机器周期是不一样的,要在IR.c文件中的程序对应修改,要修改的地方在IR.c文件程序中已经给出了注释,请认真查看并修改!

以上就是本篇的内容,源码会放在评论区(含12MHz和11.0592MHz两种源码),如有问题可评论区留言!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/260882.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux-ls命令

目录 ls&#xff1a;查看目录下文件/文件夹 ls -l&#xff1a;列表显示文件 ls -a&#xff1a;显示所有文件正常情况下‘ . ’开头的文件是隐藏的 ls -la&#xff1a;以列表形式显示所有文件包括隐藏文件 ls -lt&#xff1a;按时间倒序查看文件 ls -R&#xff1a;递归方式…

基于JavaWeb实现的在线蛋糕商城

一、系统架构 前端&#xff1a;jsp | bootstrap | js | css 后端&#xff1a;servlet | mybatis 环境&#xff1a;jdk1.7 | mysql | maven | tomcat 二、代码及数据库 三、功能介绍 01. web页-首页 02. web页-商品分类 03. web页-热销 04. web页-新品 05. w…

dockerfile文件书写

1.dockerfile构建nginx镜像 1.1书写dockerfile文件 mkdir nginx #创建nginx目录 cd nginx vim dockerfile # 修改文件FROM centos # 基础镜像&#xff0c;默认最新的centos8操作系统 MAINTAINER xianchao # 指定镜像的作者信息 RUN rm -rf /etc/yum.repos.d/* # centos8默认…

MongoDB 权限管理

文章目录 前言1. 权限控制1.1 MongoDB 默认角色1.1.1 读写角色1.1.2 管理角色1.1.3 其他角色1.1.4 超级用户角色 1.2 用户管理1.2.1 查看用户1.2.2 创建新用户1.2.3 调整角色1.2.4 删除用户1.2.4 修改密码 前言 上一篇 《MongoDB 单机安装部署》 文章中&#xff0c;为 MongoDB…

【HarmonyOS应用开发】三方库(二十)

三方库的基本使用 一、如何获取三方库 目前提供了两种途径获取开源三方库&#xff1a; 通过访问Gitee网站开源社区获取 在Gitee中&#xff0c;搜索OpenHarmony-TPC仓库&#xff0c;在tpc_resource中对三方库进行了资源汇总&#xff0c;可以供开发者参考。 通过OpenHarmony三…

自然语言编程系列(二):自然语言处理(NLP)、编程语言处理(PPL)和GitHub Copilot X

编程语言处理的核心是计算机如何理解和执行预定义的人工语言&#xff08;编程语言&#xff09;&#xff0c;而自然语言处理则是研究如何使计算机理解并生成非正式、多样化的自然语言。GPT-4.0作为自然语言处理技术的最新迭代&#xff0c;其编程语言处理能力相较于前代模型有了显…

QEMU源码全解析 —— virtio(20)

接前一篇文章&#xff1a; 上回书重点解析了virtio_pci_modern_probe函数。再来回顾一下其中相关的数据结构&#xff1a; struct virtio_pci_device struct virtio_pci_device的定义在Linux内核源码/drivers/virtio/virtio_pci_common.h中&#xff0c;如下&#xff1a; /* O…

智慧驿站_智慧文旅驿站_轻松的驿站智慧公厕_5G智慧公厕驿站_5G模块化智慧公厕

多功能城市智慧驿站是在智慧城市建设背景下&#xff0c;所涌现的一种创新型社会配套设施。其中&#xff0c;智慧公厕作为城市智慧驿站的重要功能基础&#xff0c;具备社会配套不可缺少的特点&#xff0c;所以在应用场景上&#xff0c;拥有广泛的需求和要求。那么&#xff0c;城…

springcloud-网关(gateway)

springcloud-网关(gateway) 概述 \Spring Cloud Gateway旨在提供一种简单而有效的方式来路由到API&#xff0c;并为其提供跨领域的关注&#xff0c;如&#xff1a;安全、监控/指标和容错 常用术语 Route&#xff08;路由&#xff09;: 网关的基本构件。它由一个ID、一个目的地…

【ArcGIS微课1000例】0103:导出点、线、面要素的折点坐标值

点要素对应的是一个或者若干个坐标,线要素对应的是对个坐标值对应的点连起来,面要素是多个坐标值对应的点连起来构成的封闭多边形。本文讲述导出点的坐标值。 文章目录 一、点要素坐标导出1. 计算点坐标2. 导出点坐标二、线要素坐标导出1. 生成线要素折点2. 计算折点坐标3. 导…

【打工日常】使用docker部署Dashdot工具箱

一、Dashdot介绍 dashdot是一个简洁清晰的服务器数据仪表板&#xff0c;基于React实现 &#xff0c;主要是显示操作系统、进程、存储、内存、网络这五个的数据。 二、本次实践介绍 1. 本次实践简介 本次实践部署环境为个人测试环境 2. 本地环境规划 本次实践环境规划&#xf…

S-35390A开发

计时芯片 S-35390A芯片是计时芯片&#xff0c;一般用来计算时间。低功耗&#xff0c;宽电压&#xff0c;受温度影响小&#xff0c;适用于很多电路。它有一个问题&#xff0c;不阻止用户设置不存在的时间&#xff0c;设置进去之后计时或者闹钟定时会出错。 规格书阅读 首先我…

成为大佬之路--linux软件安装使用第000000003篇--vmare安装centos

准备工作 1.下载centos安装包 2.安装vmare 建议直接百度 绿色版 直接上最新版本旗舰版(pro) 新建虚拟机 1.打开vamre,点击文件--新建虚拟机 2.直接默认选择 "典型",点击下一步 3. 选择稍后安装操作系统,点击下一步 4.选择linux版本 因为安装的是centos直接选…

Arcmap excel转shp

使用excel表格转shp的时候&#xff0c;如果你的excel里面有很多字段&#xff0c;直接转很大概率会出现转换结果错误的情况&#xff0c;那么就需要精简一下字段的个数。将原来的表格文件另存一份&#xff0c;在另存为的文件中只保留关键的经度、纬度、和用于匹配的字段即可&…

【C++】C++11下线程库

C11下线程库 1. thread类的简单介绍2.线程函数参数3.原子性操作库(atomic)4.mutex的种类5. RAII风格加锁解锁5.1Lock_guard5.2unique_lock 6.condition_variable 1. thread类的简单介绍 在C11之前&#xff0c;涉及到多线程问题&#xff0c;都是和平台相关的&#xff0c;比如wi…

代码随想录第二十一天 701.二叉搜索树中的插入操作 108.将有序数组转换为二叉搜索树

701.二叉搜索树中的插入操作 题目描述 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和要插入树中的值 value &#xff0c;将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 &#xff0c;新值和原始二叉搜索树中的任意节点值都不同。 注意&a…

pom.xml常见依赖及其作用

1.org.mybatis.spring.boot下的mybatis-spring-boot-starter&#xff1a;这个依赖是mybatis和springboot的集成库&#xff0c;简化了springboot项目中使用mybatis进行持久化操作的配置和管理 2.org.projectlombok下的lombok&#xff1a;常用注解Data、NoArgsConstructor、AllA…

ArcGIS学习(八)基于GIS平台的控规编制办法

ArcGIS学习(八)基于GIS平台的控规编制办法 上一任务我们学习了”如何进行图片数据的矢量化?" 这一关我们来学习一个比较简单的案例一一”如何在ArcGIS中录入控规指标,绘制控规图纸?" 首先,先来看看这个案例的分析思路以及导入CAD格式的控规图纸。 接着,来看…

使用静态CRLSP配置MPLS TE隧道

正文共&#xff1a;1591 字 13 图&#xff0c;预估阅读时间&#xff1a;4 分钟 静态CRLSP&#xff08;Constraint-based Routed Label Switched Paths&#xff0c;基于约束路由的LSP&#xff09;是指在报文经过的每一跳设备上&#xff08;包括Ingress、Transit和Egress&#xf…

如何邀请媒体参加活动报道?媒体邀约的几大步骤?

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 邀请媒体参加活动报道通常需要发送邀请函、提供详细活动信息&#xff0c;并通过电话或邮件进行跟进确认。 在邀请媒体之前&#xff0c;应该制定一个详细的媒体规划表&#xff0c;包括拟…