MSPM0G3507学习笔记(二) 超便捷配置led与按键

电赛备赛中,打算系统过一遍MSPM0G3507的各个部分,同时把过程记录下来。本系列以代码全部能用+复用性、可移植性高为目的。本系列所有的代码会开源至github,如果觉得有用,请点个赞/给我的github仓库点一颗star吧。

github地址:https://github.com/whyovo/MSPM0G3507Learning-Notes

(一)基础配置:https://blog.csdn.net/qq_23220445/article/details/148502065?spm=1001.2014.3001.5501

1.工程介绍

所有代码都在code中,device是设备相关代码,hardware是底层相关代码,ti是ti的库函数。

入口是main.c,general.h包含所有需要的头文件。

2.led与按键使用方法

在led.c里面添加led,key.c里面添加按键即可,像这样就添加了pb2与pb3这两个led,pa18这一个按键,按键需要指明按下时是高电平还是低电平(即active_level)

然后在main.c里面初始化即可直接使用

key_init();
led_init();

led支持开关、闪烁、呼吸灯与流水灯,分别调用以下函数即可:

void led_on(LED_Config *led);
void led_off(LED_Config *led);
void led_toggle(LED_Config *led);
void led_blink(LED_Config *led, uint32_t times, uint32_t delay_ms);
void led_breathing(LED_Config *led, uint32_t cycles, uint32_t duration_ms);
void led_water_flow(LED_Config *leds, uint8_t count, uint32_t delay_ms);

按键支持短按、长按与双击。

下面是一个综合案例,根据不同的按键操作触发不同的LED效果——短按让LED1闪烁3次,长按让LED1产生呼吸灯效果,双击触发两个LED的流水灯效果

main.c:

#include "general.h"
#include <stdio.h>int main(void)
{SYSCFG_DL_init();key_init();  // 启用按键初始化led_init();  // 启用LED初始化while (1) {// 按键扫描并触发对应LED效果KEY_State key_state = key_scan(&key_configs[0]);switch (key_state) {case KEY_SHORT_PRESS:// 短按:LED1闪烁3次,每次闪烁间隔200msled_blink(&led_configs[0], 3, 200);break;case KEY_LONG_PRESS:// 长按:LED1呼吸灯效果,2个周期,持续1000msled_breathing(&led_configs[0], 2, 1000);break;case KEY_DOUBLE_CLICK:// 双击:两个LED流水灯效果led_water_flow(led_configs, 2, 300);break;default:// 无按键操作,不执行特殊效果break;}delay_ms(10);}
}

效果:

双击:流水灯效果

短按:LED1闪烁3次

长按:LED1呼吸灯2个周期,每个周期1秒

3.gpio使用方法

需要用gpio但不是led或者按键,用以下方法:

先在gpio.c里面定义引脚,说明是输出还是输入,上拉还是下拉,以及初始电平

然后直接在主函数调用gpio_init(),即可一键配置,然后直接调用函数即可:

// 函数声明
bool gpio_init_one(const GPIO_Config *config);
bool gpio_init_multiple(const GPIO_Config *configs, uint8_t count);
void gpio_set_pin(GPIO_Regs *port, uint32_t pin);
void gpio_clear_pin(GPIO_Regs *port, uint32_t pin);
void gpio_toggle_pin(GPIO_Regs *port, uint32_t pin);
void gpio_write_pin(GPIO_Regs *port, uint32_t pin, GPIO_Level level);
GPIO_Level gpio_read_pin(GPIO_Regs *port, uint32_t pin);
bool gpio_is_pin_set(GPIO_Regs *port, uint32_t pin);
void gpio_init(void);

4.部分代码参考

这里放led与key的代码,详细见github仓库里面的tjuwyh这个文件夹。

led.c

