51单片机-红外遥控器(NEC标准)-实验(红外遥控及调速电机)

作者:Whappy

时间:2024.9.20

总结一下!基础实验到这儿里就圆满结束,历经25天,将51单片机学完并亲自手敲代码近5000行,在手敲代码过程中,明显感觉的看和敲,明显就是不同的感觉,创作不易,在原有的代码上加上自己的想法并加以实现!接下向STM32发起进攻,开始学习!

介绍:

硬件电路

针对于上图两个PNP的三极管主要用来调制的,是因为自然界中有很多红外光,我们想要得到我们需要的的红外光,就要进行调制,通过一个38hz的频率进行调制,因为自然界的红外光不可能以38hz的频率跳动,后期通过滤波器将我们需要的波形提取来就可以了!

        还有红外接收头,OUT引脚接收的脉冲特别快,需要我们及时处理,所以,我们采取51单片机的外部中断来对这个脉冲进行处理!

发送和接收装置

通过上述解释:这个高电平和低电平不是我们平常说的一个周期内的高电平,而是一个周期中高低低电平所持续的时间,同样,低电平也是,看上图!

NEC编码

示波器采集的按键波形变化,还是地址码+地址反码+命令字+命令字反码

实物外观

可以看出要控制器所对应的键码值!

51单片机的外部中断

这个外部中断,也是我们常用的一种处理手段,外部中断也比较简单,只需要打开相关寄存器,配置一下外部中断服务函数即可!如下代码

void INT0_Init(void)  //打开外部中断相关的的寄存器(寄存器可单独配置)
{IT0 = 1;  //配置位低电平触发模式IE0 = 0;  //中断标志位EX0 = 1;    //外部中断0使能EA = 1;    //中断总使能PX0 = 1;    //中断最高优先级
}/*
//外部中断0 服务函数
void Int0_Routine()	interrupt 0
{Number++;
}
*///注:配置完成之后就可以在主函数中初始化了,在主函数下面加上我们的中断服务函数,即可触发中断

实验一:红外遥控实验(其余代码参考往期实验)

这个程序是使用红外遥控器控制数值的显示,并在LCD1602上输出。主要功能是通过红外接收数据,显示遥控器的地址码、命令码,并且根据接收到的命令对变量 Num 进行增减。

主要流程:

  1. LCD 初始化:

    • LCD_Init() 初始化 LCD1602 显示屏。
    • 在第一行显示 "ADDR CMD NUM" 作为标题。
    • 在第二行初始化显示地址码、命令码和变量 Num 的值。
  2. 红外接收初始化:

    • IR_Init() 初始化红外接收功能,准备接收遥控器信号。
  3. 循环处理红外信号:

    • IR_GetDataFlag()IR_GetRepeatFlag() 判断是否接收到数据帧或连发帧。
    • 如果接收到信号:
      • 调用 IR_GetAddress() 获取遥控器地址码并显示在LCD上。
      • 调用 IR_GetCommand() 获取遥控器命令码并显示在LCD上。
  4. 处理命令:

    • 如果接收到的命令码是 IR_VOL_MINUS(对应遥控器的音量减键),变量 Num 自减。
    • 如果接收到的命令码是 IR_VOL_ADD(对应遥控器的音量加键),变量 Num 自增。
  5. 显示数值:

    • 更新LCD,显示变量 Num 的值。

通过遥控器上的音量加减键,用户可以控制数值 Num 的增减,并实时在LCD上看到变化。

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}}
}

Timer0.c

#include <REGX52.H>// 定时器0初始化函数,设置定时器0为模式1(16位定时器模式),每1毫秒计时一次,工作在11.0592MHz晶振下
void Timer0_Init()		
{TMOD &= 0xF0;        // 清除定时器0的模式位(低4位),保留高4位(定时器1的设置)TMOD |= 0x01;        // 设置定时器0为模式1(16位定时器)TL0 = 0;             // 设置定时器0低8位初值为0TH0 = 0;             // 设置定时器0高8位初值为0TF0 = 0;             // 清除定时器0的溢出标志位(TF0)TR0 = 0;             // 关闭定时器0的计时
}// 设置定时器0计数器值
void Timer0_SetCounter(unsigned int Value)
{TH0 = Value / 256;   // 将高8位写入TH0寄存器TL0 = Value % 256;   // 将低8位写入TL0寄存器
}// 获取定时器0当前的计数值
unsigned int Timer0_GetCounter(void)
{return (TH0 << 8) | TL0;  // 将TH0和TL0的值组合成16位数并返回
}// 启动或停止定时器0的计时功能
// 参数:Flag为1时启动定时器,Flag为0时停止定时器
void Timer0_Run(unsigned char Flag)
{TR0 = Flag;  // 根据Flag设置TR0位,1表示启动定时器0,0表示停止定时器0
}

