【STM32】【HAL库】遥控关灯1主机

news2024/11/16 22:40:29

相关连接

【STM32】【HAL库】遥控关灯0 概述

【STM32】【HAL库】遥控关灯1主机

【STM32】【HAL库】遥控关灯2 分机

【STM32】【HAL库】遥控关灯3 遥控器

需求

主机需要以下功能:

  • 接收来自物联网平台的命令
  • 发送RF433信号给从机
  • 接收RF433信号和红外信号
  • 驱动舵机动作

方案设计

使用双MCU方案,ESP32C3负责物联网相关通信,STM32负责发送信号给从机和接收RF433的信号,还有舵机控制

本单使用ESP32即可,但手头的RF433的遥控器的协议不是常见的,没找到相关的解码库

而ESP32本人不算熟悉,经过测试没法成功解码,因此使用双MCU方案,后续可能会改进

ESP32与STM32直接使用串口通信

使用巴法云平台作为物联网平台,使用MQTT协议连接

硬件设计

433接收

使用XL700芯片(淘宝)(单价0.52)

电路是数据手册的参考电路,天线使用弹簧天线

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YYm9ZLzX-1676130327907)(picture/1.png)]

433发射

使用XL4456(淘宝)(单价0.47)

电路是数据手册的参考电路,天线使用弹簧天线

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F40M8GrJ-1676130327908)(picture/2.png)]

esp32

使用ESP32C3(单价10)(也可以使用esp8266模块,但手头无货,故使用这个芯片)

烧录时同时按下两个按键,先松开EN按键 2s以上后在松开Io9按键

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z0vMwBYL-1676130327910)(picture/3.png)]

stm32

最小系统设计

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1lQqcCy7-1676130327912)(picture/4.png)]

电源

使用5v电源适配器

只需要在这里转3,3v即可

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iWvjBAGo-1676130327912)(picture/5.png)]

其余接口

包括控制舵机的接口和红外接口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ePYwmzg1-1676130327913)(picture/6.png)]

软件设计

协议

功能esp32串口输出代码物联网平台代码stm32动作
主屋开0xac0000H_ON操作舵机开灯
主屋关0xac00ffH_OFF操作舵机关灯
北屋开0xac1100N_ON将串口代码通过RF433发射
北屋关0xac11ffN_OFF将串口代码通过RF433发射
南屋开0xac2200S_ON将串口代码通过RF433发射
南屋关0xac22ffS_OFF将串口代码通过RF433发射
西屋开0xac3300W_ON将串口代码通过RF433发射
西屋关0xac33ffW_OFF将串口代码通过RF433发射
全开0xacff00ALL_ON分别发送各屋开灯代码
全关0xacffffALL_OFF分别发送各屋关灯代码

esp32

环境

这里使用Arduino框架

请自行查询arduino的环境搭建

这里使用了一个第三方库(PubSubClient)来建立MQTT连接

这里提供zip文件(成品的github连接中),自行导入即可

如下图选择添加zip库,添加即可

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1oUTd77Z-1676130327914)(picture/7.png)]

wifi连接

将esp32设置为sta模式,接入其他wifi

根据wifi的ssid和password接入

如下所示

const char *ssid = "";
const char *password = "";
void setupWifi() {
  WiFi.mode(WIFI_STA);
  esp_wifi_set_mac(WIFI_IF_STA, newMACAddress);
  Serial.println(WiFi.macAddress());

  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

MQTT

云平台设置

使用的是巴法云的mqtt服务

巴法云设置,传送门

一般的MQTT有这么几个要素

设备id(mqtt_devid),产品id(mqtt_pubid),密钥信息(mqtt_password),主题名(mqtt_topic)

在巴法云中只用了设备ID和主题名(产品ID和密钥为空即可)

#define mqtt_devid "********"  //设备ID
#define mqtt_pubid "  "                                //产品ID
#define mqtt_password " "                              //鉴权信息
const char *mqtt_topic = "ESP32HomeRFLight2";


设备ID是巴法云控制台中的这个红圈里的私钥

主题则是自己建立的主题名

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BxBbVn7e-1676130327915)(picture/8.png)]