#include "led.h"
LED_Config led_configs[] = {{.port        = GPIOB,.pin         = DL_GPIO_PIN_2,.initialized = false}, // LED1{.port        = GPIOB,.pin         = DL_GPIO_PIN_3,.initialized = false}, // LED2
};void led_init(void)
{for (int i = 0; i < sizeof(led_configs) / sizeof(led_configs[0]); i++) {// 创建临时GPIO配置结构体GPIO_Config gpio_config = {.port = led_configs[i].port,.pin = led_configs[i].pin,.dir = GPIO_DIR_OUTPUT,.pull = GPIO_PULL_NONE,.init_level = GPIO_HIGH  // 默认高电平};// 直接调用led_init_one初始化LED和GPIOif (!led_init_one(&led_configs[i], &gpio_config)) {// 初始化失败,可以添加错误处理}}
}// LED初始化
bool led_init_one(LED_Config *led, const GPIO_Config *gpio_config)
{if (!led || !gpio_config) return false;// 检查GPIO配置是否为输出模式if (gpio_config->dir != GPIO_DIR_OUTPUT) {return false;}// 初始化GPIOif (!gpio_init_one(gpio_config)) {return false;}// 配置LED结构体led->port        = gpio_config->port;led->pin         = gpio_config->pin;led->initialized = true;return true;
}// 检查LED是否已初始化
static bool led_is_initialized(LED_Config *led)
{return led && led->initialized;
}void led_on(LED_Config *led)
{if (!led_is_initialized(led)) return;gpio_clear_pin(led->port, led->pin); // 共阴极LED,低电平点亮
}void led_off(LED_Config *led)
{if (!led_is_initialized(led)) return;gpio_set_pin(led->port, led->pin); // 共阴极LED,高电平熄灭
}void led_toggle(LED_Config *led)
{if (!led_is_initialized(led)) return;gpio_toggle_pin(led->port, led->pin);
}void led_blink(LED_Config *led, uint32_t times, uint32_t delay_ms_val)
{if (!led_is_initialized(led)) return;for (uint32_t i = 0; i < times; i++) {led_on(led);delay_ms(delay_ms_val);led_off(led);delay_ms(delay_ms_val);}
}void led_breathing(LED_Config *led, uint32_t cycles, uint32_t duration_ms)
{if (!led_is_initialized(led)) return;// 呼吸灯参数配置const uint32_t steps         = 100;                       // 每个方向的步数const uint32_t pwm_period_us = 1000;                      // PWM周期1msconst uint32_t step_delay_ms = duration_ms / (steps * 2); // 每步延时for (uint32_t cycle = 0; cycle < cycles; cycle++) {// 渐亮过程for (uint32_t i = 1; i <= steps; i++) {// 计算占空比 (1-100%)uint32_t duty_percent = (i * 100) / steps;uint32_t on_time_us   = (pwm_period_us * duty_percent) / 100;uint32_t off_time_us  = pwm_period_us - on_time_us;// PWM周期数,确保有足够的时间看到效果uint32_t pwm_cycles = (step_delay_ms * 1000) / pwm_period_us;if (pwm_cycles < 1) pwm_cycles = 1;// 执行PWM - 使用GPIO函数for (uint32_t j = 0; j < pwm_cycles; j++) {if (on_time_us > 0) {gpio_clear_pin(led->port, led->pin); // LED点亮delay_us(on_time_us);}if (off_time_us > 0) {gpio_set_pin(led->port, led->pin); // LED熄灭delay_us(off_time_us);}}}// 渐暗过程for (uint32_t i = steps; i >= 1; i--) {// 计算占空比 (100%-1%)uint32_t duty_percent = (i * 100) / steps;uint32_t on_time_us   = (pwm_period_us * duty_percent) / 100;uint32_t off_time_us  = pwm_period_us - on_time_us;// PWM周期数uint32_t pwm_cycles = (step_delay_ms * 1000) / pwm_period_us;if (pwm_cycles < 1) pwm_cycles = 1;// 执行PWM - 使用GPIO函数for (uint32_t j = 0; j < pwm_cycles; j++) {if (on_time_us > 0) {gpio_clear_pin(led->port, led->pin); // LED点亮delay_us(on_time_us);}if (off_time_us > 0) {gpio_set_pin(led->port, led->pin); // LED熄灭delay_us(off_time_us);}}}}// 确保最后LED是关闭状态led_off(led);
}void led_water_flow(LED_Config *leds, uint8_t count, uint32_t delay_ms_val)
{if (!leds) return;for (uint8_t i = 0; i < count; i++) {if (led_is_initialized(&leds[i])) {led_on(&leds[i]);delay_ms(delay_ms_val);led_off(&leds[i]);}}
}

led.h

#ifndef __LED_H
#define __LED_H#if __has_include("gpio.h")
#include "gpio.h"#else
// 如果没有定义GPIO模块,使用其他库,以HAL库为例
#include "stm32f1xx_hal.h" // 根据实际MCU型号调整// 定义GPIO类型别名
typedef GPIO_TypeDef GPIO_Regs;// 将自定义GPIO函数映射到HAL库函数
#define gpio_set_pin(port, pin)          HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET)
#define gpio_clear_pin(port, pin)        HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET)
#define gpio_toggle_pin(port, pin)       HAL_GPIO_TogglePin(port, pin)
#define gpio_write_pin(port, pin, level) HAL_GPIO_WritePin(port, pin, (level) ? GPIO_PIN_SET : GPIO_PIN_RESET)
#define gpio_read_pin(port, pin)         (HAL_GPIO_ReadPin(port, pin) == GPIO_PIN_SET ? 1 : 0)
#define gpio_is_pin_set(port, pin)       (HAL_GPIO_ReadPin(port, pin) == GPIO_PIN_SET)// 定义GPIO配置结构体(简化版)
typedef struct {GPIO_Regs *port;uint32_t pin;uint8_t dir;        // 方向uint8_t init_level; // 初始电平uint8_t pull;       // 上拉下拉
} GPIO_Config;// 定义枚举值
#define GPIO_DIR_INPUT                   0
#define GPIO_DIR_OUTPUT                  1
#define GPIO_LOW                         0
#define GPIO_HIGH                        1// 提供兼容函数声明
static inline bool gpio_init_one(const GPIO_Config *config)
{GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin              = config->pin;GPIO_InitStruct.Mode             = (config->dir == GPIO_DIR_OUTPUT) ? GPIO_MODE_OUTPUT_PP : GPIO_MODE_INPUT;GPIO_InitStruct.Pull             = GPIO_NOPULL; // 简化处理GPIO_InitStruct.Speed            = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(config->port, &GPIO_InitStruct);if (config->dir == GPIO_DIR_OUTPUT && config->init_level == GPIO_HIGH) {HAL_GPIO_WritePin(config->port, config->pin, GPIO_PIN_SET);}return true;
}
#endif#include "gpio.h"
#include "delay.h"// LED配置结构体
typedef struct {GPIO_Regs *port;uint32_t pin;bool initialized; // 标记是否已初始化
} LED_Config;// LED初始化和控制函数
bool led_init_one(LED_Config *led, const GPIO_Config *gpio_config);
void led_on(LED_Config *led);
void led_off(LED_Config *led);
void led_toggle(LED_Config *led);
void led_blink(LED_Config *led, uint32_t times, uint32_t delay_ms);
void led_breathing(LED_Config *led, uint32_t cycles, uint32_t duration_ms);
void led_water_flow(LED_Config *leds, uint8_t count, uint32_t delay_ms);
void led_init(void);// 便捷宏定义
#define LED_ON(led)     led_on(led)
#define LED_OFF(led)    led_off(led)
#define LED_TOGGLE(led) led_toggle(led)extern LED_Config led_configs[];#endif

key.c

#include "key.h"KEY_Config key_configs[] = {{.port         = GPIOA,.pin          = DL_GPIO_PIN_18,.active_level = KEY_ACTIVE_HIGH,.initialized  = false},          // KEY1
};#define KEY_DEBOUNCE_TIME     20  // 消抖时间 20ms
#define KEY_LONG_PRESS_TIME   500 // 长按时间 500ms
#define KEY_DOUBLE_CLICK_TIME 300 // 双击间隔时间 300ms// 按键状态定义
typedef enum {KEY_STATE_IDLE = 0,   // 空闲状态KEY_STATE_PRESSED,    // 按下状态KEY_STATE_RELEASED,   // 释放状态KEY_STATE_DOUBLE_WAIT // 双击等待状态
} KEY_StateMachine;void key_init(void)
{for (int i = 0; i < sizeof(key_configs) / sizeof(key_configs[0]); i++) {// 根据按键有效电平选择合适的上拉/下拉配置GPIO_Pull pull_config;if (key_configs[i].active_level == KEY_ACTIVE_HIGH) {pull_config = GPIO_PULL_DOWN;  // 高电平有效时使用下拉电阻} else {pull_config = GPIO_PULL_UP;    // 低电平有效时使用上拉电阻}// 创建临时GPIO配置结构体GPIO_Config gpio_config = {.port = key_configs[i].port,.pin = key_configs[i].pin,.dir = GPIO_DIR_INPUT,.pull = pull_config,          // 根据按键有效电平配置上拉/下拉.init_level = GPIO_HIGH       // 对输入引脚无实际影响};// 直接调用key_init_one初始化按键和GPIOif (!key_init_one(&key_configs[i], &gpio_config, key_configs[i].active_level)) {// 初始化失败,可以添加错误处理}}
}   // KEY初始化
bool key_init_one(KEY_Config *key, const GPIO_Config *gpio_config, KEY_ActiveLevel active_level)
{if (!key || !gpio_config) return false;// 检查GPIO配置是否为输入模式if (gpio_config->dir != GPIO_DIR_INPUT) {return false;}// 初始化GPIOif (!gpio_init_one(gpio_config)) {return false;}// 配置KEY结构体key->port         = gpio_config->port;key->pin          = gpio_config->pin;key->active_level = active_level;key->initialized  = true;// 初始化内部状态key->last_time       = 0;key->press_count     = 0;key->long_press_flag = 0;return true;
}// 检查KEY是否已初始化
static bool key_is_initialized(KEY_Config *key)
{return key && key->initialized;
}uint8_t key_read(KEY_Config *key)
{if (!key_is_initialized(key)) return 0;uint8_t pin_state = DL_GPIO_readPins(key->port, key->pin) ? 1 : 0;// 根据配置的有效电平返回按键状态if (key->active_level == KEY_ACTIVE_HIGH) {return pin_state; // 高电平有效} else {return !pin_state; // 低电平有效}
}KEY_State key_scan(KEY_Config *key)
{if (!key_is_initialized(key)) return KEY_NONE;static KEY_StateMachine key_state  = KEY_STATE_IDLE;static uint32_t press_start_time   = 0;static uint32_t release_start_time = 0;static uint32_t last_scan_time     = 0;uint32_t current_time = get_tick();// 每1ms扫描一次if (current_time - last_scan_time < 1) {return KEY_NONE;}last_scan_time = current_time;uint8_t key_pressed           = key_read(key);static uint8_t last_key_state = 0;// 消抖处理if (key_pressed != last_key_state) {delay_ms(KEY_DEBOUNCE_TIME);if (key_read(key) != key_pressed) {return KEY_NONE; // 抖动,忽略}last_key_state = key_pressed;}switch (key_state) {case KEY_STATE_IDLE:if (key_pressed) {key_state        = KEY_STATE_PRESSED;press_start_time = current_time;}break;case KEY_STATE_PRESSED:if (!key_pressed) {// 按键释放,判断按下时间uint32_t press_duration = current_time - press_start_time;if (press_duration >= KEY_LONG_PRESS_TIME) {// 长按事件,直接回到空闲状态key_state = KEY_STATE_IDLE;return KEY_LONG_PRESS;} else {// 进入释放状态,等待可能的双击key_state          = KEY_STATE_RELEASED;release_start_time = current_time;}}break;case KEY_STATE_RELEASED:if (key_pressed) {// 在释放状态内再次按下,进入双击等待状态key_state        = KEY_STATE_DOUBLE_WAIT;press_start_time = current_time;} else if (current_time - release_start_time >= KEY_DOUBLE_CLICK_TIME) {// 超时未再次按下,判定为单击key_state = KEY_STATE_IDLE;return KEY_SHORT_PRESS;}break;case KEY_STATE_DOUBLE_WAIT:if (!key_pressed) {// 双击的第二次按下释放key_state = KEY_STATE_IDLE;return KEY_DOUBLE_CLICK;} else if (current_time - press_start_time >= KEY_LONG_PRESS_TIME) {// 如果第二次按下时间过长,按长按处理key_state = KEY_STATE_IDLE;return KEY_LONG_PRESS;}break;}return KEY_NONE;
}

key.h

#ifndef __KEY_H
#define __KEY_H#include "sys_init.h"
#include "gpio.h"
#include "delay.h"typedef enum {KEY_NONE = 0,KEY_SHORT_PRESS,KEY_LONG_PRESS,KEY_DOUBLE_CLICK
} KEY_State;typedef enum {KEY_ACTIVE_LOW  = 0, // 按键按下为低电平KEY_ACTIVE_HIGH = 1  // 按键按下为高电平
} KEY_ActiveLevel;// KEY配置结构体
typedef struct {GPIO_Regs *port;uint32_t pin;KEY_ActiveLevel active_level; // 按键有效电平bool initialized;             // 标记是否已初始化// 内部状态变量uint32_t last_time;      // 上次扫描时间uint8_t press_count;     // 按键计数uint8_t long_press_flag; // 长按标志
} KEY_Config;// 函数声明
bool key_init_one(KEY_Config *key, const GPIO_Config *gpio_config, KEY_ActiveLevel active_level);
KEY_State key_scan(KEY_Config *key);
uint8_t key_read(KEY_Config *key);// 便捷宏定义
#define KEY_IS_PRESSED(key)  (key_read(key) == 1)
#define KEY_IS_RELEASED(key) (key_read(key) == 0)
void key_init(void);extern KEY_Config key_configs[];#endif

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

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