注释说明:

  • Timer0_Init():初始化定时器0为模式1(16位定时器模式),并设置初值。此模式下,定时器从TH0|TL0组合的16位计数器开始计数,直到溢出。
  • Timer0_SetCounter():根据传入的Value值,设置定时器的当前计数值。
  • Timer0_GetCounter():获取当前定时器的计数值(16位数),将高8位和低8位组合返回。
  • Timer0_Run():启动或停止定时器的计时功能,通过Flag参数来控制。

INT0.c

#include <REGX52.H>// 外部中断0初始化函数
void INT0_Init(void)
{IT0 = 1;  // 设置外部中断0为下降沿触发模式(1为下降沿触发,0为低电平触发)IE0 = 0;  // 清除外部中断0的中断标志位EX0 = 1;  // 使能外部中断0EA = 1;   // 全局中断使能PX0 = 1;  // 设置外部中断0为高优先级(1为高优先级,0为低优先级)
}/*
// 外部中断0的中断服务函数
void Int0_Routine() interrupt 0
{Number++;  // 每次触发外部中断0时,将变量 Number 自增
}
  • INT0_Init():初始化外部中断0,将其配置为下降沿触发,并使能相关中断。通过设置中断优先级位来设置其为高优先级中断。
    • IT0 = 1:配置外部中断0为下降沿触发。
    • IE0 = 0:清除中断标志位,确保没有待处理的中断。
    • EX0 = 1:使能外部中断0。
    • EA = 1:开启全局中断,使单片机响应中断。
    • PX0 = 1:设置外部中断0为高优先级。
  • Int0_Routine():这是外部中断0的中断服务函数,执行中断时该函数会被调用。在该例子中,每次外部中断触发时,变量 Number 会自增。

注:中断服务函数 Int0_Routine() 被注释掉,可以根据需要进行启用。

IR.c  (核心代码:主要处理红外遥控接收和发送数据)

#include <REGX52.H>
#include "Timer0.h"
#include "INT0.h"unsigned int IR_Time;              // 用于记录红外信号的时间间隔
unsigned char IR_State;            // 用于记录红外接收状态机的状态
unsigned char IR_Data[4];          // 用于存储接收到的红外数据信息
unsigned char IR_pData;            // 用于记录当前接收数据的位索引unsigned char IR_DataFlag;         // 用于标记是否接收到数据帧
unsigned char IR_RepeatFlag;       // 用于标记是否接收到连发信号
unsigned char IR_Address;          // 存储接收到的红外遥控器地址
unsigned char IR_Command;          // 存储接收到的红外遥控器命令// 红外遥控初始化函数
void IR_Init(void) 
{INT0_Init();           // 初始化外部中断0,用于捕获红外接收信号的下降沿Timer0_Init();         // 初始化定时器0,用于计时
}// 获取数据帧标志位的函数
unsigned char IR_GetDataFlag(void)  
{if(IR_DataFlag)        // 如果收到数据帧标志置位{IR_DataFlag = 0;   // 清除数据帧标志return 1;          // 返回1表示已接收到数据帧}return 0;              // 否则返回0
}// 获取连发信号标志位的函数
unsigned char IR_GetRepeatFlag(void) 
{if(IR_RepeatFlag)      // 如果收到连发信号标志置位{IR_RepeatFlag = 0; // 清除连发信号标志return 1;          // 返回1表示已接收到连发信号}return 0;              // 否则返回0
}// 获取接收到的红外遥控地址
unsigned char IR_GetAddress(void)  
{return IR_Address;
}// 获取接收到的红外遥控命令
unsigned char IR_GetCommand(void) 
{return IR_Command;
}// 外部中断0服务函数,处理红外接收的信号
void Int0_Routine() interrupt 0
{// 状态0:空闲状态,检测到信号开始,重置计时器if(IR_State == 0)  {Timer0_SetCounter(0);    // 将定时器计数器清零Timer0_Run(1);           // 启动定时器IR_State = 1;            // 设置状态为1,等待信号}// 状态1:等待Start信号或Repeat信号else if(IR_State == 1)  {IR_Time = Timer0_GetCounter(); // 获取上次中断到此次中断的时间Timer0_SetCounter(0);          // 计时器清零准备下一次测量// 检测到Start信号if(IR_Time > (12442-500) && IR_Time < (12442+500)){IR_State = 2;        // 转换到状态2,准备接收数据}// 检测到Repeat信号else if(IR_Time > (10368-500) && IR_Time < (10368+500)){IR_RepeatFlag = 1;   // 置连发信号标志Timer0_Run(0);       // 停止定时器IR_State = 0;        // 返回空闲状态}else{IR_State = 1;        // 未收到有效信号,保持状态1}}// 状态2:接收数据else if(IR_State == 2)  {IR_Time = Timer0_GetCounter();  // 获取时间间隔Timer0_SetCounter(0);           // 计时器清零// 判断是逻辑0还是逻辑1if(IR_Time > (1032-500) && IR_Time < (1032+500)){IR_Data[IR_pData/8] &= ~(0x01 << (IR_pData % 8)); // 写入逻辑0IR_pData++;         // 数据位索引加1}else if(IR_Time > (2074-500) && IR_Time < (2074+500)){IR_Data[IR_pData/8] |= (0x01 << (IR_pData % 8));  // 写入逻辑1IR_pData++;         // 数据位索引加1}else{IR_pData = 0;       // 出现错误,数据位清零,返回状态1IR_State = 1;}// 如果接收到完整的32位数据if(IR_pData >= 32){IR_pData = 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;             // 置数据帧标志位}Timer0_Run(0);  // 停止定时器IR_State = 0;   // 返回空闲状态}}
}

代码思路

  1. 初始化部分

    • 调用 IR_Init() 函数来初始化外部中断0和定时器0,确保红外接收能够计时和响应信号的变化。

  2. 状态机控制

    • 通过 IR_State 进行状态管理。程序根据中断触发的时间判断信号类型(启动信号、连发信号或数据)。

    • 根据不同状态,程序分别执行启动计时、判断信号类型、接收并解码红外数据的操作。

  3. 数据接收和处理

    • 红外信号的编码通过时间间隔来区分逻辑0和逻辑1。程序根据红外信号的时间长短判断数据位,最终解码成地址和命令。

    • 采用位操作将红外信号按位存入 IR_Data 数组,并在接收到完整32位数据后校验数据的有效性(利用地址和命令码的互补关系)。

  4. 标志位与状态管理

    • 使用 IR_DataFlagIR_RepeatFlag 来标记是否接收到完整数据帧或连发信号。

    • 外部模块可以通过 IR_GetDataFlag() 等函数获取这些标志位,并作出相应的处理。

函数调用关系

  • IR_Init() 初始化中断和定时器。

  • Int0_Routine() 是外部中断服务函数,负责处理红外信号,状态机在这个函数中运行。

  • IR_GetDataFlag()IR_GetRepeatFlag() 函数提供了对外的接口,用于其他模块判断红外遥控信号状态。

  • IR_GetAddress()IR_GetCommand() 函数用于获取解码后的红外遥控地址和命令。

目的和好处

  • 状态机的设计:通过 IR_State 实现多阶段处理红外信号(如空闲、判断信号、数据接收),结构清晰,便于调试与扩展。

  • 标志位管理:通过 IR_DataFlagIR_RepeatFlag 等标志位,模块化地提供状态信息,便于其他模块获取数据而不直接干扰中断逻辑。

  • 位操作与定时器结合:通过定时器捕获时间差,结合位操作解码数据,使得红外信号的处理精确而高效。

思想方法

  • 模块化设计:将不同功能(如定时器、外部中断、信号解码)分离为不同的函数,方便维护和扩展。

  • 状态机模型:通过有限状态机的方式处理信号,能够清晰管理不同阶段的任务,避免逻辑混乱。

  • 时间敏感的处理:通过定时器精确测量时间,结合中断机制,高效地接收和处理红外信号。

实验二:红外遥控控制电机调速实验(其余代码往期实验)

目的是通过红外遥控器来控制电机的转速,并通过数码管显示当前速度值。具体功能如下:

  1. 红外遥控输入

    • 程序接收红外遥控器的命令码,根据不同的按键(如 IR_0, IR_1, IR_2, IR_3)来设置不同的电机速度。

  2. 电机速度控制

    • 程序根据遥控器的命令,通过 Motor_SetSpeed() 函数来调整电机的实际转速。设定的速度分为4个级别:停止、50%、75%、100%。

  3. 数码管显示

    • 使用数码管 Nixie() 来显示当前的速度状态,将当前的速度级别(0、1、2、3)显示在数码管上。

总体思想

  1. 模块化设计

    • 程序分为几个独立模块,如 Motor_Init() 初始化电机,IR_Init() 初始化红外接收,Motor_SetSpeed() 设置电机转速,Nixie() 用于显示当前速度值。这样的设计便于调试和扩展。

  2. 红外控制

    • 利用红外接收模块,通过接收遥控器发送的命令码,改变电机的速度。程序通过不断检查是否有数据帧到来,一旦收到有效数据,就解析命令码并做出响应。

  3. 状态机思想

    • 代码使用简单的状态判断(速度级别为0到3),根据不同的命令调整电机的运行状态,并通过显示屏实时反馈当前状态。这种逻辑使得代码结构清晰,处理不同输入时能够快速响应。

  4. 解耦合和灵活性

    • 将电机控制和遥控器输入解耦合,遥控器只需发出简单的命令,电机部分负责实现速度控制。通过简单扩展,系统可以支持更多的命令和功能,例如控制电机的方向或其他附加功能。

这样做的好处

  • 可扩展性:功能可以方便地扩展,比如增加更多速度级别或其他控制命令,代码结构简单易懂,模块化设计便于维护。

  • 用户友好:通过遥控器方便地控制电机运行,数码管实时显示当前状态,用户能直观地知道电机运行情况。

  • 高效运行:通过红外信号触发的状态机结构,使得程序在低资源消耗下响应快速。

main.c

void main()
{Motor_Init();        // 电机初始化IR_Init();           // 红外遥控初始化while(1)             // 主循环{if(IR_GetDataFlag())  // 如果接收到红外遥控的有效数据帧{Command = IR_GetCommand();  // 获取遥控器发来的命令码// 根据不同的遥控命令码设置速度值if(Command == IR_0) { Speed = 0; }   // 命令码为 0,速度设为 0if(Command == IR_1) { Speed = 1; }   // 命令码为 1,速度设为 1if(Command == IR_2) { Speed = 2; }   // 命令码为 2,速度设为 2if(Command == IR_3) { Speed = 3; }   // 命令码为 3,速度设为 3// 根据速度值调整电机的实际转速if(Speed == 0) { Motor_SetSpeed(0); }    // 速度0,电机停止if(Speed == 1) { Motor_SetSpeed(50); }   // 速度1,电机以50%的功率运行if(Speed == 2) { Motor_SetSpeed(75); }   // 速度2,电机以75%的功率运行if(Speed == 3) { Motor_SetSpeed(100); }  // 速度3,电机以100%的功率运行}Nixie(1, Speed);  // 数码管显示当前速度值}
}

IR.c(同上)

INT0.c(同上)

Timer0.c(同上)
Timer1.c

#include <REGX52.H>// 定时器1初始化函数,用于配置定时器1,产生一个100微秒的定时中断。
/**
* @brief 定时器初始化(51单片机软件内置配置的定时器)
* @param 无
* @retval 无
*/
void Timer1_Init()		//100微秒@11.0592MHz
{TMOD &= 0x0F;		// 清除定时器1的模式位,保持定时器0的模式不变TMOD |= 0x10;		// 设置定时器1为模式1,即16位定时模式TL0 = 0xA4;		    // 设置定时器1的低位初值为0xA4TH0 = 0xFF;		    // 设置定时器1的高位初值为0xFFTF0 = 0;		    // 清除定时器1的溢出标志位TR0 = 1;		    // 启动定时器1// 启用定时器中断ET0  = 1;  // 打开定时器1中断EA = 1;    // 打开总中断PT0 = 0;   // 设置定时器1中断优先级为低优先级
}/* 定时器中断函数模板 */
/*
void Timer0_Rountine(void)  interrupt 3
{static unsigned int T0Count;  // 用于记录定时器0的计数TL0 = 0x66;		// 设置定时初值TH0 = 0xFC;		// 设置定时初值T0Count++;      // 每次中断发生时自增1if(T0Count >= 1000)  // 1000次中断(即1秒)后执行翻转P2_0口{T0Count = 0;P2_0 = ~P2_0;  // 反转P2_0引脚的输出电平,达到控制外部设备的效果}	
}
*/