程序

连接函数

巴法云的MQTT连接地址是(bemfa.com),端口号是 9501

MQTT连接,传入链接地址端口,在传入设备信息,主题信息即可

注意设置回调函数(接收到信息时触发)(client.setCallback(callback)😉

void clientReconnect() {
  while (!client.connected())  //再重连客户端
  {
    delay(3000);
    client.setServer(mqtt_server, 9501);                    //设置客户端连接的服务器
    client.connect(mqtt_devid, mqtt_pubid, mqtt_password);  //客户端连接到指定的产品的指定设备.同时输入鉴权信息
    client.subscribe(mqtt_topic);
    client.setCallback(callback);  //设置好客户端收到信息是的回调
    Serial.println("reconnect MQTT...");
    if (client.connect(mqtt_devid, mqtt_pubid, mqtt_password)) {
      Serial.println("connected");
    } else {
      Serial.println("failed");
      Serial.println(client.state());
    }
  }
}
//收到主题下发的回调, 注意这个回调要实现三个形参 1:topic 主题, 2: payload: 传递过来的信息 3: length: 长度
void callback(char *topic, byte *payload, unsigned int length) 
{

}

在回调函数中需要对信息处理

首先把主题信息和数据信息提取出来,转化成string格式(可以用内置函数比较)

  String topic_zj = "";
  String data_zj = "";
  for (size_t i = 0; i < strlen(topic); i++) {
    topic_zj += (char)topic[i];
  }

  for (size_t i = 0; i < length; i++) {
    data_zj += (char)payload[i];
  }

之后根据协议做比较即可

if (!topic_zj.compareTo(mqtt_topic)) {
    Serial.write(0xac);
    if (!data_zj.compareTo("H_ON")) {
      Serial.write(0x00);
      Serial.write(0x00);
    } else if (!data_zj.compareTo("H_OFF")) {
      Serial.write(0x00);
      Serial.write(0xFF);
    } else if (!data_zj.compareTo("N_ON")) {
      Serial.write(0x11);
      Serial.write(0x00);
    } else if (!data_zj.compareTo("N_OFF")) {
      Serial.write(0x11);
      Serial.write(0xFF);
    } else if (!data_zj.compareTo("S_ON")) {
      Serial.write(0x22);
      Serial.write(0x00);
    } else if (!data_zj.compareTo("S_OFF")) {
      Serial.write(0x22);
      Serial.write(0xFF);
    } else if (!data_zj.compareTo("W_ON")) {
      Serial.write(0x33);
      Serial.write(0x00);
    } else if (!data_zj.compareTo("W_OFF")) {
      Serial.write(0x33);
      Serial.write(0xFF);
    } else if (!data_zj.compareTo("ALL_ON")) {
      Serial.write(0xFF);
      Serial.write(0x00);
    } else if (!data_zj.compareTo("ALL_OFF")) {
      Serial.write(0xFF);
      Serial.write(0xFF);
    }
  }

esp32总程序

#include <PubSubClient.h>
#include <WiFi.h>
#include <esp_wifi.h>

uint8_t newMACAddress[] = { 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf };
const char *ssid = "K2FeO4";
const char *password = "lxz123ac";
const char *mqtt_server = "bemfa.com";  //onenet 的 IP地址

#define mqtt_devid "858e79b6f49d47fb90f2bd9f9ca2d331"  //设备ID
#define mqtt_pubid "  "                                //产品ID
#define mqtt_password " "                              //鉴权信息
const char *mqtt_topic = "ESP32HomeRFLight2";
WiFiClient espClient;            //创建一个WIFI连接客户端
PubSubClient client(espClient);  // 创建一个PubSub客户端, 传入创建的WIFI客户端

char msg_buf[200];  //发送信息缓冲区

void setupWifi() {
  WiFi.mode(WIFI_STA);
  esp_wifi_set_mac(WIFI_IF_STA, newMACAddress);
  Serial.println(WiFi.macAddress());

  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

//收到主题下发的回调, 注意这个回调要实现三个形参 1:topic 主题, 2: payload: 传递过来的信息 3: length: 长度
void callback(char *topic, byte *payload, unsigned int length) {
  String topic_zj = "";
  String data_zj = "";
  for (size_t i = 0; i < strlen(topic); i++) {
    topic_zj += (char)topic[i];
  }

  for (size_t i = 0; i < length; i++) {
    data_zj += (char)payload[i];
  }
  if (!topic_zj.compareTo(mqtt_topic)) {

    Serial.write(0xac);
    if (!data_zj.compareTo("H_ON")) {
      Serial.write(0x00);
      Serial.write(0x00);
    } else if (!data_zj.compareTo("H_OFF")) {
      Serial.write(0x00);
      Serial.write(0xFF);
    } else if (!data_zj.compareTo("N_ON")) {
      Serial.write(0x11);
      Serial.write(0x00);
    } else if (!data_zj.compareTo("N_OFF")) {
      Serial.write(0x11);
      Serial.write(0xFF);
    } else if (!data_zj.compareTo("S_ON")) {
      Serial.write(0x22);
      Serial.write(0x00);
    } else if (!data_zj.compareTo("S_OFF")) {
      Serial.write(0x22);
      Serial.write(0xFF);
    } else if (!data_zj.compareTo("W_ON")) {
      Serial.write(0x33);
      Serial.write(0x00);
    } else if (!data_zj.compareTo("W_OFF")) {
      Serial.write(0x33);
      Serial.write(0xFF);
    } else if (!data_zj.compareTo("ALL_ON")) {
      Serial.write(0xFF);
      Serial.write(0x00);
    } else if (!data_zj.compareTo("ALL_OFF")) {
      Serial.write(0xFF);
      Serial.write(0xFF);
    }
  }
}

void sendTempAndHumi() {
  if (client.connected()) {

    Serial.print("public message:");
    client.publish("$dp", (uint8_t *)msg_buf, 3);  //发送数据到主题$dp
  }
}

//重连函数, 如果客户端断线,可以通过此函数重连
void clientReconnect() {
  while (!client.connected())  //再重连客户端
  {
    delay(3000);
    client.setServer(mqtt_server, 9501);                    //设置客户端连接的服务器
    client.connect(mqtt_devid, mqtt_pubid, mqtt_password);  //客户端连接到指定的产品的指定设备.同时输入鉴权信息
    client.subscribe(mqtt_topic);
    client.setCallback(callback);  //设置好客户端收到信息是的回调
    Serial.println("reconnect MQTT...");
    if (client.connect(mqtt_devid, mqtt_pubid, mqtt_password)) {
      Serial.println("connected");
    } else {
      Serial.println("failed");
      Serial.println(client.state());
    }
  }
}

void setup() {
  // put your setup code here, to run once:
  //   rtc_wdt_protect_off();
  //   rtc_wdt_enable();
  //   rtc_wdt_feed();
  //   rtc_wdt_set_time(RTC_WDT_STAGE0, 8000);
  Serial.begin(115200);
  setupWifi();  //调用函数连接WIFI
  delay(2000);
  clientReconnect();
}

void loop() {
  // put your main code here, to run repeatedly:


  if (!WiFi.isConnected())  //先看WIFI是否还在连接
  {
    setupWifi();
  }
  if (!client.connected())  //如果客户端没连接ONENET, 重新连接
  {
    clientReconnect();
  }
  client.loop();  //客户端循环检测
}

stm32

相关链接

用到了之前写的几个库

舵机驱动

NEC

RF433

舵机关灯思路

设计思路

需要:

接收RF433信号/红外,根据解码的信号控制舵机

接收来自串口信号,根据信号发送RF433或控制舵机

需要用到的外设及功能

定时器(3个)(红外433解码,合用一个,舵机控制一个,RF433发送的时序控制一个)

串口1个(与esp32通信)

GPIO(5个,后续详细说)

硬件看门狗

HAL初始化

定时器1

用作 红外和RF433解码的计时

需要分频后1us为周期,最大计数无需改变,开启溢出中断

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LkSXEQuo-1676130327915)(picture/9.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rM7t2myC-1676130327916)(picture/10.png)]