相关文章

day03-微服务01

【黑马程序员SpringCloud微服务技术栈实战教程&#xff0c;涵盖springcloud微服务架构Nacos配置中心分布式事务等】 暂时无法在飞书文档外展示此内容 之前我们学习的项目一是单体项目&#xff0c;可以满足小型项目或传统项目的开发。而在互联网时代&#xff0c;越来越多的一线…

嵌入式Linux系统内存占用率高的原因、后果与防控全解析

作者&#xff1a;嵌入式Jerry 【欢迎关注“嵌入式Jerry”&#xff0c;获取更多Linux/驱动/性能实战干货】 推荐阅读&#xff1a;《Yocto项目实战教程&#xff1a;高效定制嵌入式Linux系统》 京东正版促销&#xff0c;支持作者&#xff01;https://item.jd.com/15020438.html 嵌…

【案例分享】如何用 DHTMLX Scheduler 构建灵活高效的资源调度系统?

在企业信息化进程加速的今天&#xff0c;资源调度与任务管理已成为ERP系统中的关键模块。今天&#xff0c;我们带来了一个来自 X-Interactive 的精彩应用案例&#xff0c;看他们如何借助 DHTMLX Scheduler 实现更智能的任务分配与资源规划。 DHTMLX Scheduler 试用下载 &…