Motor.c

#include <REGX52.H>
#include "Timer1.h"sbit Motor = P1^0;  // 将 P1 口的第0位定义为 Motor 引脚,用于控制电机的开关unsigned char Counter, Compare;  // Counter 用于计时,Compare 用于占空比比较/*** @brief 电机初始化函数,初始化定时器1* @param 无* @retval 无*/
void Motor_Init()
{Timer1_Init();  // 调用定时器1初始化函数,开始计时
}/*** @brief 设置电机转速* @param Speed 速度参数,范围为0-100,用于调节电机的占空比* @retval 无*/
void Motor_SetSpeed(unsigned char Speed)
{Compare = Speed;  // 将传入的速度值赋给 Compare,作为占空比参考值
}/*** @brief 定时器1中断服务函数*        使用定时器实现 PWM 调速功能* @param 无* @retval 无*/
void Timer1_Rountine(void) interrupt 3  // 定时器1中断函数
{TL0 = 0xA4;  // 设置定时器初值,确保每次中断后保持相同的定时时间TH0 = 0xFF;  // 设置定时器高位初值Counter++;         // 每次中断时,计时器 Counter 自增1Counter %= 100;    // 将 Counter 限制在 0 到 99 的范围内,形成 100 个周期(模拟 PWM 占空比)// 比较 Counter 和 Compare 的值,用于控制占空比if(Counter < Compare){Motor = 1;  // 如果 Counter 小于 Compare,电机引脚输出高电平,电机通电工作}else{Motor = 0;  // 如果 Counter 大于或等于 Compare,电机引脚输出低电平,电机停止工作}
}

