当前位置: 首页 > news >正文

51单片机—智能垃圾桶(定时器)

一. 定时器

1. 简介

C51中的定时器和计数器是同一个硬件电路支持的,通过寄存器配置不同,就可以将他当做定时器或者计数器使用。

确切的说,定时器和计数器区别是致使他们背后的计数存储器加1的信号不同。当配置为定时器使用时,每经过1个机器周期,计数存储器的值就加1。而当配置为计数器时,每来一个负跳变信号(信号从P3.4 或者P3.5引脚输入),就加1,以此达到计数的目的。

标准C51有2个定时器/计数器:T0和T1。他们的使用方法一致。C52相比C51多了一个T2

1.1 概念解读
  • 定时器和计数器,电路一样
  • 定时或者计数的本质就是让单片机某个部件数数
  • 当定时器用的时候,靠内部震荡电路数数
  • 当计数器用的时候,数外面的信号,读取针脚的数据

在51单片机中,定时器和计数器的主要区别在于它们的工作方式和用途:

  • 定时器(Timer)
    • 工作方式:定时器使用内部时钟源(例如晶振)进行计数。
    • 用途:用于计时,例如生成精确的时间延迟、实现周期性中断等。
    • 例子:设定一个定时器来每隔一秒触发一次中断,用于更新系统时钟。
  • 计数器(Counter)
    • 工作方式:计数器通过外部信号(例如外部引脚上的脉冲信号)进行计数。
    • 用途:用于计数外部事件或脉冲,例如计数输入脉冲的次数。
    • 例子:连接一个传感器到单片机的计数器引脚,计数传感器发出的脉冲信号。
1.2 定时器怎么定时

定时器的本质原理: 每经过一个机器周期,就加1 :寄存器

思考:

  • 什么是晶振

晶振(晶体震荡器),又称数字电路的“心脏”,是各种电子产品里面必不可少的频率元器件。数字电

路的所有工作都离不开时钟,晶振的好坏、晶振电路设计的好坏,会影响到整个系统的稳

  • 什么是时钟周期

时钟周期也称为振荡周期,定义为时钟频率的倒数。时钟周期是计算机中最基本的、最小的时间单

位。在一个时钟周期内,CPU仅完成一个最基本的动作。时钟周期是一个时间的量。更小的时钟周

期就意味着更高的工作频率

  • 什么是机器周期

机器周期也称为CPU周期。在计算机中,为了便于管理,常把一条指令的执行过程划分为若干个阶

段(如取指、译码、执行等),每一阶段完成一个基本操作。完成一个基本操作所需要的时间称为

机器周期。一般情况下,一个机器周期由若干个时钟周期组成

  • 加1经过了多少时间

当晶振频率是11.0592MHz的时候,等于11059.2KHz = 11059200Hz

跳一次等于一个机器周期

一个机器周期等于12个时钟周期

一个时钟周期等于晶振的倒数:1/11059200秒

那么跳一次就是:12/11059200秒 = 12000000/11059200 微秒= 1.085微妙

机器周期 = 12 x 时钟周期

= 12 x (1/时钟频率) 秒 = 12 / 时钟频率 秒 = 12 / 11059200 秒 = 12 000 000 / 11059200 微秒 = 1.085 微秒

1.3 定时器编程

相关寄存器:

  • 在哪里加1,最大计数时间,也就是爆表了能计算多长

在T8H0/1和TL0/1寄存器中加1,默认是从0开始数数,最多能数65536下,累计计时71ms ,71毫秒

  • 如何算出10ms定时器的初值

就不让他从0开始数数,10ms需要数9216下,你让他从65536-9126=56320(16进制表示为

0xDC00)开始数数

这样TL0=0x00;TH0=0xDC

  • 关于TCON

  • 怎么知道爆表

TCON寄存器的bit5(TF0)能表示爆表:当爆表的时候,硬件会修改bit5(TF0)位上面的数据,改成 1(置1),如果不用中断,我们代码清零。

  • 怎么开始计时

TCON寄存器的bit4,TRO通过编程让这个位为1的时候,开始计时,相当于按下了闹钟

  • 定时器使用是有很多种模式的

定时器模式寄存器:TMOD来选择定时器模式,选择工作方式1,TMOD的bit0 bit1配置成0 1 :16 位的定时器功能

  • 四个二进制数表示一位的16进制数

8421法进制的转换,二进制转16进制(方便人类来看,对计算机底层来说,不关心二进制010101010)。

配寄存器推荐用按位操作,清零的时候,对应的需要清零的位与上0,不需要清零的位与上1

置1的时候,需要置1的位置或1,不需要置一的位置或0

AUXR,降低单片机时钟对外界的辐射。

  • 定时器控制led灯每隔一秒灭一次
#include "reg52.h"sbit led1 = P3^6;   // 定义 led1 变量,指向 P3.6 引脚
sbit led2 = P3^7;   // 定义 led2 变量,指向 P3.7 引脚void main()
{// 1.配置定时器0工作模式为16位计数器模式int cnt = 0;  // 定义一个整数变量 'cnt' 用于计数led1 = 1; // 初始化 led1 为高电平(假设高电平点亮)led2 = 0; // 初始化 led2 为低电平(假设低电平熄灭)TMOD = 0x01; // 配置定时器0为模式1(16位定时器模式)// 2.设置定时器初值,使其每10ms产生一次溢出TL0 = 0x00; // 设置定时器0低8位初值为 0x00TH0 = 0xDC; // 设置定时器0高8位初值为 0xDC// 3.启动计时TR0 = 1;  // 启动定时器0TF0 = 0;  // 清除定时器0溢出标志位while(1) {   // 无限循环if(TF0 == 1) { // 如果定时器0溢出  爆表TF0 = 0; // 清除定时器0溢出标志位cnt++; // 增加计数器 'cnt' 的值// 重新设置定时器初值TL0 = 0x00;   TH0 = 0xDC;if(cnt == 100) { // 如果计数器 'cnt' 达到 100(即经过1秒)cnt = 0; // 重置计数器 'cnt'led1 = !led1; // 翻转 led1 的状态led2 = !led2; // 翻转 led2 的状态}}}
}

1.4 定时器中断方式控制 (相当于多线程)

中断寄存器

  • 定时器中断方式控制led