Kafka 向 TDengine 写入数据

TDengine Kafka Connector 包含 TDengine Source Connector 和 TDengine Sink Connector 两个插件。用户只需提供简单的配置文件&#xff0c;就可以将 Kafka 中指定 topic 的数据&#xff08;批量或实时&#xff09;同步到 TDengine&#xff0c;或将 TDengine 中指定数据库的数…

智慧医院核心引擎:IBMS 系统守护医疗环境高效与安全​

在医疗场景中&#xff0c;时间就是生命&#xff0c;效率与安全容不得分毫差错。传统医院面临着设备管理分散、应急响应迟缓、能耗居高不下等难题&#xff0c;严重制约医疗服务质量与运营效率。而 IBMS 系统&#xff0c;作为智慧医院的核心引擎&#xff0c;以尖端科技重塑医疗环…

平均性能提升70%,盖雅工场基于腾讯云数据仓库TCHouse-D构建实时报表平台

点击蓝字⬆ 关注我们 本文共计3569字 预计阅读时长11分钟 导语 腾讯云数据仓库TCHouse-D助力盖雅工场构建了架构简洁、查询高效的报表平台。目前该平台已经支撑了盖雅工场上千个租户的实时报表需求&#xff0c;报表查询时效性整体可达亚秒级&#xff0c;相较原架构&#xff0c;…