代码说明

  1. Motor_Init():

    • 初始化电机控制模块,内部调用了 Timer1_Init() 函数,启动定时器1以实现电机的速度控制。

  2. Motor_SetSpeed():

    • 该函数用于设置电机的转速。传入的 Speed 参数(范围0-100)表示电机速度的占空比,控制电机开启的时间占整个周期的比例。

  3. Timer1_Rountine():

    • 定时器1的中断服务函数,用于实现电机的PWM(脉宽调制)控制。

    • 定时器每触发一次中断,Counter 自增并与设定的占空比 Compare 进行比较:

      • 如果 Counter 小于 Compare,电机引脚输出高电平(电机运行)。

      • 如果 Counter 大于或等于 Compare,电机引脚输出低电平(电机停止)。

    • 通过这种方式,程序控制了电机开启与关闭的比例,从而调整电机的转速。

总体思想

通过定时器中断实现 PWM 控制,以调节电机的工作状态。Counter 循环自增形成一个周期,并根据占空比 Compare 控制电机的开关,从而实现电机的转速控制。

最后总结

通过C语言编程控制51单片机的几种常见功能,包括红外遥控解码电机转速控制定时器中断外部中断等。这些功能的核心思想是利用单片机的定时器、中断机制和外设来实现对外部设备的控制和数据采集。以下是关键点的总结:

  1. 红外遥控解码

    • 通过外部中断 INT0 捕获红外信号的下降沿,用定时器测量信号脉冲宽度,从而解码出遥控器的地址和命令。

    • 利用状态机进行红外信号的解析,包括起始信号数据位解码重复信号处理。

    • 解码后的命令可以用于控制电机或其他设备的操作。

  2. 定时器的使用

    • 定时器用于生成精准的时间延迟、控制设备(如电机)、或周期性执行任务。

    • 在定时器中断服务函数中,计时器 Counter 和占空比 Compare 的比较决定了电机的开关状态,从而实现 PWM 调速。

  3. PWM 控制电机

    • 通过定时器中断产生的PWM信号控制电机的转速。利用占空比来控制电机工作时间的比例,从而调整电机的转速。

    • 电机控制分为初始化、设置速度和根据设定的速度输出对应的PWM信号,形成灵活的调速机制。

  4. 外部中断

    • 外部中断用于响应外部事件,例如红外遥控信号的输入。中断服务函数快速响应并执行特定任务,确保即使主程序忙碌也能处理紧急事件。

  5. 思想方法

    • 模块化设计:通过封装函数实现功能模块的独立性,如红外解码、定时器配置、电机控制等。这种设计思路使代码具有良好的扩展性和维护性。

    • 状态机:红外解码使用状态机方法,根据接收信号的不同状态(如空闲、等待、解码等)做出相应的处理,确保程序运行稳定。

    • 中断优先机制:中断机制保证了单片机可以及时响应重要事件,如定时器溢出或外部信号输入,而不会影响主程序的执行。