定时器2

用作舵机控制的PWM生成

每隔20us触发一次中断

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L6fP0vkC-1676130327916)(picture/11.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U7e4YdhY-1676130327917)(picture/12.png)]

定时器3

用作RF433信号发射时的计时

分频1us,计数值默认最大即可,开中断

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NK734OrN-1676130327917)(picture/13.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WaVZdcEq-1676130327918)(picture/14.png)]

GPIO

LED:用作指示灯,推挽输出即可

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wu93asXP-1676130327918)(picture/15.png)]

GPIO

RF433输出

需要配置为推挽输出(开漏不行)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vxdzvUSG-1676130327919)(picture/16.png)]

GPIO

舵机控制信号

配置为开漏浮空(外部接上拉电阻到5V),配置为最高等级(避免复位时让电机出现误动作)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tne6j7oG-1676130327919)(picture/17.png)]

GPIO

RF433输入

配置为边沿中断模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uTchpMON-1676130327920)(picture/18.png)]

GPIO

红外输入

配置为下降沿中断模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l63PeSdI-1676130327921)(picture/19.png)]

注意开两个外部中断的中断设置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Uu169nDs-1676130327921)(picture/20.png)]

串口

开启中断,后面使用空闲中断来接收数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FTWQvzDw-1676130327921)(picture/21.png)]