zynq裸机开发:更改系统时间保存文件到SD卡

1、首先勾选文件系统库 2、之后导出一个SD卡文件写demo 3、SD卡创建或修改文件时的创建时间和修改时间是通过调用BSP包的diskio.c文件中的get_fattime函数 4、找到这段函数&#xff0c;先把他注释掉&#xff0c;之后考到导出demo的最后一行&#xff0c;稍作修改&#xff0c…

“荔枝使”的难题怎么破:A*运输路径算法编程实践

原文首发请访问&#xff1a;https://cloud.tencent.com/developer/article/2533317 荔枝最初被称为“离支”&#xff0c;亦作“离枝”。 这是一种非常精贵的水果&#xff0c;一旦离开枝头&#xff0c;色泽、香气和味道会在短时间内迅速变质。 但它又是非常美味&#xff0c;宋…

python基础知识,以及7个练习案例

python的用途 搭建网站网络爬虫科学计算与大数据分析人工智能与机器学习设计动画游戏&#xff1a;例如pygame图形用户接口开发&#xff1a;模块与框架&#xff0c;如tkinter python基础课程包含内容 自动化运维人工智能应用web开发多媒体处理自动化办公python爬虫 python是…

Java 编程之命令模式

什么是命令模式 命令模式Command Pattern 是一种行为型设计模式&#xff0c;它把请求封装成对象&#xff0c;从而将请求的发送者与执行者完全解耦&#xff0c;支持排队、撤销、日志记录等操作。。 模式目标&#xff1a; 解耦命令的发出者&#xff08;Invoker&#xff09;与执…