#include "reg52.h"  // 包含51系列单片机寄存器定义文件sbit led = P3^6;   // 定义一个位变量led,连接到P3端口的第6位(LED1)
sbit led1 = P3^7;  // 定义一个位变量led1,连接到P3端口的第7位(LED2)
int cnt = 0;       // 定义一个整数变量cnt,用来统计定时器溢出的次数// 定义定时器0初始化函数
void Time0Init()
{// 1. 配置定时器0工作模式为16位计时模式TMOD = 0x01;    // 设置TMOD寄存器为0x01,定时器0为16位定时器模式// 2. 设置定时器初值,以生成大约10ms的定时TL0 = 0x00;    // 设置定时器0低8位初值为0x00TH0 = 0xDC;    // 设置定时器0高8位初值为0xDC(即0xDC00)// 3. 启动定时器0TR0 = 1;       // 启动定时器0,使其开始计时TF0 = 0;       // 清除定时器0的溢出标志位(初始为0)// 4. 启用定时器0中断ET0 = 1;       // 使能定时器0中断,使单片机能够响应定时器0的中断请求// 5. 启用总中断EA = 1;        // 启用全局中断,使单片机能够响应所有中断请求
}void main()
{led = 1;       // 将LED1点亮(即将P3^6置为高电平)led1 = 0;      // 将LED2熄灭(即将P3^7置为低电平)Time0Init();   // 调用定时器初始化函数,设置定时器0并启动定时器while(1) {// 无限循环,程序在这里等待中断事件发生// 这部分代码可以执行其他任务,但本例中为空}
}// 定时器0中断处理函数  interrupt 1 定时器0的优先级
void Time0Handler() interrupt 1
{cnt++;        // 每次定时器0溢出时,计数器cnt增加1// 重新设置定时器0的初值,保持定时周期不变TL0 = 0x00;  // 重新加载定时器0低8位初值为0x00TH0 = 0xDC;  // 重新加载定时器0高8位初值为0xDC(即0xDC00)if (cnt == 30) { // 如果定时器0溢出30次(约300ms)cnt = 0;     // 重置计数器cnt为0// 翻转LED的状态led = !led;   // 每300ms翻转LED1的状态led1 = !led1; // 每300ms翻转LED2的状态}
}

这段代码是用来在51系列单片机中配置定时器0,使其每隔1秒钟翻转一个LED的状态。下面是对每一部分的详细解释:

1. 头文件和变量定义
#include "reg52.h"sbit led = P3^6;  // 定义一个位变量led,连接到P3端口的第6位(LED1)
sbit led1 = P3^7; // 定义一个位变量led1,连接到P3端口的第7位(LED2)
int cnt = 0;      // 定义一个整数变量cnt,用来统计定时器溢出次数
  • #include "reg52.h":包含51系列单片机的寄存器定义文件。
  • sbit led = P3^6;:将单片机的P3端口的第6位定义为 led,用于控制LED的开关。
  • sbit led1 = P3^7;:将P3端口的第7位定义为 led1,虽然在代码中没有使用。
  • int cnt = 0;:定义一个计数器 cnt,用于跟踪定时器0的溢出次数。
2. Time0Init 函数
void Time0Init()
{//1. 配置定时器0工作模式位16位计时TMOD = 0x01;//2. 给初值,定一个10ms出来TL0=0x00;TH0=0xDC;//3. 开始计时TR0 = 1;TF0 = 0;//4. 打开定时器0中断ET0 = 1;//5. 打开总中断EAEA = 1;
}
  • TMOD = 0x01;:将 TMOD 寄存器的值设置为 0x01,将定时器0配置为模式1(16位定时器模式)。低4位 0001 表示定时器0的工作模式。
  • TL0 = 0x00;TH0 = 0xDC;:设置定时器0的初始值。TH0TL0 设置为 0xDC00,这样定时器从 0xDC00 开始计数。
  • TR0 = 1;:启动定时器0。
  • TF0 = 0;:清除定时器0的溢出标志位。
  • ET0 = 1;:允许定时器0的中断。
  • EA = 1;:允许总中断,使单片机能够响应所有中断请求。
3. main 函数
void main()
{led = 1;     // 初始时点亮LEDTime0Init(); // 初始化定时器0while(1){// 无限循环,等待中断发生}
}
  • led = 1;:在程序开始时,将 led 设为1,点亮LED。
  • Time0Init();:调用初始化定时器0的函数。
  • while(1){}:无限循环,程序在这里等待中断事件发生。实际的操作由中断处理函数完成。
4. 定时器0中断处理函数
void Time0Handler() interrupt 1
{cnt++;  // 统计溢出次数// 重新设置定时器初值TL0=0x00;TH0=0xDC;if(cnt == 100) {  // 每100次溢出表示1秒cnt = 0;     // 重置计数器led = !led;  // 翻转LED状态}
}
  • void Time0Handler() interrupt 1:定义了一个中断服务函数,用于处理定时器0的中断。interrupt 1 表示这是定时器0的中断处理函数。
  • cnt++;:每次定时器0溢出时,计数器 cnt 增加1。
  • TL0 = 0x00;TH0 = 0xDC;:重新加载定时器初值,保持定时器周期不变。
  • if(cnt == 100):检查 cnt 是否达到100。每100次溢出表示1秒(因为10毫秒 × 100 = 1000毫秒,即1秒)。
    • cnt = 0;:重置 cnt 以开始新的计时周期。
    • led = !led;:每秒钟翻转LED的状态。
总结
  • 初始化Time0Init 函数设置定时器0的工作模式和初值,并开启定时器中断。
  • 主程序main 函数设置LED初始状态,并无限循环等待中断。
  • 中断处理Time0Handler 函数在每次定时器0溢出时执行,统计溢出次数,并每1秒翻转一次LED的状态。

  • 定时器中断方式控制led,led灯多线程 控制
#include "reg52.h"// 定义LED控制的位变量
sbit led = P3^6;   // LED1 连接到P3端口的第6位
sbit led1 = P3^7;  // LED2 连接到P3端口的第7位int cnt = 0;       // 用于计数定时器溢出次数的变量// 定时器0初始化函数
void Time0Init()
{// 1. 配置定时器0工作模式为16位计时模式TMOD = 0x01;   // 设置定时器0为16位计时器模式(模式1)// 2. 给定初值,设置一个10ms的定时周期TL0 = 0x00;    // 设置定时器0的低8位初值TH0 = 0xDC;    // 设置定时器0的高8位初值// (0xDC00 是 16位定时器初值,用来生成10ms的定时周期)// 3. 开始计时TR0 = 1;       // 启动定时器0TF0 = 1;       // 设置定时器0的溢出标志位(启动时应清零,但此处设为1可能是为确保中断服务函数能被触发)// 4. 打开定时器0中断ET0 = 1;       // 使能定时器0中断// 5. 打开总中断EAEA = 1;        // 使能总中断,允许所有中断请求
}// 延时函数
void Delay300ms()		//@11.0592MHz
{unsigned char i, j, k;i = 3;  // 外循环计数j = 26; // 中循环计数k = 223; // 内循环计数do{do{while (--k);  // 内循环延时} while (--j);  // 中循环延时} while (--i);  // 外循环延时
}// 主函数
void main()
{led = 1;    // 初始化时将LED1点亮led1 = 0;   // 初始化时将LED2熄灭Time0Init(); // 调用定时器0初始化函数while(1) {// 无限循环led1 = 0;       // LED2熄灭Delay300ms();   // 延时300msled1 = 1;       // LED2点亮Delay300ms();   // 延时300ms}
}// 定时器0中断服务函数
void Time0Handler() interrupt 1
{cnt++;      // 每次定时器0溢出时,计数器cnt增加1// 重新给定时器0初值,以保持定时周期TL0 = 0x00; // 重新加载定时器0的低8位初值TH0 = 0xDC; // 重新加载定时器0的高8位初值if(cnt == 30) { // 每30次溢出表示约1秒(10ms * 30 = 300ms)cnt = 0;     // 重置计数器cnt,以开始新的计时周期led = !led;  // 翻转LED1的状态}
}

