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

这篇具有很好参考价值的文章主要介绍了单片机学习笔记---红外遥控&红外遥控电机调速(完结篇)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

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

红外遥控

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来举个例子:

单片机学习笔记---红外遥控&红外遥控电机调速(完结篇),51单片机学习笔记,单片机,学习,笔记,51单片机,mcu,物联网,嵌入式硬件

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

单片机学习笔记---红外遥控&红外遥控电机调速(完结篇),51单片机学习笔记,单片机,学习,笔记,51单片机,mcu,物联网,嵌入式硬件

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

单片机学习笔记---红外遥控&红外遥控电机调速(完结篇),51单片机学习笔记,单片机,学习,笔记,51单片机,mcu,物联网,嵌入式硬件

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

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

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

单片机学习笔记---红外遥控&红外遥控电机调速(完结篇),51单片机学习笔记,单片机,学习,笔记,51单片机,mcu,物联网,嵌入式硬件

然后在主程序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++;
}

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

效果请看视频:

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

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

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

红外遥控

现在开始正式演示代码:

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

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

单片机学习笔记---红外遥控&红外遥控电机调速(完结篇),51单片机学习笔记,单片机,学习,笔记,51单片机,mcu,物联网,嵌入式硬件

然后先创建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;//取出高八位赋值给TH0
	TL0=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();//初始化定时器0
	Int0_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中断函数,下降沿触发执行 

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

单片机学习笔记---红外遥控&红外遥控电机调速(完结篇),51单片机学习笔记,单片机,学习,笔记,51单片机,mcu,物联网,嵌入式硬件

void Int0_Routine(void) interrupt 0
{
	//第一次进入中断函数时
	if(IR_State==0)				//状态0,空闲状态
	{
		Timer0_SetCounter(0);	//定时计数器清0
		Timer0_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;	//置收到连发帧标志位为1
			Timer0_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));	//数据对应位置1
			IR_pData++;			//数据位置指针自增
		}
		else					//接收出错
		{
			IR_pData=0;			//数据位置指针清0
			IR_State=1;			//置状态为1
		}
		
		//32位数据解码完成后,开始验证
		if(IR_pData>=32)		//如果接收到了32位数据
		{
			IR_pData=0;			//数据位置指针清0
			if((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

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

单片机学习笔记---红外遥控&红外遥控电机调速(完结篇),51单片机学习笔记,单片机,学习,笔记,51单片机,mcu,物联网,嵌入式硬件

#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			0x4A

void 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函数

单片机学习笔记---红外遥控&红外遥控电机调速(完结篇),51单片机学习笔记,单片机,学习,笔记,51单片机,mcu,物联网,嵌入式硬件

数码管

单片机学习笔记---红外遥控&红外遥控电机调速(完结篇),51单片机学习笔记,单片机,学习,笔记,51单片机,mcu,物联网,嵌入式硬件

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

单片机学习笔记---红外遥控&红外遥控电机调速(完结篇),51单片机学习笔记,单片机,学习,笔记,51单片机,mcu,物联网,嵌入式硬件

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~99
	if(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两种源码),如有问题可评论区留言!文章来源地址https://www.toymoban.com/news/detail-833237.html

到了这里,关于单片机学习笔记---红外遥控&红外遥控电机调速(完结篇)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【51单片机学习】PWM电机调速

    中断允许寄存器,详情可以看STC51单片机芯片手册第160页 TMOD、TCON详情可以看STC51单片机芯片手册第187页 51单片机中的定时器有三个,(C52比C51多了一个定时器3,但这些都统称为51单片机) 本次以 Timer0 为例进行介绍 定时器的作用: 1:用于计时系统,可实现软件计时,或者使程

    2023年04月18日
    浏览(79)
  • 51单片机--红外遥控

    红外遥控是一种无线、非接触控制技术, 通过使用红外线来传送控制信号。它具有抗干扰能力强、信息传输可靠、功耗低、成本低、易实现等显著优点 ,因此被广泛应用于各种电子设备和家用电器,也越来越多地应用于计算机和手机系统中。 红外遥控系统一般由 发射和接收

    2024年02月15日
    浏览(40)
  • 51单片机 (十八)红外遥控

    什么是红外线?         人的眼睛能看到的可见光按波长从长到短排列,依次为红、橙、黄、绿、青、蓝、紫。其中红光的波长范围为0.62~0.76μm;紫光的波长范围为0.38~0.46μm。比紫光波长还短的光叫紫外线,比红光波长还长的光叫红外线.红外线遥控就是利用波长为0.

    2024年02月08日
    浏览(38)
  • 【【51单片机的红外遥控】】

    红外遥控 利用红外光进行通信的设备,由红外LED将调制后的信号发出,再由专门的红外接收头进行解调输出 通信方式:单工 异步 红外LED波长:940nm 通信协议标准:NEC标准 用那种一体化红红外接收头 直接帮忙滤波 好用一点 因为用红外遥控案件按下 速度太快了 比普通按键按

    2024年02月15日
    浏览(37)
  • (十六)51单片机——红外遥控

    目录 学习目标 成果展示  硬件知识 简介 硬件电路 NEC编码 遥控器键码 外部中断  中断号 寄存器 代码  红外调控  直流电机 总结            本节知识我们来学习关于红外遥控的部分,重点要学习的是NEC编码和外部中断的知识,好了,让我们开始今天的学习吧! 红外遥

    2023年04月09日
    浏览(37)
  • 51单片机-PWM调速(直流电机,智能小车的电机调速)

    这次来对PWM做一个总结 最近学习时,发现PWM控制在很多地方都会用到,比如使用PWM来控制电机的速度,使用PWM来生成想要的波形。 那么到底什么是PWM呢? PWM即 脉冲宽度调制 ,在具有惯性的系统中,可以通过对 一系列脉冲的宽度进行调制 ,来等效的获得所需要的模拟参量。

    2024年02月02日
    浏览(46)
  • 【【51单片机红外遥控小风车】】

    今天结束了51单片机的学习,明天开始学习stm32 我是学习江科大的视频一步一步完成的 ,他讲的非常好,非常好 特别通俗易懂 学习复刻他的作品我也自己创作了一些 但是现在暂时脱离这块板子了 以后可能会更新一个应用51单片机制作的智能小车 我特别想开一个小车的坑 谢

    2024年02月15日
    浏览(39)
  • 【【51单片机直流电机调速】】

    PWM的生成方法 先用户设定一个比较值,然后计数器定时自增。 当计数器比较值,输出0 当计数器比较值,输出1

    2024年02月15日
    浏览(46)
  • 【【51单片机11.0592晶振红外遥控】】

    这是初步实现的架构 怎么实现内部的详细逻辑 我们用状态机的方法 0状态时一个空闲状态 当它接收到下降沿开始计时然后转为1状态 1状态下 寻找start 或者repeat的信号 再来下降沿读出定时器的值 如果是start 那就进入2状态开始译码 如果repeat 那么重发标志位 重新切回去 我每次

    2024年02月15日
    浏览(40)
  • 通过51单片机实现直流电机调速

    随着各种工业生产设备和机械设备的广泛使用,直流电机调速技术的研究和应用越来越受到人们的重视,具有广泛的应用前景。本项目通过51单片机实现直流电机调速功能,为实际工程应用提供一个可靠和有效的调速方案。 如果需要下载项目工程,可以去这里: https://blog.c

    2024年02月14日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包