优点和好处:

  • 实时性强:中断机制保证了高优先级任务(如定时和外部输入)的及时响应,不会因为主程序的延迟而错失事件。

  • 精确控制:利用定时器实现精准的时间控制,结合PWM调制实现了对电机速度的精确调节。

  • 模块化和可扩展性:各个功能模块相互独立,便于后期扩展新功能或修改现有功能。

通过这些机制和设计,代码能够高效地管理外部设备和信号输入,实现自动化控制和调节功能。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

STM32 通过 SPI 驱动 W25Q128

目录 一、STM32 SPI 框图1、通讯引脚2、时钟控制3、数据控制逻辑4、整体控制逻辑5、主模式收发流程及事件说明如下&#xff1a; 二、程序编写1、SPI 初始化2、W25Q128 驱动代码2.1 读写厂商 ID 和设备 ID2.2 读数据2.3 写使能/写禁止2.4 读/写状态寄存器2.5 擦除扇区2.6 擦除整…

基于SpringBoot的在线点餐系统【附源码】

​基于SpringBoot的高校社团管理系统&#xff08;源码L文说明文档&#xff09; 4 系统设计 4.1 系统概述 网上点餐系统的结构图4-1所示&#xff1a; 图4-1 系统结构 模块包括主界面&#xff0c;首页、个人中心、用户管理、美食店管理、美食分类管理、美食…