当然,下面是对你提供的代码的详细解释,逐步解释每一部分的功能和目的:

1. 头文件和变量定义
#include "reg52.h"// 定义LED控制的位变量
sbit led = P3^6;   // LED1 连接到P3端口的第6位
sbit led1 = P3^7;  // LED2 连接到P3端口的第7位int cnt = 0;       // 用于计数定时器溢出次数的变量
  • #include "reg52.h":包括一个头文件,这个文件通常包含对51系列单片机寄存器的定义。
  • sbit led = P3^6;sbit led1 = P3^7;:将 ledled1 分别定义为 P3 端口的第6位和第7位,控制对应的LED灯。sbit 是位变量的定义方式,用于操作单片机的特定位。
  • int cnt = 0;:定义一个全局变量 cnt,用来计数定时器溢出次数。
2. 定时器0初始化函数
void Time0Init()
{// 1. 配置定时器0工作模式为16位计时模式TMOD = 0x01;   // 设置定时器0为16位定时器模式(模式1)// 2. 给定初值,设置一个10ms的定时周期TL0 = 0x00;    // 设置定时器0的低8位初值TH0 = 0xDC;    // 设置定时器0的高8位初值// (0xDC00 是 16位定时器初值,用来生成10ms的定时周期)// 3. 开始计时TR0 = 1;       // 启动定时器0TF0 = 1;       // 设置定时器0的溢出标志位(启动时应清零,但此处设为1可能是为确保中断服务函数能被触发)// 4. 打开定时器0中断ET0 = 1;       // 使能定时器0中断// 5. 打开总中断EAEA = 1;        // 使能总中断,允许所有中断请求
}
  • 配置定时器模式
    • TMOD = 0x01;:设置定时器0为模式1(16位定时器模式)。TMOD 寄存器的低4位设置定时器0的模式,0x01 表示模式1,即16位计时器。
  • 设置定时初值
    • TL0 = 0x00;TH0 = 0xDC;:设置定时器0的低8位(TL0)和高8位(TH0)的初值。这里的初值 0xDC00(16位)用来生成一个10ms的定时周期。具体的10ms周期计算基于单片机的时钟频率(11.0592 MHz)。
  • 启动定时器和中断
    • TR0 = 1;:启动定时器0,开始计时。
    • TF0 = 1;:设置溢出标志位。这通常在定时器启动时应清除,但此处设为1可能是为了确保中断服务函数能被触发。
    • ET0 = 1;:使能定时器0的中断,允许定时器溢出时触发中断。
    • EA = 1;:使能所有中断,允许中断请求的处理。
3. 延时函数
void Delay300ms()		//@11.0592MHz
{unsigned char i, j, k;i = 3;  // 外循环计数j = 26; // 中循环计数k = 223; // 内循环计数do{do{while (--k);  // 内循环延时} while (--j);  // 中循环延时} while (--i);  // 外循环延时
}
  • 延时函数
    • Delay300ms() 用来实现一个大约300ms的延时。
    • 使用嵌套的 do-while 循环来耗费时间。外层循环 i 控制循环次数,中层循环 j 和内层循环 k 控制每次循环的延时。具体的延时时间取决于单片机的时钟频率(11.0592 MHz)。
4. 主函数
void main()
{led = 1;    // 初始化时将LED1点亮led1 = 0;   // 初始化时将LED2熄灭Time0Init(); // 调用定时器0初始化函数while(1) {// 无限循环led1 = 0;       // LED2熄灭Delay300ms();   // 延时300msled1 = 1;       // LED2点亮Delay300ms();   // 延时300ms}
}
  • 主函数
    • 初始化时将LED1点亮 (led = 1;),LED2熄灭 (led1 = 0;)。
    • 调用 Time0Init() 初始化定时器0。
    • 进入无限循环,在其中交替点亮和熄灭LED2,每次切换后调用 Delay300ms() 实现300ms的延时。
5. 定时器0中断服务函数
void Time0Handler() interrupt 1
{cnt++;      // 每次定时器0溢出时,计数器cnt增加1// 重新给定时器0初值,以保持定时周期TL0 = 0x00; // 重新加载定时器0的低8位初值TH0 = 0xDC; // 重新加载定时器0的高8位初值if(cnt == 30) { // 每30次溢出表示约1秒(10ms * 30 = 300ms)cnt = 0;     // 重置计数器cnt,以开始新的计时周期led = !led;  // 翻转LED1的状态}
}
  • 定时器0中断服务函数
    • void Time0Handler() interrupt 1:这是定时器0的中断服务函数。interrupt 1 表示它处理定时器0的中断请求。
    • cnt++:每次定时器0溢出时,计数器 cnt 增加1。
    • 重新设置定时器0的初值 (TL0TH0),以保持定时器的计时周期。
    • cnt 达到30时(每30次10ms溢出约300ms),重置 cnt 并翻转LED1的状态。

二、PWM开发SG90

2.1 简介

PWM,英文名Pulse Width Modulation,是脉冲宽度调制缩写,它是通过对一系列脉冲的宽度进 行调制,等效出所需要的波形(包含形状以及幅值),对模拟信号电平进行数字编码,也就是说通过调节占空比的变化来调节信号、能量等的变化,占空比就是指在一个周期内,信号处于高电平的 时间占据整个信号周期的百分比,例如方波的占空比就是50%.

  • 脉冲宽度调制
  • 通过占空比编码模拟信号
  • 占空比 一个周期内,高电平占据时长的百分比

4毫秒为一个(波形)周期,其中3ms为低电平,1ms为高电平

什么是占空比 :一个周期内,高电平占据时长的百分比,为25%。

2.2 如何实现PWM信号输出

1. 通过芯片内部模块输出,一般观察手册或者芯片IO口都会标明这个是否是PWM口

如下图增强51,STC15w的

2. 如果没有集成PWM功能,可以通过IO口软件模拟,相对硬件PWM来说精准度略差 ,怎么模拟;

搞个50HZ频率的pwm;

2.3 控制舵机
1. 什么是舵机

如下图所示,最便宜的舵机sg90,常用三根或者四根接线,黄色为PWM信号控制

用处:垃圾桶项目开盖用、智能小车的全比例转向、摄像头云台、机械臂等

常见的有0-90°、0-180°、0-360°

2. 怎么控制舵机

向黄色信号线“灌入”PWM信号。

PWM波的频率不能太高,大约50HZ,即周期=1/频率=1/50=0.02s,20ms左右

数据:

0.5ms-------------0度; 2.5% 对应函数中占空比为250

1.0ms------------45度; 5.0% 对应函数中占空比为500

1.5ms------------90度; 7.5% 对应函数中占空比为750

2.0ms-----------135度; 10.0% 对应函数中占空比为1000

2.5ms-----------180度; 12.5% 对应函数中占空比为1250