硬件看门狗

32分频,溢出值4000

每(32/40k*4000=3.2s)触发一次

本程序目的是让程序每3.2s重启一次,因此只在需要操作舵机时喂狗,主循环无喂狗

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LljvVjOh-1676130327922)(picture/22.png)]

程序

分为

  1. 红外和RF433的解码共用了一个定时器,需要做时序控制,让红外有输入时屏蔽RF433,避免出现问题(RF会有幻听,会阶段性输入高低电平)
  2. 接收来自RF433,串口,红外的数据,在主循环里根据不同的指令做发射信号/控制舵机的动作

中断回调函数(舵机/红外/RF433的驱动)

保存串口数据

调用之前的库文件

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if (htim == &htim1)
  {
  }
  else if (htim == &htim2)
  {
    if (M_EN == 1)
      Steering_Engine_Action();
    else
      HAL_GPIO_WritePin(Steering_Engine_GPIOx, Steering_Engine_GPIO_Pin, GPIO_PIN_SET);
  }
  else if (htim == &htim3)
  {
  }
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if (GPIO_Pin == GPIO_PIN_2) // 433
  {
    if (Input_EN == 1)
      if (IR_NEC_Read_ins == 0)
        if (RF_READ_OK == 0)
          RF_Read_Decode();
  }
  else if (GPIO_Pin == GPIO_PIN_3) // IR
  {
    if (Input_EN == 1)
      if (IR_NEC_Read_OK == 0)
        IR_NEC_Read_Decode(air);
  }
}
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
  if (huart == &huart1)
  {
    Uart1_OK = 1;
    HAL_UART_Transmit(&huart2, Uart1_Buf, Size, 0xfff);
  }
}

开关灯控制

详情原理见,传送门

void OPEN()
{
  M_EN = 1;
  HAL_IWDG_Refresh(&hiwdg);
  Steering_Engine_360(0, 30);

  HAL_Delay(500);
  HAL_IWDG_Refresh(&hiwdg);
  Steering_Engine_360(1, 40);
  HAL_Delay(80);
  HAL_IWDG_Refresh(&hiwdg);
  Steering_Engine_Stop();
  M_EN = 0;
}
void CLOSE()
{
  M_EN = 1;
  HAL_IWDG_Refresh(&hiwdg);
  Steering_Engine_360(1, 30);
  HAL_Delay(500);
  HAL_IWDG_Refresh(&hiwdg);
  Steering_Engine_360(0, 30);
  HAL_Delay(80);
  HAL_IWDG_Refresh(&hiwdg);
  Steering_Engine_Stop();
  M_EN = 0;
}