前端开发者必学:mo.js动画库

前端开发者必学&#xff1a;mo.js动画库 前言 在当今的网页设计中&#xff0c;动态效果和交互性是提升用户体验的关键因素。 mo.js&#xff0c;一个轻量级的 JavaScript 动画库&#xff0c;为前端开发者提供了一种简单而强大的方法来创建引人注目的动画效果。 本文将向您介…

Nature|PathChat:病理学多模态生成性AI助手的创新与应用|顶刊精析·24-09-21

小罗碎碎念 今日顶刊&#xff1a;Nature 这篇文章今年6月就发表了&#xff0c;当时我分析的时候&#xff0c;还是预印本&#xff0c;没有排版。今天第一篇推文介绍的是Faisal Mahmood &#xff0c;所以又把这篇文章拉出来详细分析一下。 作者角色作者姓名单位名称单位英文名称第…

目标拟合椭圆

对于目标区域&#xff0c;the ellipse fit is computing by matching second-order moments.

【C/C++】速通涉及string类的经典编程题

【C/C】速通涉及string类的经典编程题 一.字符串最后一个单词的长度代码实现&#xff1a;&#xff08;含注释&#xff09; 二.验证回文串解法一&#xff1a;代码实现&#xff1a;&#xff08;含注释&#xff09; 解法二&#xff1a;&#xff08;推荐&#xff09;1. 函数isalnum…

Linux文件IO(六)-多次打开同一个文件

大家看到这个小节标题可能会有疑问&#xff0c;同一个文件还能被多次打开&#xff1f;事实确实如此&#xff0c;同一个文件可以被多次打开&#xff0c;譬如在一个进程中多次打开同一个文件、在多个不同的进程中打开同一个文件&#xff0c;那么这些操作都是被允许的。本小节就来…

Linux软件包管理器、Linux开发工具、vim的配置等的介绍

文章目录 前言一、Linux软件包管理器yum二、Linux开发工具1. 命令模式2. 插入模式3. 底行模式4. 三种模式的切换5. 命令模式下的快捷键 三、vim的配置总结 前言 Linux软件包管理器、Linux开发工具、vim的配置等的介绍 一、Linux软件包管理器yum 关于rzsz 这个工具用于 window…

动手学深度学习(李沐)PyTorch 第 2 章 预备知识

2.1 数据操作 N维数组样例 N维数组是机器学习和神经网络的主要数据结构 张量表示一个由数值组成的数组&#xff0c;这个数组可能有多个维度。 具有一个轴的张量对应数学上的向量&#xff08;vector&#xff09;&#xff1b; 具有两个轴的张量对应数学上的矩阵&#xff08;…

MySQL高阶1843-可疑银行账户