定时器需要定时20ms, 关心的单位0.5ms, 40个的0.5ms,初值0.5m cnt++

1s = 10ms * 100

20ms = 0.5ms * 40 \

  • 编程实现

#include "reg52.h"sbit sg90_con = P1^1;  // 定义一个名为 sg90_con 的引脚,与 P1 端口的第 1 位连接int jiaodu ;  // 定义一个整数变量 jiaodu,用于表示角度
int cnt = 0;  // 定义一个计数器变量 cnt,用于统计定时器溢出次数// 延时 2000 毫秒函数
void Delay2000ms()		//@11.0592MHz
{unsigned char i, j, k;i = 15;j = 2;k = 235;do{do{while (--k);  // 内层循环,k 减到 0} while (--j);  // 中层循环,j 减到 0} while (--i);  // 外层循环,i 减到 0
}// 定时器0初始化函数
void Time0Init()
{//1. 配置定时器0工作模式为16位计时TMOD = 0x01;//2. 设置初值,定时10msTL0=0x33;TH0=0xFE;//3. 开始计时TR0 = 1;TF0 = 0;//4. 打开定时器0中断ET0 = 1;//5. 打开总中断EAEA = 1;
}// 延时 300 毫秒函数
void Delay300ms()		//@11.0592MHz
{unsigned char i, j, k;i = 3;j = 26;k = 223;do{do{while (--k);  // 内层循环,k 减到 0} while (--j);  // 中层循环,j 减到 0} while (--i);  // 外层循环,i 减到 0
}void main()
{Delay300ms();  // 让硬件稳定一下Time0Init();  // 初始化定时器jiaodu = 1;   // 初始角度是 0 度,高电平时间为 0.5mscnt = 0;sg90_con = 1;  // 一开始从高电平开始// 每隔两秒切换一次角度while(1){jiaodu = 3;  // 90度,高电平时间为 1.5mscnt = 0;Delay2000ms();jiaodu = 1;  // 0度,高电平时间为 0.5mscnt = 0;Delay2000ms();}
}// 定时器0中断处理函数
void Time0Handler() interrupt 1
{cnt++;  // 统计溢出次数// 重新设置定时器初值TL0=0x33;TH0=0xFE;// 控制PWM波if(cnt < jiaodu){	sg90_con = 1;  // 设置高电平}else{sg90_con = 0;  // 设置低电平} if(cnt == 40){  // 溢出40次,经过20mscnt = 0;  // 重新开始计数sg90_con = 1;  // 开始新的PWM周期,从高电平开始}
}
详细解释
  1. 头文件和变量定义
    • #include "reg52.h":包含51单片机的头文件。
    • sbit sg90_con = P1^1;:定义舵机控制引脚,连接到P1.1。
    • int jiaodu;int cnt = 0;:用于控制舵机角度和计数器的变量。
  1. 延时函数
    • Delay2000ms()Delay300ms():这两个函数通过嵌套的空循环实现延时,用于产生约2000毫秒和300毫秒的延时。
  1. 定时器初始化函数
    • Time0Init():配置定时器0为16位计时模式,设置初始值,启动定时器,并开启定时器中断和全局中断。
  1. 主函数
    • main():主函数初始化定时器,并在一个无限循环中每隔2秒切换舵机的角度。jiaodu 设置为1表示0度,设置为3表示90度。
  1. 定时器中断处理函数
    • Time0Handler():定时器0溢出时调用此函数。每次溢出时计数器 cnt 增加,设置新的初始值,并根据 cntjiaodu 控制舵机信号引脚 sg90_con 的高低电平,从而产生PWM波。
工作原理
  • PWM信号生成
    • 中断处理函数通过计数器 cnt 控制 sg90_con 的高低电平时间,从而生成PWM信号。每个PWM周期为20ms,其中高电平时间由 jiaodu 控制。
  • 舵机控制
    • 主函数通过设置 jiaodu 控制舵机角度,每隔2秒改变一次角度。通过 Delay2000ms() 函数实现延时。
  • 中断处理
    • 每次定时器0溢出时,进入中断处理函数。计数器 cnt 增加,并根据 cnt 的值控制PWM波的高低电平。当 cnt 达到40次溢出时(相当于20ms),重置 cnt 并开始新的PWM周期。

主函数和中断一起执行 ,如果cnt 大于角度的时候,是低电压,中断函数cnt继续加加,直到加到等于40的时候,这个周期结束,进入下一个周期,

三、 超声波测距

3.1 简介

型号:HC-SR04

接线参考:模块除了两个电源引脚外,还有TRIG,ECHO引脚,这两个引脚分别接我们开发板的P1.5和

P1.6端口

超声波测距模块是用来测量距离的一种产品,通过发送和收超声波,利用时间差和声音传播速度, 计算出模块到前方障碍物的距离。

  • 怎么让它发送波

Trig ,给Trig端口至少10us的高电平

  • 怎么知道它开始发了

Echo信号,由低电平跳转到高电平,表示开始发送波

  • 怎么知道接收了返回波

Echo,由高电平跳转回低电平,表示波回来了

  • 怎么算时间

Echo引脚维持高电平的时间!

波发出去的那一下,开始启动定时器

波回来的拿一下,我们开始停止定时器,计算出中间经过多少时间

  • 怎么算距离

距离 = 速度 (340m/s)* 时间/2

3.2 超声波的时序图

3.3 超声波测距代码实现
#include "reg52.h"//距离小于10cm ,D5 亮,6灭,反之想反sbit D5 = P3^7;//根据原理图(电路图),设备变量led1指向P3组IO口的第7口
sbit D6 = P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6口sbit Trig = P1^5;   // 发送声波
sbit Echo = P1^6;   // 接收声波void Delay10us()		//@11.0592MHz  //声波的持续时间   10微妙  
{unsigned char i;i = 2;while (--i);
}
/*
十进制2左移1位,变成20。相当于乘以10
二禁止1左移1位,变成10(2)。相当于乘以2,左移8位,乘以2的8次方=256;*/
void startHC()   //Trig  输出10ms的高电平 启动发波
{Trig = 0;    //发声波 低电压 Trig = 1;    //发声波 高电压 维持10秒Delay10us();Trig = 0;  //发声波 低电压 }//设置定时器0工作模式1,初始值设定0开始数数,不着急启动定时器void Time0Init()   //不用关心初值  定时器
{TMOD &= 0xF0;		//设置定时器模式TMOD |= 0x01;		//设置定时器模式TH0 = 0;    //16进制计时TL0 = 0;// 设置定时器-0工作模块1.初值为0,不着急启动定时器、}
double get_distance()
{double time;//定时器数据清零,以便下一次测距TH1 = 0;TL1 = 0;startHC(); //调用超声波函数,启动发波;while(Echo == 0);   // 当接收端由低电压转换至高电压时,循环结束 表示声波发出//	启动定时器TR0 = 1;   // 开始计时//		3、Echo,由高电平跳转回低电平,表示波回来了 //	 停止计时while(Echo == 1);  // 当接收端由高电压转换至低电压时,循环结束,表示声波返回TR0 = 0;  // 停止计时//4. 计算出中间经过多少时间 (公式)time = (TH0 * 256 + TL0)*1.085;//us为单位//5. 距离 = 速度 (340m/s)* 时间/2dis = time * 0.017;double dis;  //返回一个数值
}
void openStatusLight()   // 开启状态灯
{D5 = 0;D6 = 1;
}
void closeStatusLight()  // 关闭状态灯
{D5 = 1;D6 = 0;
}
void main()
{double dis;   // 距离Time0Init();   //初始化定时器while(1){dis = get_distance();  // 计算距离// 判断距离是否小于10cmif(dis < 10){   // 如果小于10cm  openStatusLight();  // 调用开启函数}else{     // 否则。其他情况closeStatusLight();     // 调用关闭函数}}
}

四、本节项目感应开关盖垃圾桶

4.1 项目概述
  • 功能描述
      • 检测靠近时,垃圾桶自动开盖并伴随滴一声,2秒后关盖
      • 发生震动时,垃圾桶自动开盖并伴随滴一声,2秒后关盖
      • 按下按键时,垃圾桶自动开盖并伴随滴一声,2秒后关盖
  • 硬件说明
      • SG90舵机,超声波模块,震动传感器,蜂鸣器
  • 接线说明

舵机控制口 P1.1;超声波Trig接 P1.5 ,Echo接 P1.6 ;蜂鸣器接 P2.0 口; 震动传感器接 P3.2`口(外部 中断0)

4.2 编程实现
  • 开发步骤:

1. 舵机和超声波代码整合

    • 舵机用定时器0
    • 超声波用定时器1
    • 实现物体靠近后,自动开盖,2秒后关盖

2. 查询的方式添加按键控制

3. 查询的方式添加震动控制

4. 使用外部中断0配合震动控制

代码:

#include "reg52.h"sbit sg90_con = P1^1;
sbit D5 = P3^7;//根据原理图(电路图),设备变量led1指向P3组IO口的第7口
sbit D6 = P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6口sbit Trig = P1^5;
sbit Echo = P1^6;int jiaodu ;  // 舵机的角度
int cnt = 0;  //爆表的累计次数void Delay2000ms()		//@11.0592MHz  // 延迟2秒
{unsigned char i, j, k;i = 15;j = 2;k = 235;do{do{while (--k);} while (--j);} while (--i);
}void Delay10us()		//@11.0592MHz 
{unsigned char i;i = 2;while (--i);
}void startHC()   //Trig  输出10ms的高电平 启动发波
{Trig = 0;Trig = 1;Delay10us();Trig = 0;}
void Time0Init1()  // 初始化定时器0,用于舵机控制
{//1. 配置定时器0工作模式位16位计时TMOD &= 0xF0;		//设置定时器模式TMOD |= 0x01;//2. 给初值,定一个10ms出来TL0=0x33;TH0=0xFE;//3. 开始计时TR0 = 1;TF0 = 0;//4. 打开定时器0中断ET0 = 1;//5. 打开总中断EAEA = 1;
}void Time0Init2()   // 初始化定时器1,用于超声波控制
{TMOD &= 0x0F;		//设置定时器模式TMOD |= 0x10;		//设置定时器模式TH1 = 0;TL1 = 0;// 设置定时器-0工作模块1.初值为0,不着急启动定时器、}
void Delay300ms()		//@11.0592MHz
{unsigned char i, j, k;i = 3;j = 26;k = 223;do{do{while (--k);} while (--j);} while (--i);
}void initSG90_0()
{jiaodu = 1;      //初始角度是0度,0.5ms,溢出1就是0.5,高电平cnt = 0;sg90_con = 1;		//一开始从高电平开始
}
double  get_distance()
{double time;double dis;//定时器数据清零,以便下一次测距TH1 = 0;TL1 = 0;//1. Trig ,给Trig端口至少10us的高电平startHC();// 2、Echo信号,由低电平跳转到高电平,表示开始发送波//		波发出去的那一下,开始启动定时器while(Echo == 0);//	启动定时器TR1 = 1;//		3、Echo,由高电平跳转回低电平,表示波回来了 //	 停止计时while(Echo == 1);TR1 = 0;//4. 计算出中间经过多少时间time = (TH1 * 256 + TL1)*1.085;//us为单位//5. 距离 = 速度 (340m/s)* 时间/2dis = time * 0.017;return dis;
}
void openStatusLight() {D5 = 0;  // 点亮D5D6 = 1;  // 熄灭D6
}void closeStatusLight() {D5 = 1;  // 熄灭D5D6 = 0;  // 点亮D6
}void openlajitong() {jiaodu = 3;  // 90度,1.5ms高电平cnt = 0;Delay2000ms();
}void closelajitong() {jiaodu = 1;  // 0度,0.5ms高电平cnt = 0;Delay2000ms();
}
void main()
{double dis;Delay300ms(); 	//  让硬件稳定一下Time0Init1();  	//  初始化定时器1Time0Init2();	//  初始化定时器2initSG90_0();   //  初始化舵机的角度// 每隔两秒切换一次角度while(1){dis = get_distance();   // 计算距离if(dis < 10){        // 判断距离  //  如果距离小于10 调用开启函数openStatusLight();    //openlajitong();}else{                 //  如果距离大于10 调用关闭函数closeStatusLight();closelajitong();}}
}
void Time0Handler() interrupt 1  // 定时器中断
{cnt++;  //统计爆表的次数,cnt = 1的时候,报表了1//重新给初值TL0=0x33;TH0=0xFE;// 控制PWM波if(cnt < jiaodu){	sg90_con = 1 ;}else{sg90_con = 0 ;} if(cnt == 40){//爆表40次,经过了20mscnt = 0;  //当100次表示1s,重新让cnt从0开始,计算下一次的1ssg90_con = 1 ;}}
  • 测距开关盖添加按键开盖功能
    • 51单片机KY1 按键
    • 遥控发送接收433M
      • https://wenku.baidu.com/view/8fe8f444bed5b9f3f80f1c33.html
      • 默认低电平,按键之后是高电平。
      • 遥控控制开关
#include "reg52.h"// 定义各个IO口
sbit D5       = P3^7;      // LED D5连接到P3.7口
sbit D6       = P3^6;      // LED D6连接到P3.6口
sbit SW1      = P2^1;      // 开关 SW1连接到P2.1口
sbit Trig     = P1^5;      // 超声波传感器Trig引脚连接到P1.5口
sbit Echo     = P1^6;      // 超声波传感器Echo引脚连接到P1.6口
sbit sg90_con = P1^1;      // SG90舵机控制引脚连接到P1.1口
sbit D0_ON    = P1^2;      // LED D0_ON连接到P1.2口
sbit D1_OFF   = P1^3;      // LED D1_OFF连接到P1.3口int jiaodu ;  // 舵机的角度
int cnt = 0;  //爆表的累计次数void Delay2000ms()		//@11.0592MHz  // 延迟2秒
{unsigned char i, j, k;i = 15;j = 2;k = 235;do{do{while (--k);} while (--j);} while (--i);
}
void Delay10us()		//@11.0592MHz 
{unsigned char i;i = 2;while (--i);
}
void startHC()   //Trig  输出10ms的高电平 启动发波
{Trig = 0;Trig = 1;Delay10us();Trig = 0;}
void Time0Init1()  // 初始化定时器0,用于舵机控制
{//1. 配置定时器0工作模式位16位计时TMOD &= 0xF0;		//设置定时器模式TMOD |= 0x01;//2. 给初值,定一个10ms出来TL0=0x33;TH0=0xFE;//3. 开始计时TR0 = 1;TF0 = 0;//4. 打开定时器0中断ET0 = 1;//5. 打开总中断EAEA = 1;
}
void Time0Init2()   // 初始化定时器1,用于超声波控制
{TMOD &= 0x0F;		//设置定时器模式TMOD |= 0x10;		//设置定时器模式TH1 = 0;TL1 = 0;// 设置定时器-0工作模块1.初值为0,不着急启动定时器、}
void Delay300ms()		//@11.0592MHz
{unsigned char i, j, k;i = 3;j = 26;k = 223;do{do{while (--k);} while (--j);} while (--i);
}
void initSG90_0()
{jiaodu = 1;      //初始角度是0度,0.5ms,溢出1就是0.5,高电平cnt = 0;sg90_con = 1;		//一开始从高电平开始
}
double  get_distance()
{double time;double dis;//定时器数据清零,以便下一次测距TH1 = 0;TL1 = 0;//1. Trig ,给Trig端口至少10us的高电平startHC();// 2、Echo信号,由低电平跳转到高电平,表示开始发送波//		波发出去的那一下,开始启动定时器while(Echo == 0);//	启动定时器TR1 = 1;//		3、Echo,由高电平跳转回低电平,表示波回来了 //	 停止计时while(Echo == 1);TR1 = 0;//4. 计算出中间经过多少时间time = (TH1 * 256 + TL1)*1.085;//us为单位//5. 距离 = 速度 (340m/s)* 时间/2dis = time * 0.017;return dis;
}
void openStatusLight() {D5 = 0;  // 点亮D5D6 = 1;  // 熄灭D6
}
void closeStatusLight() {D5 = 1;  // 熄灭D5D6 = 0;  // 点亮D6
}
void openlajitong() {jiaodu = 3;  // 90度,1.5ms高电平cnt = 0;Delay2000ms();
}
void closelajitong() {jiaodu = 1;  // 0度,0.5ms高电平cnt = 0;Delay2000ms();
}
void main()
{double dis;Delay300ms(); 	//  让硬件稳定一下Time0Init1();  	//  初始化定时器1Time0Init2();	//  初始化定时器2initSG90_0();   //  初始化舵机的角度// 每隔两秒切换一次角度while(1){dis = get_distance();   // 计算距离if(dis < 10 || SW1 == 0 || D0_ON == 1){openStatusLight();openDusbin();}else if (D1_OFF == 1){//关盖,灯状态,D5灭closeStatusLight();closeDusbin();}else{closeStatusLight();closeDusbin();}}
}
void Time0Handler() interrupt 1  // 定时器中断
{cnt++;  //统计爆表的次数,cnt = 1的时候,报表了1//重新给初值TL0=0x33;TH0=0xFE;// 控制PWM波if(cnt < jiaodu){	sg90_con = 1 ;}else{sg90_con = 0 ;} if(cnt == 40){//爆表40次,经过了20mscnt = 0;  //当100次表示1s,重新让cnt从0开始,计算下一次的1ssg90_con = 1 ;}	
}
  • 测距开关盖添加振动传感器开盖功能
#include "reg52.h"// 定义各个IO口
sbit D5       = P3^7;      // LED D5连接到P3.7口
sbit D6       = P3^6;      // LED D6连接到P3.6口
sbit SW1      = P2^1;      // 开关 SW1连接到P2.1口
sbit Trig     = P1^5;      // 超声波传感器Trig引脚连接到P1.5口
sbit Echo     = P1^6;      // 超声波传感器Echo引脚连接到P1.6口
sbit sg90_con = P1^1;      // SG90舵机控制引脚连接到P1.1口
sbit D0_ON    = P1^2;      // LED D0_ON连接到P1.2口
sbit D1_OFF   = P1^3;      // LED D1_OFF连接到P1.3口
sbit vibrate  = P3^2;      // 振动传感器连接到P3.2口
sbit beep     = P2^0;char jiaodu;  // 舵机的角度变量
char jd_bak;
char cnt = 0;// 定时器溢出次数累计变量
char mark_vibrate = 0;// 延迟2秒
void Delay2000ms()		//@11.0592MHz
{unsigned char i, j, k;i = 15;j = 2;k = 235;do {do {while (--k);} while (--j);} while (--i);
}// 延迟10微秒
void Delay10us()		//@11.0592MHz 
{unsigned char i;i = 2;while (--i);
}// Trig输出10微秒的高电平以启动超声波传感器
void startHC()
{Trig = 0;Trig = 1;Delay10us();Trig = 0;
}// 初始化定时器0,用于舵机控制
void Time0Init1()
{TMOD &= 0xF0;		// 设置定时器模式TMOD |= 0x01;		// 配置定时器0工作模式为16位计数TL0 = 0x33;			// 定时器初值TH0 = 0xFE;			// 定时器初值TR0 = 1;			// 开始计时TF0 = 0;			// 清除定时器溢出标志ET0 = 1;			// 打开定时器0中断EA = 1;				// 打开总中断
}// 初始化定时器1,用于超声波控制
void Time0Init2()
{TMOD &= 0x0F;		// 设置定时器模式TMOD |= 0x10;		// 配置定时器1工作模式为16位计数TH1 = 0;			// 定时器1初值TL1 = 0;			// 定时器1初值
}// 延迟300毫秒
void Delay300ms()		//@11.0592MHz
{unsigned char i, j, k;i = 3;j = 26;k = 223;do {do {while (--k);} while (--j);} while (--i);
}// 初始化舵机角度为0度(0.5ms高电平)
void initSG90_0()
{jiaodu = 1;      // 初始角度是0度cnt = 0;sg90_con = 1;	 // 一开始从高电平开始
}// 获取距离
double get_distance()
{double time;double dis;TH1 = 0;  // 定时器1数据清零TL1 = 0;startHC();  // 启动超声波传感器while(Echo == 0);  // 等待Echo信号变高TR1 = 1;  // 启动定时器1while(Echo == 1);  // 等待Echo信号变低TR1 = 0;  // 停止定时器1time = (TH1 * 256 + TL1) * 1.085;  // 计算时间,单位为微秒dis = time * 0.017;  // 计算距离,单位为厘米return dis;
}// 打开状态灯
void openStatusLight() {D5 = 0;  // 点亮D5D6 = 1;  // 熄灭D6
}// 关闭状态灯
void closeStatusLight() {D5 = 1;  // 熄灭D5D6 = 0;  // 点亮D6
}// 打开垃圾桶
void openlajitong() {char n;jiaodu = 3; //90度 1.5ms高电平//舵机开盖if(jd_bak != jiaodu){cnt = 0;beep = 0;for(n=0;n<2;n++)Delay150ms();beep = 1;Delay2000ms();}jd_bak = jiaodu;}// 关闭垃圾桶
void closelajitong() {char n;//关盖for(n=0;n<2;n++)Delay150ms();jd = 1; //0度jd_bak = jd;cnt = 0;Delay150ms();
}
void EX0_Init()
{//打开外部中断EX0 = 1;//低电平触发IT0 = 0;
}
// 主函数
void main()
{double dis;Delay300ms(); 	// 让硬件稳定一下Time0Init1();  	// 初始化定时器0Time0Init2();	// 初始化定时器1EX0_Init();initSG90_0();   // 初始化舵机角度while(1) {dis = get_distance();  // 获取距离if(dis < 10 || SW1 == 0 || D0_ON == 1 ||  mark_vibrate == 1 ) {  // 距离小于10cm或SW1按下或D0_ON为高电平openStatusLight();openlajitong();} else if (D1_OFF == 1) {  // D1_OFF为高电平closeStatusLight();closelajitong();} else {  // 其他情况closeStatusLight();closelajitong();}}
}// 定时器中断处理函数
void Time0Handler() interrupt 1
{cnt++;  // 累计定时器溢出次数TL0 = 0x33;  // 重新设置定时器初值TH0 = 0xFE;if(cnt < jiaodu) {sg90_con = 1;  // 输出高电平} else {sg90_con = 0;  // 输出低电平}if(cnt == 40) {  // 溢出40次,经过20mscnt = 0;  // 重置计数sg90_con = 1;}}void Ex0_Handler() interrupt 0   //			振动传感器输出低电平 中断
{mark_vibrate = 1;          
}

相关文章:

51单片机—智能垃圾桶(定时器)

一. 定时器 1. 简介 C51中的定时器和计数器是同一个硬件电路支持的&#xff0c;通过寄存器配置不同&#xff0c;就可以将他当做定时器或者计数器使用。 确切的说&#xff0c;定时器和计数器区别是致使他们背后的计数存储器加1的信号不同。当配置为定时器使用时&#xff0c;每…...

熵权法模型(评价类问题)

一. 概念 利用信息熵计算各个指标的权重&#xff0c;从而为多指标的评价类问题提供依据。 指标的变异程度越小&#xff0c;所反映的信息量也越少&#xff0c;所以其对应的权值也应该越低。 指标的变异程度&#xff08;或称为变异性、波动性&#xff09;&#xff1a;描述了一…...

用uniapp 及socket.io做一个简单聊天app 踢人拉黑 7

在聊天群里&#xff0c;以及私聊时&#xff0c;可以点对方头象弹出踢跟拉黑&#xff0c;踢只是让对方退出聊天室。拉黑是记对方退出且不能再进入。 socket.io 中的踢人流程&#xff1a; 将用户从groupUsers 删除&#xff0c;表现在uniapp的界面&#xff0c;就是通知friends页&…...

springboot项目迁移到阿里云函数

注意&#xff1a;长耗时&#xff0c;高内存 的应用&#xff0c;定时任务 不适合迁移。spring-cloud的微服务项目暂不适合迁移。 一、根据模板创建项目 1.内网数据库连接配置 如果用到了rds或者阿里云上自建的mysql数据库 则配置 internetAccess: true vpcConfig:securityGrou…...

Java设计模式(桥接模式)

定义 将抽象部分与它的实现部分解耦&#xff0c;使得两者都能够独立变化。 角色 抽象类&#xff08;Abstraction&#xff09;&#xff1a;定义抽象类&#xff0c;并包含一个对实现化对象的引用。 扩充抽象类&#xff08;RefinedAbstraction&#xff09;&#xff1a;是抽象化角…...

【独家原创】基于APO-Transformer-LSTM多特征分类预测(多输入单输出)Matlab代码

【独家原创】基于APO-Transformer-LSTM多特征分类预测&#xff08;多输入单输出&#xff09;Matlab代码 目录 【独家原创】基于APO-Transformer-LSTM多特征分类预测&#xff08;多输入单输出&#xff09;Matlab代码分类效果基本描述程序设计参考资料 分类效果 基本描述 [24年最…...

【大模型】大模型指令微调的“Prompt”模板

文章目录 一、微调数据集格式二、常用的指令监督微调模板2.1 指令跟随格式&#xff08;Alpaca&#xff09;2.2 多轮对话格式&#xff08;ShareGPT&#xff09;2.3 其他形式2.4 常见模板 参考资料 一、微调数据集格式 在进行大模型微调的过程中&#xff0c;我们会发现“Prompt”…...

Spring的设计模式----工厂模式及对象代理

一、工厂模式 工厂模式提供了一种将对象的实例化过程封装在工厂类中的方式。通过使用工厂模式&#xff0c;可以将对象的创建与使用代码分离&#xff0c;提供一种统一的接口来创建不同类型的对象。定义一个创建对象的接口让其子类自己决定实例化哪一个工厂类&#xff0c;…...

【算法】浅析广度优先搜索算法

广度优先搜索算法&#xff1a;层层推进&#xff0c;全面探索 1. 引言 在计算机科学和算法设计中&#xff0c;广度优先搜索&#xff08;Breadth-First Search&#xff0c;简称BFS&#xff09;是一种用于遍历或搜索树或图的算法。这种算法从起点开始&#xff0c;优先访问所有距…...

分布式时序数据库TimeLyre 9.2发布:原生多模态、高性能计算、极速时序回放分析

在当今数据驱动的世界中&#xff0c;多模态数据已经成为企业的重要资产。随着数据规模和多样性的不断增加&#xff0c;企业不仅需要高效存储和处理这些数据&#xff0c;更需要从中提取有价值的洞察。工业领域在处理海量设备时序数据的同时&#xff0c;还需要联动分析警报信息、…...

PMP考试题库每日五题+答案解析

第1题&#xff08;单选题&#xff09;某技术开发项目正在开展&#xff0c;目前项目所用成本还在预算范围内&#xff0c;但是已经落后项目进度计划三周。项目集经理在最近的项目状态报告中了解到这一项目信息&#xff0c;他要求项目经理必须在计划的交付日期之前完成可交付成果。…...

机器学习用python还是R,哪个更好?

目录 1. 语言特点 1.1 Python的语言特点 1.2 R的语言特点 2. 库支持 2.1 Python的库支持 2.2 R的库支持 3. 性能 3.1 Python的性能 3.2 R的性能 4. 社区支持 4.1 Python的社区支持 4.2 R的社区支持 5. 学习曲线 5.1 Python的学习曲线 5.2 R的学习曲线 6. 实际应…...

【数据结构】mapset详解

&#x1f341;1. Set系列集合 Set接口是一种不包含重复元素的集合。它继承自Collection接口&#xff0c;所以可以使用Collection所拥有的方法&#xff0c;Set接口的实现类主要有HashSet、LinkedHashSet、TreeSet等&#xff0c;它们各自以不同的方式存储元素&#xff0c;但都遵…...

数据结构(邓俊辉)学习笔记】词典 02—— 散列函数

文章目录 1. 冲突难免2. 何为优劣3. 整除留余4. 以禅为师5. M A D6. 平方取中7. 折叠汇总8. 伪随机数9. 多项式10. Vorldmort 1. 冲突难免 好&#xff0c;接下来的这一节我们就来介绍散列策略中的第一项&#xff0c;也是最重要的技术&#xff0c;散列函数的设计与定制。 在上…...

Python学习(1):使用Python的Dask库实现并行计算

目录 一、Dask介绍 二、使用说明 安装 三、测试 1、单个文件中实现功能 2、运行多个可执行文件 最近在写并行计算相关部分&#xff0c;用到了python的Dask库。 Dask官网&#xff1a;Dask | Scale the Python tools you love 一、Dask介绍 Dask是一个灵活的并行和分布式…...

数据结构 - 哈希表

文章目录 前言一、哈希思想二、哈希表概念三、哈希函数1、哈希函数设计原则2、常用的哈希函数 四、哈希冲突1、什么是哈希冲突2、解决哈希冲突闭散列开散列 五、哈希表的性能分析时间复杂度分析空间复杂度分析 前言 一、哈希思想 哈希思想&#xff08;Hashing&#xff09;是计…...

电商选品这几点没做好,等于放弃80%的流量!

在竞争激烈的电商领域&#xff0c;选品是决定店铺命运的核心环节。到底是哪些关键要点能够帮助我们在选品时抢占流量高地&#xff0c;稳步出单呢&#xff1f; 一、深入了解市场需求 选品的第一步是对市场进行深入调研。要关注当前的消费趋势、热门品类以及潜在的需求缺口。通…...

【教程】最新可用!Docker国内镜像源列表

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 目录 镜像加速器地址 用法示例 一、自动配置地址 二、配置单次地址 镜像加速器地址 Docker镜像加速站https://hub.uuuadc.top/docker.1panel.live…...

使用RabbitMQ在Spring Boot入门实现简单的消息的发送与接收

文章目录 要引入spring-boot-starter-amqp依赖才能开始后续操作 1. 配置RabbitMQ地址2. 编写消息发送测试类3. 实现消息接收 在本文中&#xff0c;我们将介绍如何在Spring Boot应用中使用RabbitMQ实现消息的发送与接收。我们将创建两个服务&#xff0c;一个用于发送消息&#x…...

基于物联网的水质监测系统设计与实现:React前端、Node.js后端与TCP/IP协议的云平台集成(代码示例)

一、项目概述 随着环境保护意识的增强&#xff0c;水质监测在水资源管理和污染防治中变得尤为重要。本项目旨在设计一个基于物联网的水质监测系统&#xff0c;能够实时监测水中的pH值、溶解氧、电导率和浊度等参数&#xff0c;并将数据传输至云端&#xff0c;以便进行分析和可…...

组合模式:构建树形结构的艺术

引言:处理复杂对象结构的挑战 在软件开发中,我们常遇到需要处理部分-整体层次结构的场景: 文件系统中的文件与文件夹GUI中的容器与组件组织结构中的部门与员工菜单系统中的子菜单与菜单项组合模式正是为解决这类问题而生的设计模式。它允许我们将对象组合成树形结构来表示&…...

【VLAs篇】02:Impromptu VLA—用于驱动视觉-语言-动作模型的开放权重和开放数据

项目描述论文标题Impromptu VLA&#xff1a;用于驱动视觉-语言-动作模型的开放权重和开放数据 (Impromptu VLA: Open Weights and Open Data for Driving Vision-Language-Action Models)研究问题自动驾驶的视觉-语言-动作 (VLA) 模型在非结构化角落案例场景中表现不佳&#xf…...

Java在word中指定位置插入图片。

Java使用&#xff08;Poi-tl&#xff09; 在word&#xff08;docx&#xff09;中指定位置插入图片 Poi-tl 简介Maven 依赖配置Poi-tl 实现原理与步骤1. 模板标签规范2.完整实现代码3.效果展示 Poi-tl 简介 Poi-tl 是基于 Apache POI 的 Java 开源文档处理库&#xff0c;专注于…...

LeetCode - 53. 最大子数组和

目录 题目 Kadane 算法核心思想 Kadane 算法的步骤分析 读者可能的错误写法 正确的写法 题目 53. 最大子数组和 - 力扣&#xff08;LeetCode&#xff09; Kadane 算法核心思想 定义状态变量: currentSum: 表示以当前元素为结束的子数组的最大和。 maxSum: 记录全局最大…...

IDEA中微服务指定端口启动

在使用IDEA开发SpringBoot微服务时&#xff0c;经常需要开启多个服务实例以测试负载均衡&#xff0c;以下几种方法开启不同端口。 直接在配置文件中指定 # application.propertiesserver.port8001指定VM参数 点击Modify options&#xff0c;选择Add VM options&#xff0c;值…...

uniapp+<script setup lang=“ts“>解决有数据与暂无数据切换显示,有数据加载时暂无数据闪现(先加载空数据)问题

声明showEmpty 为false&#xff0c;在接口返回处判断有数据时设置showEmpty 为false&#xff0c;接口返回数据为空则判断showEmpty 为true &#xff08;这样就解决有数据的时候会闪现暂无数据的问题啦&#xff09; <!--* Date: 2024-02-26 03:38:52* LastEditTime: 2025-06…...

Redis知识体系

1. 概述 本文总结了Redis基本的核心知识体系&#xff0c;在学习Redis的过程中&#xff0c;可以将其作为学习框架&#xff0c;以此更好的从整体的角度去理解和学习Redis的内容和设计思想。同时知识框架带来的好处是可以帮助我们更好的进行记忆&#xff0c;在大脑中形成相应的知识…...

如何通过外网访问内网服务器?怎么让互联网上连接本地局域网的网址

服务器作为一个数据终端&#xff0c;是很多企事业单位不可获缺的重要设备&#xff0c;多数公司本地都会有部署服务器供测试或部署一些网络项目使用。有人说服务器就是计算机&#xff0c;其实这种说法不是很准确。准确的说服务器算是计算机的一种&#xff0c;它的作用是管理计算…...

JavaWeb:前端工程化-Vue

Vue工程化 介绍 什么是Vue? 小白眼里前端开发 前端工程化 环境准备 D:\Program Files\nodejs Vue项目-快速入门 步骤 D:\front\vue 安装依赖 目录结构 code . vscode打开 启动 VScode侧边栏左下角&#xff0c;没有NPM脚本&#xff0c;如何打开&#xff1f;&…...

php apache构建 Web 服务器

虚拟机配置流程winsever2016配置Apache、Mysql、php_windows server 2016配置web服务器-CSDN博客 PHP 和 Apache 通过 ​​模块化协作​​ 共同构建 Web 服务器&#xff0c;以下是它们的交互机制和工作流程&#xff1a; ​​一、核心组件分工​​ 组件角色​​Apache​​Web …...