TCP 三次握手与四次挥手全流程详解

TCP(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层协议。为了建立和终止连接,TCP 使用了 三次握手 和 四次挥手 的机制。本文将从原理到状态变化,详细解析 TCP 连接的建立与释放全过程,力求专业、准确。 一、TCP 三次握手(Three-Way Han…

MySQL 慢 SQL 识别与优化

一、识别慢 SQL 1. 启用慢查询日志 -- 查看当前慢查询配置 SHOW VARIABLES LIKE slow_query%; SHOW VARIABLES LIKE long_query_time;-- 开启慢查询日志&#xff08;临时生效&#xff09; SET GLOBAL slow_query_log ON; SET GLOBAL long_query_time 2; -- 设置慢查询阈值…

墨记APP:水墨风记事,书写生活诗意

在快节奏的现代生活中&#xff0c;记录生活的点滴成为了一种独特的仪式感。无论是日常的琐事、突发的灵感&#xff0c;还是对未来的规划&#xff0c;一款好用的记事软件都能帮助我们更好地整理思绪&#xff0c;留住美好瞬间。墨记APP正是一款兼具美学与实用性的记事软件&#x…

龙芯7A1000桥片数据手册解读(时序)

RTC是电池&#xff0c;理论上一直是有电的&#xff0c;图示指的是接上220V电之后切换为系统的电。顺序是这样的&#xff1a;接上220V电之后系统的12V供电就有了&#xff0c;12V转为5VSB&#xff0c;5VSB供给RTC3V&#xff0c;此时RTC3V转为系统供电而不是电池供电。这里的5VSB指…

无人机气压计模块技术解析

一、运行方式 1. 基础原理 气压计通过测量大气压力间接计算高度。无人机飞行中&#xff0c;气压随高度上升而降低&#xff0c;传感器将压力信号转为电信号&#xff0c;经ADC转换为数字值。 2. 工作流程 数据采集&#xff1a;同步获取压力与温度值。 原始数据处理&…

第十四节:第三部分:IO流:前置知识-什么是方法递归以及递归的形式、递归算法三要素

什么是方法递归以及递归的形式 递归算法三要素 代码 代码一&#xff1a;认识一下递归的形式 package com.itheima.Recurtion; //目标:认识一下递归的形式 public class RecurtionTest1 {public static void main(String[] args) {test2();}//直接方法递归public static void…

论文阅读笔记:Digging Into Self-Supervised Monocular Depth Estimation

论文阅读笔记&#xff1a;Digging Into Self-Supervised Monocular Depth Estimation 1 背景2 创新点3 方法4 模块4.1 自监督训练4.2 优化自监督深度估计4.2.1 每个像素的最小重建损失4.2.2 自动掩码静态像素4.2.3 多尺度估计4.2.4 最终的训练损失 4.3 额外考虑 5 效果 1 背景 …

YAML 数据格式详解

1. YAML 概念 YAML (YAML Ain’t Markup Language) 是一种人性化的数据序列化格式&#xff1a; 专注于数据而非标记&#xff08;与 XML 不同&#xff09;使用简洁的语法表示复杂数据结构可读性高&#xff0c;适合人类编写和阅读广泛应用于配置文件&#xff08;如 Docker Comp…

react扩展

首先补充一下上个章节的一点结尾内容。reducer是一个纯函数&#xff0c;纯函数指的是当我们在redux里面定义了我们需要共享的对象后&#xff0c;我们是不可以对共享的对象本身进行改变的。我们在获取更新后的共享数据时&#xff0c;要去重新定义一个新的变量来获取更新后的共享…

6.获取图片灰度与缩放

目录 一、Halcon 1. 获取像素坐标以及灰度 2. 拖动缩放 3.图像缩放的实现方式 二、VS联合编程 1.获取像素坐标和灰度 2.拖动缩放 一、Halcon 1. 获取像素坐标以及灰度 *1. 获取像素坐标 * 1. get_mposition * 2. halcon窗口事件自带坐标数据 * *2. 获取像素灰度 *…