主循环内容,根据传入的信息判断

 if (RF_READ_OK == 1)
    {
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
      Input_EN = 0;
      if (RF_READ_data[0] == 0xac && RF_READ_data[1] == 0x01 && RF_READ_data[2] == 0x00)
        OPEN();
      else if (RF_READ_data[0] == 0xac && RF_READ_data[1] == 0x01 && RF_READ_data[2] == 0xff)
        CLOSE();
      HAL_IWDG_Refresh(&hiwdg);
      RF_READ_data[0] = 0;
      RF_READ_data[1] = 0;
      RF_READ_data[2] = 0;
      RF_READ_OK = 0;
      Input_EN = 1;
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
    }

    if (IR_NEC_Read_OK == 1)
    {
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
      Input_EN = 0;
      //  printf("%02X%02X%02X\r\n", RF_READ_data[0], RF_READ_data[1], RF_READ_data[2]);

      if (IR_NEC_Read_Dat[0] == 0x4D && IR_NEC_Read_Dat[1] == 0xb2 && IR_NEC_Read_Dat[2] == 0xa3 && IR_NEC_Read_Dat[3] == 0x5C)
        OPEN();
      else if (IR_NEC_Read_Dat[0] == 0x4D && IR_NEC_Read_Dat[1] == 0xb2 && IR_NEC_Read_Dat[2] == 0x59 && IR_NEC_Read_Dat[3] == 0xa6)
        CLOSE();

      if (IR_NEC_Read_Dat[0] == 0x84 && IR_NEC_Read_Dat[1] == 0xff && IR_NEC_Read_Dat[2] == 0x81 && IR_NEC_Read_Dat[3] == 0x7e)
        OPEN();
      else if (IR_NEC_Read_Dat[0] == 0x84 && IR_NEC_Read_Dat[1] == 0xff && IR_NEC_Read_Dat[2] == 0x01 && IR_NEC_Read_Dat[3] == 0xfe)
        CLOSE();

      HAL_IWDG_Refresh(&hiwdg);
      IR_NEC_Read_Dat[0] = 0;
      IR_NEC_Read_Dat[1] = 0;
      IR_NEC_Read_Dat[2] = 0;
      IR_NEC_Read_Dat[3] = 0;
      IR_NEC_Read_OK = 0;
      Input_EN = 1;
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
    }

    if (Uart1_OK == 1)
    {
      Input_EN = 0;
      HAL_IWDG_Refresh(&hiwdg);
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
      if (Uart1_Buf[0] == 0xac && Uart1_Buf[1] != 0x00 && Uart1_Buf[1] != 0xFF)
      {
        for (int i = 0; i < 3; i++)
          RF433_Buf[i] = Uart1_Buf[i];
        RF_Write_Send(RF433_Buf);
      }
      else if (Uart1_Buf[0] == 0xac && Uart1_Buf[1] == 0x00)
      {
        if (Uart1_Buf[2] == 0x00)
          OPEN();
        else if (Uart1_Buf[2] == 0xff)
          CLOSE();
      }
      if (Uart1_Buf[0] == 0xac && Uart1_Buf[1] == 0xff)
      {
        // HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);
        if (Uart1_Buf[2] == 0x00)
        {
          RF_Write_Send(Data_N_Open);
          HAL_IWDG_Refresh(&hiwdg);
          HAL_Delay(300);
          HAL_IWDG_Refresh(&hiwdg);
          RF_Write_Send(Data_S_Open);
          OPEN();
        }
        else if (Uart1_Buf[2] == 0xff)
        {
          RF_Write_Send(Data_N_Close);
          HAL_IWDG_Refresh(&hiwdg);
          HAL_Delay(300);
          HAL_IWDG_Refresh(&hiwdg);
          RF_Write_Send(Data_S_Close);
          HAL_IWDG_Refresh(&hiwdg);
          CLOSE();
        }
      }
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
      Input_EN = 1;
      Uart1_OK = 0;
      HAL_UARTEx_ReceiveToIdle_IT(&huart1, Uart1_Buf, 20);
    }