目录 题目 准备数据 ​分析数据 实现 总结 题目 如果一个账户在 连续两个及以上 月份的 总收入 超过最大收入&#xff08;max_income&#xff09;&#xff0c;那么认为这个账户 可疑。 账户当月 总收入 是当月存入资金总数&#xff08;即 transactions 表中 type 字段的…

【Unity-UGUI组件拓展】| Image 组件拓展,支持FIlled和Slice功能并存

🎬【Unity-UGUI组件拓展】| Image 组件拓展,支持FIlled和Slice功能并存一、组件介绍二、组件拓展方法三、完整代码💯总结🎬 博客主页:https://xiaoy.blog.csdn.net 🎥 本文由 呆呆敲代码的小Y 原创,首发于 CSDN🙉 🎄 学习专栏推荐:Unity系统学习专栏 🌲 游戏…

C / C++的内存管理

前言 Hello&#xff0c;我又回来了&#xff0c;今天我们将继续学习C部分&#xff0c;今天我们将承接前面的知识&#xff0c;继续学习C的内存管理&#xff0c;今天的内容较为重要&#xff0c;所以我们废话不多说&#xff0c;我们还是按例三连上车&#xff0c;开始我们今天内容&…

Python中lambda表达式的使用——完整通透版

文章目录 一、前言二、 基本语法三、举个简单的例子&#xff1a;四、常见应用场景1. 用于排序函数sort() 方法简介lambda 表达式的作用详细解释进一步扩展总结 2、与 map、filter、reduce 等函数结合1、 map() 函数示例&#xff1a;将列表中的每个数字平方 2、 filter() 函数示…

Typora安装和导入导出

Typora安装和导入导出 文章目录 Typora安装和导入导出前言Typora v1.9.5Typora v1.4.7Pandoc 前言 Typora v1.9是最新版, , Typora v1.4是老版本的, 这两个选择一个即可Pandoc可以导入导出word Typora v1.9.5 Typora v1.9.rar, 提取码&#xff1a;tian按ctrl单击鼠标左键打开…

数据飞轮崛起:数据中台真的过时了吗?

一、数据中台的兴起与困境 随着大数据技术的不断发展&#xff0c;我见证了企业数据能力建设的演变。从数据中台的兴起&#xff0c;到如今数据飞轮模式的热议&#xff0c;企业的数据管理理念经历了巨大的变化。起初&#xff0c;数据中台作为解决数据孤岛、打破部门壁垒的“救星…

新版torch_geometric不存在uniform、maybe_num_nodes函数问题(Prune4ED论文报错解决)

这是在复现论文”“时遇到的报错。 ImportError: cannot import name uniform from torch_geometric.nn.pool.topk_pool 一、报错原因 论文作者使用的是2.1.0版本的torch_geometric。而我安装了2.6.1的torch_geometric。新版中已经去除了uniform和maybe_num_nodes这两个函数&…

力扣 中等 162.寻找峰值

文章目录 题目介绍解法 题目介绍 解法 定理&#xff1a;如果 i<n−1 且 nums[i]<nums[i1]&#xff0c;那么在下标 [i1,n−1] 中一定存在至少一个峰值。证明 思路分析&#xff1a;利用采用红蓝染色题体法&#xff0c;n为数组的长度&#xff0c;开始左指针L指向数组最左边…

CompletableFuture-详解使用及源码解析

背景 上一篇文章我们看了FutureTask&#xff0c;分析了他的问题&#xff0c;异步编程并不方便。 问题1&#xff1a; FutureTask获取执行结果前&#xff0c;主线程需要通过get()方法一直阻塞等待子线程执行完成call方法&#xff0c;才可以拿到返回结果问题2&#xff1a;如果不…

linux固定串口别名

最近项目功能要求&#xff0c;需要将插入设备的串口设备占用的端口号固定住&#xff0c;这里记录一下设置过程方便以后查阅。 linux固定串口别名 配置过程相关补充 配置过程 列出当前插入USB端口的设备&#xff1a; lsusb查看当前设备的端口号&#xff1a; ls dev/查看当前设…

【24华为杯数模研赛赛题思路已出】国赛D题思路丨附参考代码丨免费分享

2024年华为杯研赛C题解题思路 D 题 大数据驱动的地理综合问题 地理系统是自然、人文多要素综合作用的复杂巨系统[1-2]&#xff0c;地理学家常用地理综合的方式对地理系统进行主导特征的表达[3]。如以三大阶梯概括中国的地形特征&#xff0c;以秦岭—淮河一线和其它地理区划的…