注意,串口使用了空闲中断模式,鉴别不同数据帧

成品

另外app开发很简单,百度凑凑就行了,源码同样在GitHub上,请自行查看即可

GitHub

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

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

相关文章

【计算机网络期末复习】第二章 物理层

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4e3;专栏定位&#xff1a;为想复习学校计算机网络课程的同学提供重点大纲&#xff0c;帮助大家渡过期末考~ &#x1f4da;专栏地址&#xff1a; ❤️如果有收获的话&#xff0c;欢迎点…

Verilog语法之数学函数

Verilog-2005支持一些简单的数学函数&#xff0c;其参数的数据类型只能是integer和real型。 Integer型数学函数 $clog2是一个以2为底的对数函数&#xff0c;其结果向上取整&#xff0c;返回值典型的格式&#xff1a; integer result; result $clog2(n); 最典型的应用就是通过…

数据库(三):行锁和表锁,共享锁和排他锁,数据库引擎MyISAM和InnoDB,乐观锁和悲观锁

文章目录前言零、数据库引擎一、封锁粒度二、行锁三、表锁四、数据库中的属性锁4.2. 意向锁五、乐观锁和悲观锁总结前言 之前我们提到了数据库的隔离性可能会出现的若干问题&#xff0c;以及数据库为了解决这些问题而提出来的若干种隔离级别。实际上&#xff0c;数据库底层实现…

代码随想录算法训练营第二十七天|● 39. 组合总和 ● 40.组合总和II ● 131.分割回文串

39. 组合总和 看完题后的思路 本题本质上还是一个传统排列题&#xff0c;不同之处在于每个元素可以重复选取。void f&#xff08;【】&#xff0c;startIndex&#xff0c;sum&#xff09;递归终止 if&#xff08;和target&#xff09;{ 加入&#xff1b; 返回&#xff1b; }递…

HTTPS为什么就安全了?我们做了什么?

目录 一 安全概念 二 HTTPS的安全措施 三 总结 一 安全概念 网络安全是一个比较笼统的概念。我们说网络安全的时候&#xff0c;往往会包含很多安全问题&#xff0c;包括网络设备层面、通信过程、数据本身等多方面引入的安全问题。比如设备被有意无意的破坏&#xff0c;链路…

微搭低代码从入门到精通-03 创建模型应用

我们在进行低代码开发的时候&#xff0c;第一个需要建立的概念就是应用。不管你开发的是小程序还是管理系统&#xff0c;最终的承载物就是应用。 而我们创建应用是一共可以创建两种类型的应用&#xff0c;自定义应用和模型应用。自定义应用对应着一页多端&#xff0c;你开发一…

【Hello Linux】 Linux的权限以及Shell原理

作者&#xff1a;小萌新 专栏&#xff1a;Linux 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;介绍Linux的基础命令 Linux的权限以及Shell原理Shell的运行原理权限Linux中权限的概念如何切换用户如何提升当前操作的权限如何添加信任…

【C++:STL之栈和队列 | 模拟实现 | 优先级队列 】

目录 1. stack的介绍和使用 1.1 stack的介绍 1.2 stack的使用 2 栈的模拟实现 3 queue的介绍和使用 3.1 queue的介绍 3.2 queue的使用 4 queue的模拟实现 5 deque的介绍 5.1deque的原理介绍 5.2 deque的缺陷 5.3 为什么选择deque作为stack和queue的底层默认容器 6 p…

nodejs+vue+elementui在线求助系统vscode

目 录 摘 要 1 前 言 3 第1章 概述 4 1.1 研究背景 4 1.2 研究目的 4 1.3 研究内容 4 第二章 开发技术介绍 5 前端技术&#xff1a;nodejsvueelementui,视图层其实质就是vue页面&#xff0c;通过编写vue页面从而展示在浏览器中&#xff0c;编写完成的vue页面要能够和控制器类进…

加载sklearn covtype数据集出错 fetch_covtype() HTTPError: HTTP Error 403: Forbidden解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结与归纳,不仅形成深入且独到的理…

微搭低代码从入门到精通07-基础布局组件

低码开发不同于传统开发&#xff0c;传统开发我们通常需要编写前端代码和后端代码。前端代码由HTML、CSS和JavaScript组成&#xff0c;后端代码我们通常要用后端语言比如Java来编写接口。 低码开发的特点是可视化开发&#xff0c;在编辑器中通过组件的拖拽来完成页面的编制。如…

莽村李青都看得懂的Vue响应式原理

Vue响应式原理八股文序违背老祖宗的决定将Vue响应式原理公众于世响应式数据&#xff08;Observe篇&#xff09;dom更新&#xff08;Wacther篇&#xff09;依赖收集八股文序 开篇来一段大家都会背诵的八股文。 某面试官&#xff1a; 请你简要介绍一下Vue的响应式原理。 答&am…

leaflet 读取上传的wkt文件,转换为geojson文件(示例代码056)

第056个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+leaflet中上传WKT文件,解析wtk文件并转换为geojson,并在地图上显示图片。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式本示例所用的a.wkt示例源代码(共139行)…

AirServer在哪下载?如何免费使用教程

苹果手机投屏到电脑mac是怎么弄&#xff1f;你知道多少&#xff1f;相信大家对苹果手机投屏到电脑mac能在电脑上操作不是很了解&#xff0c;下面就让coco玛奇朵带大家一起了解一下教程。AIrServer是一款ios投屏到mac的专用软件&#xff0c;可将iOS上的音频&#xff0c;视频&…

make的使用及Makefile万能模板

make的使用及Makefile万能模板前言为什么用makemake的使用Makefile万能模板前言 gcc 的编译&#xff0c;是将源码生成可执行程序。 例如&#xff1a; gcc hello.c -o hello源码到可执行程序需要四步处理 硬件——》机器语言——》汇编语言——》 高级语言 1&#xff09;预处理…

【openGauss实战8】Schema的图文解读

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

Session与Cookie的区别(三)

中场休息 让我们先从比喻回到网络世界里&#xff0c;HTTP 是无状态的&#xff0c;所以每一个 Request 都是不相关的&#xff0c;就像是对小明来说每一位客人都是新的客人一样&#xff0c;他根本不知道谁是谁。 既然你没办法把他们关联&#xff0c;就代表状态这件事情也不存在。…

微搭低代码从入门到精通08-轮播容器

我们上一篇讲解了基础布局组件&#xff0c;讲解了普通容器和文本组件的用法&#xff0c;本篇我们继续介绍布局组件。 小程序中经常会有个功能是轮播图展示的功能&#xff0c;多张图片可以顺序进行切换。我们学习使用轮播容器的时候&#xff0c;先考虑切换的图片从哪来&#xf…

视频连载09 - 这个为生信学习和生信作图打造的开源R教程真香!!!

点击阅读原文跳转完整教案。1 思考题2 R基础2.1 R安装2.2 Rstudio基础2.2.1 Rstudio版本2.2.2 Rstudio安装2.2.3 Rstudio 使用2.3 R基本语法2.3.1 获取帮助文档&#xff0c;查看命令或函数的使用方法、事例或适用范围2.3.2 R中的变量及其初始化2.3.3 变量类型和转换2.3.4 R中矩…

Python-项目实战--贪吃蛇小游戏(1)

1.贪吃蛇游戏规则贪吃蛇游戏规则如下:1.1开始和结束贪吃蛇初始出现在游戏窗口的左上角位置,体长共有3节游戏过程中&#xff0c;一旦蛇头撞到了窗口的边缘或者身体的其他部位,游戏结束游戏过程中&#xff0c;点击游戏窗口的关闭按钮&#xff0c;或者按下ESC键可以直接退出游戏一…