ARM综合编程--LED--ADC--UART--中断--PWM综合示例按键和旋钮控制音乐

news2024/10/12 3:16:49

第一步:定义全局变量

  • 包括歌曲和音符数组。
  • 定义控制LED灯和按键的GPIO地址(这里你需要提供准确的硬件位置信息)。
  • 定义用于ADC旋钮调节音量的变量。
// 全局变量定义
char song0[] = {2, 3, 4, 3, 2, 3, 2, 3, 2, 4, 2, 1, 4, 3, 2};  // 两只老虎
char song1[] = {1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1};         // 生日快乐
char song2[] = {4, 4, 5, 5, 6, 6, 7, 7, 6, 6, 5, 5};             // abcdefg
char song3[] = {7, 6, 5, 4, 3, 2, 1};                            // 祝你平安

char yf[] = {0, 191, 172, 159, 144, 135, 120, 107};  // 音符对应的频率表

char song_index = 0;  // 当前播放的歌曲索引
char play_pos = 0;    // 当前音符位置

// LED 和按键的 GPIO 地址(根据你的实际硬件位置调整)
#define GPIO_LED1 *(volatile long*)0x11400000  // LED 1 的 GPIO 地址
#define GPIO_LED2 *(volatile long*)0x11400004  // LED 2 的 GPIO 地址
#define GPIO_LED3 *(volatile long*)0x11400008  // LED 3 的 GPIO 地址
#define GPIO_LED4 *(volatile long*)0x1140000C  // LED 4 的 GPIO 地址

#define BUTTON_PIN *(volatile long*)0x11000020  // 按键的 GPIO 地址,用于切换歌曲

// ADC 的 GPIO 地址,用于旋钮控制音量
#define ADCCON   *(volatile long*)0x126C0000  // ADC 控制寄存器
#define ADCDAT   *(volatile long*)0x126C000C  // ADC 数据寄存器
#define ADCMUX   *(volatile long*)0x126C001C  // ADC 多路复用器

第二步:UART 串口初始化

  • 初始化 UART 用于调试输出。
  • 实现串口发送字符和字符串的功能。
// 串口初始化及调试输出相关定义
#define GPA1CON  *(volatile long*)0x11400020  // GPIO A1 控制寄存器
#define ULCON2   *(volatile long*)0x13820000  // UART2 控制寄存器
#define UCON2    *(volatile long*)0x13820004  // UART2 控制寄存器
#define UTRSTAT2 *(volatile long*)0x13820010  // UART2 状态寄存器
#define UTXH2    *(volatile long*)0x13820020  // UART2 发送寄存器
#define UBRDIV2  *(volatile long*)0x13820028  // UART2 波特率分频寄存器
#define UFRACVAL2 *(volatile long*)0x1382002C // UART2 波特率小数部分寄存器

// 串口初始化函数
void uart_init(void) {
    GPA1CON = GPA1CON & ~0xF;
    GPA1CON = GPA1CON | (1 << 1);    // UART TX
    GPA1CON = GPA1CON & ~(0xF << 4);
    GPA1CON = GPA1CON | (1 << 5);    // UART RX

    ULCON2 = 0x03;                   // 8 位数据,无校验,1 位停止位
    UCON2 = 0x05;                    // 轮询模式
    UBRDIV2 = 53;                    // 设置波特率为 115200
    UFRACVAL2 = 4;
}

// 串口发送单个字符
void putc(char ch) {
    while (!(UTRSTAT2 & (1 << 1)));  // 等待发送缓冲区空
    UTXH2 = ch;
}

// 串口发送字符串
void puts(char *s) {
    int i = 0;
    while (s[i]) {
        putc(s[i]);
        i++;
    }
}

第三步:ADC 初始化和音量读取

通过 ADC 获取旋钮的电压值,并将其用于调节音量大小。

// ADC 初始化函数
void adc_init(void) {
    ADCCON |= 1 << 16;  // 12 比特分辨率
    ADCCON |= 1 << 14;  // 使能分频
    ADCCON &= ~(0xFF << 6);
    ADCCON |= 19 << 6;  // 设置分频值
    ADCCON &= ~(1 << 2);  // 禁用空闲模式
    ADCCON |= 1 << 0;  // 启动 ADC
    ADCMUX = 3;  // 使用第 3 个 ADC 通道
}

// 获取 ADC 值并转换为毫伏值
int adc_get_mv(void) {
    int reg = ADCDAT & 0xFFF;
    return reg * 1800 / 4095;  // 将 ADC 数据转换为毫伏
}

第四步:PWM 定时器配置用于音符播放

// PWM 定时器初始化
#define TCFG0    *(volatile long*)0x139D0000  // 定时器配置寄存器 0
#define TCFG1    *(volatile long*)0x139D0004  // 定时器配置寄存器 1
#define TCNTB0   *(volatile long*)0x139D000C  // 定时器计数寄存器,用于设置周期
#define TCMPB0   *(volatile long*)0x139D0010  // 定时器比较寄存器,用于设置占空比
#define TCON     *(volatile long*)0x139D0008  // 定时器控制寄存器

void pwm_init(void) {
    // 配置预分频器
    TCFG0 = (TCFG0 & ~(0xFF)) | 99;      // 预分频器1,设置为99+1=100分频
    TCFG1 = (TCFG1 & ~(0xF)) | 0x2;      // 分频器2,设置为PWM模式的1/4分频
    
    // 设置PWM占空比为50%,即一半时间高电平,一半时间低电平
    TCMPB0 = TCNTB0 / 2;                 // 设置比较寄存器,产生50%的占空比
    
    // 设置定时器控制寄存器,启用自动重载并开始PWM输出
    TCON |= (1 << 1);                    // 手动更新 TCNTB0 和 TCMPB0 的值
    TCON &= ~(1 << 1);                   // 清除手动更新位
    TCON |= (1 << 0) | (1 << 3);         // 启用定时器0并启动PWM
}

// 播放音符函数,调整PWM频率以产生不同音符
void play_yinfu(char note) {
    if (note >= 1 && note <= 7) {
        TCNTB0 = yf[note];  // 根据音符调整PWM频率
        TCMPB0 = TCNTB0 / 2;  // 设置50%占空比
        TCON |= (1 << 1);      // 手动更新TCNTB0和TCMPB0的值
        TCON &= ~(1 << 1);     // 清除手动更新位
        TCON |= (1 << 0);      // 启动PWM输出
    }
}

第五步:按键切换歌曲及 LED 显示

不断轮询 ADC 的值用于调节音量,并根据当前的歌曲播放音符。

// 切换歌曲和控制灯光的中断处理函数
void do_irq() {
    song_index = (song_index + 1) % 4;  // 切换到下一首歌
    play_pos = 0;  // 从头开始播放

    // 切换灯光逻辑
    switch (song_index) {
        case 0:
            GPIO_LED1 = 1;
            GPIO_LED2 = 0;
            GPIO_LED3 = 0;
            GPIO_LED4 = 0;
            break;
        case 1:
            GPIO_LED1 = 0;
            GPIO_LED2 = 1;
            GPIO_LED3 = 0;
            GPIO_LED4 = 0;
            break;
        case 2:
            GPIO_LED1 = 0;
            GPIO_LED2 = 0;
            GPIO_LED3 = 1;
            GPIO_LED4 = 0;
            break;
        case 3:
            GPIO_LED1 = 0;
            GPIO_LED2 = 0;
            GPIO_LED3 = 0;
            GPIO_LED4 = 1;
            break;
    }

    puts("Song changed!\r\n);
}
    // 定义按键中断
void handle_button_press() {
    if (BUTTON_PIN & 0x01) {  // 假设按键按下触发低电平
        do_irq();  // 处理按键按下,切换歌曲
    }
}


第六步: 主程序逻辑

主程序将持续运行,轮询按键的状态,控制 LED 和音符的播放,并根据 ADC 旋钮调节音量和播放速度。

// 主程序
int main(void) {
    int mv;
    int qian, bai, shi, ge;

    uart_init();  // 初始化串口
    adc_init();   // 初始化 ADC
    pwm_init();   // 初始化 PWM

    puts("System initialized!\r\n");

    while (1) {
        // 检查按键是否按下
        handle_button_press();  // 检查是否有按键按下,处理歌曲切换

        // 获取当前的音量值(通过 ADC 读取旋钮值)
        mv = adc_get_mv();  // 获取当前电压值

        // 将电压值转换为千位、百位、十位和个位
        qian = mv / 1000;
        bai = (mv / 100) % 10;
        shi = (mv / 10) % 10;
        ge = mv % 10;

        // 通过串口发送电压值,用于调试
        putc(qian + '0');
        putc(bai + '0');
        putc(shi + '0');
        putc(ge + '0');
        puts(" mV\r\n");

        // 根据当前歌曲索引和音符位置播放音符
        switch (song_index) {
            case 0:
                play_yinfu(song0[play_pos]);
                play_pos++;
                if (play_pos >= sizeof(song0)) {
                    play_pos = 0;  // 一首歌曲播放完毕,重头开始
                }
                break;
            case 1:
                play_yinfu(song1[play_pos]);
                play_pos++;
                if (play_pos >= sizeof(song1)) {
                    play_pos = 0;
                }
                break;
            case 2:
                play_yinfu(song2[play_pos]);
                play_pos++;
                if (play_pos >= sizeof(song2)) {
                    play_pos = 0;
                }
                break;
            case 3:
                play_yinfu(song3[play_pos]);
                play_pos++;
                if (play_pos >= sizeof(song3)) {
                    play_pos = 0;
                }
                break;
        }

        // 使用 ADC 值(mv)调节播放速度,音量越大,播放速度越快
        mdelay(600 - mv / 3);  // 根据音量值调整播放速度
    }

    return 0;
}

第七步:关键函数:延时函数 mdelay

为了实现不同音符的播放速度,我们需要使用一个简单的延时函数。

// 简单的延时函数
void mdelay(int ms) {
    while (ms--) {
        int num = 0x1FFF;  // 延时循环
        while (num--);
    }
}

总结

歌曲数组和音符频率:定义了4首歌曲,并通过 yf[] 数组存储了不同音符对应的频率。play_yinfu() 函数使用 PWM 调节频率,实现音符播放。

按键切换歌曲:handle_button_press() 函数负责检测按键是否按下,并通过 do_irq() 切换当前播放的歌曲。同时对应的 LED 指示灯显示当前播放的歌曲。

ADC 调节音量:ADC 通过旋钮获取电压值,用于调节播放速度。较高的电压值(即较大的旋钮值)会加快播放速度。

串口调试信息输出:通过 UART 发送调试信息,输出当前的 ADC 值(音量信息)和系统状态。

主循环逻辑:主程序不断轮询按键状态和 ADC 值,控制 LED 和播放音符,并根据音量值调节播放速度。


完整代码

// 全局变量定义
char song0[] = {2, 3, 4, 3, 2, 3, 2, 3, 2, 4, 2, 1, 4, 3, 2};  // 两只老虎
char song1[] = {1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1};         // 生日快乐
char song2[] = {4, 4, 5, 5, 6, 6, 7, 7, 6, 6, 5, 5};             // abcdefg
char song3[] = {7, 6, 5, 4, 3, 2, 1};                            // 祝你平安

char yf[] = {0, 191, 172, 159, 144, 135, 120, 107};  // 音符对应的频率表

char song_index = 0;  // 当前播放的歌曲索引
char play_pos = 0;    // 当前音符位置

// LED 和按键的 GPIO 地址(根据实际硬件调整)
#define GPIO_LED1 *(volatile long*)0x11400000  // LED 1 的 GPIO 地址
#define GPIO_LED2 *(volatile long*)0x11400004  // LED 2 的 GPIO 地址
#define GPIO_LED3 *(volatile long*)0x11400008  // LED 3 的 GPIO 地址
#define GPIO_LED4 *(volatile long*)0x1140000C  // LED 4 的 GPIO 地址

#define BUTTON_PIN *(volatile long*)0x11000020  // 按键的 GPIO 地址,用于切换歌曲

// ADC 的 GPIO 地址,用于旋钮控制音量
#define ADCCON   *(volatile long*)0x126C0000  // ADC 控制寄存器
#define ADCDAT   *(volatile long*)0x126C000C  // ADC 数据寄存器
#define ADCMUX   *(volatile long*)0x126C001C  // ADC 多路复用器

// 串口初始化及调试输出相关定义
#define GPA1CON  *(volatile long*)0x11400020  // GPIO A1 控制寄存器
#define ULCON2   *(volatile long*)0x13820000  // UART2 控制寄存器
#define UCON2    *(volatile long*)0x13820004  // UART2 控制寄存器
#define UTRSTAT2 *(volatile long*)0x13820010  // UART2 状态寄存器
#define UTXH2    *(volatile long*)0x13820020  // UART2 发送寄存器
#define UBRDIV2  *(volatile long*)0x13820028  // UART2 波特率分频寄存器
#define UFRACVAL2 *(volatile long*)0x1382002C // UART2 波特率小数部分寄存器

// PWM 定时器相关定义
#define TCFG0    *(volatile long*)0x139D0000  // 定时器配置寄存器 0
#define TCFG1    *(volatile long*)0x139D0004  // 定时器配置寄存器 1
#define TCNTB0   *(volatile long*)0x139D000C  // 定时器计数寄存器,用于设置周期
#define TCMPB0   *(volatile long*)0x139D0010  // 定时器比较寄存器,用于设置占空比
#define TCON     *(volatile long*)0x139D0008  // 定时器控制寄存器

// 串口初始化函数
void uart_init(void) {
    GPA1CON = GPA1CON & ~0xF;
    GPA1CON = GPA1CON | (1 << 1);    // UART TX
    GPA1CON = GPA1CON & ~(0xF << 4);
    GPA1CON = GPA1CON | (1 << 5);    // UART RX

    ULCON2 = 0x03;                   // 8 位数据,无校验,1 位停止位
    UCON2 = 0x05;                    // 轮询模式
    UBRDIV2 = 53;                    // 设置波特率为 115200
    UFRACVAL2 = 4;
}

// 串口发送单个字符
void putc(char ch) {
    while (!(UTRSTAT2 & (1 << 1)));  // 等待发送缓冲区空
    UTXH2 = ch;
}

// 串口发送字符串
void puts(char *s) {
    int i = 0;
    while (s[i]) {
        putc(s[i]);
        i++;
    }
}

// ADC 初始化函数
void adc_init(void) {
    ADCCON |= 1 << 16;  // 12 比特分辨率
    ADCCON |= 1 << 14;  // 使能分频
    ADCCON &= ~(0xFF << 6);
    ADCCON |= 19 << 6;  // 设置分频值
    ADCCON &= ~(1 << 2);  // 禁用空闲模式
    ADCCON |= 1 << 0;  // 启动 ADC
    ADCMUX = 3;  // 使用第 3 个 ADC 通道
}

// 获取 ADC 值并转换为毫伏值
int adc_get_mv(void) {
    int reg = ADCDAT & 0xFFF;
    return reg * 1800 / 4095;  // 将 ADC 数据转换为毫伏
}

// PWM 定时器初始化
void pwm_init(void) {
    // 配置预分频器
    TCFG0 = (TCFG0 & ~(0xFF)) | 99;      // 预分频器1,设置为99+1=100分频
    TCFG1 = (TCFG1 & ~(0xF)) | 0x2;      // 分频器2,设置为PWM模式的1/4分频
    
    // 设置PWM占空比为50%,即一半时间高电平,一半时间低电平
    TCMPB0 = TCNTB0 / 2;                 // 设置比较寄存器,产生50%的占空比
    
    // 设置定时器控制寄存器,启用自动重载并开始PWM输出
    TCON |= (1 << 1);                    // 手动更新 TCNTB0 和 TCMPB0 的值
    TCON &= ~(1 << 1);                   // 清除手动更新位
    TCON |= (1 << 0) | (1 << 3);         // 启用定时器0并启动PWM
}

// 播放音符函数,调整PWM频率以产生不同音符
void play_yinfu(char note) {
    if (note >= 1 && note <= 7) {
        TCNTB0 = yf[note];  // 根据音符调整PWM频率
        TCMPB0 = TCNTB0 / 2;  // 设置50%占空比
        TCON |= (1 << 1);      // 手动更新TCNTB0和TCMPB0的值
        TCON &= ~(1 << 1);     // 清除手动更新位
        TCON |= (1 << 0);      // 启动PWM输出
    }
}

// 切换歌曲和控制灯光的中断处理函数
void do_irq() {
    song_index = (song_index + 1) % 4;  // 切换到下一首歌
    play_pos = 0;  // 从头开始播放

    // 切换灯光逻辑
    switch (song_index) {
        case 0:
            GPIO_LED1 = 1;
            GPIO_LED2 = 0;
            GPIO_LED3 = 0;
            GPIO_LED4 = 0;
            break;
        case 1:
            GPIO_LED1 = 0;
            GPIO_LED2 = 1;
            GPIO_LED3 = 0;
            GPIO_LED4 = 0;
            break;
        case 2:
            GPIO_LED1 = 0;
            GPIO_LED2 = 0;
            GPIO_LED3 = 1;
            GPIO_LED4 = 0;
            break;
        case 3:
            GPIO_LED1 = 0;
            GPIO_LED2 = 0;
            GPIO_LED3 = 0;
            GPIO_LED4 = 1;
            break;
    }

    puts("Song changed!\r\n");  // 通过串口打印调试信息
}

// 定义按键中断
void handle_button_press() {
    if (BUTTON_PIN & 0x01) {  // 假设按键按下触发低电平
        do_irq();  // 处理按键按下,切换歌曲
    }
}

// 简单的延时函数
void mdelay(int ms) {
    while (ms--) {
        int num = 0x1FFF;  // 延时循环
        while (num--);
    }
}

// 主程序
int main(void) {
    int mv;
    int qian, bai, shi, ge;

    uart_init();  // 初始化串口
    adc_init();   // 初始化 ADC
    pwm_init();   // 初始化 PWM

    puts("System initialized!\r\n");

    while (1) {
        // 检查按键是否按下
        handle_button_press();  // 检查是否有按键按下,处理歌曲切换

        // 获取当前的音量值(通过 ADC 读取旋钮值)
        mv = adc_get_mv();  // 获取当前电压值

        // 将电压值转换为千位、百位、十位和个位
        qian = mv / 1000;
        bai = (mv / 100) % 10;
        shi = (mv / 10) % 10;
        ge = mv % 10;

        // 通过串口发送电压值,用于调试
        putc(qian + '0');
        putc(bai + '0');
        putc(shi + '0');
        putc(ge + '0');
        puts(" mV\r\n");

        // 根据当前歌曲索引和音符位置播放音符
        switch (song_index) {
            case 0:
                play_yinfu(song0[play_pos]);
                play_pos++;
                if (play_pos >= sizeof(song0)) {
                    play_pos = 0;  // 一首歌曲播放完毕,重头开始
                }
                break;
            case 1:
                play_yinfu(song1[play_pos]);
                play_pos++;
                if (play_pos >= sizeof(song1)) {
                    play_pos = 0;
                }
                break;
            case 2:
                play_yinfu(song2[play_pos]);
                play_pos++;
                if (play_pos >= sizeof(song2)) {
                    play_pos = 0;
                }
                break;
            case 3:
                play_yinfu(song3[play_pos]);
                play_pos++;
                if (play_pos >= sizeof(song3)) {
                    play_pos = 0;
                }
                break;
        }

        // 使用 ADC 值(mv)调节播放速度,音量越大,播放速度越快
        mdelay(600 - mv / 3);  // 根据音量值调整播放速度
    }

    return 0;
}

相关代码

  1. start.S 去前面章节找一个带有中断的汇编即可
  2. Makefile 和map.lds也在前面有
  3. Linux下执行make 烧录bin文件即可。

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

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

相关文章

10月更新|国内可用的ChatGPT攻略镜像中文网站

一、GPT中文镜像站 ① yixiaai.com 支持GPT4、4o以及o1&#xff0c;支持MJ绘画 ② chat.lify.vip 支持通用全模型&#xff0c;支持文件读取、插件、绘画、AIPPT ③ AI Chat支持GPT3.5/4&#xff0c;4o以及MJ绘画 1. 什么是镜像站 镜像站&#xff08;Mirror Site&#xff0…

【GO基础学习】环境安装到基础语法(1)

文章目录 环境安装GoLand 安装GO基础GO特点类型和函数Init函数和main函数GO命令下划线变量和常量数组切片Slice 引用 环境安装 下载地址&#xff1a;https://www.golangroadmap.com/ 安装目录文件说明&#xff1a; api&#xff1a;每个版本的 api 变更差异。 bin&#xff1…

JAVA 字符串 trim() 方法的正确使用

JAVA类里面 trim() 方法大家都比较熟悉&#xff0c;就是用来清除掉字符串首尾的空白字符。但在一次程序运行崩溃后&#xff0c;查找具体原因时&#xff0c;发现是由字符串末尾的一个回车符号 "\r" 所导致的。于是有机会仔细读了下该方法的 java 文档说明。其中一段内…

Docker理念

1.为什么会出现Docker Docker 的出现并非偶然&#xff0c;而是由一系列技术发展趋势和实际需求所推动的一项技术创新。 随着软件行业的快速发展&#xff0c;开发团队的规模不断扩大&#xff0c;成员可能分布在不同的地理位置&#xff0c;使用不同的操作系统和开发工具。这就导致…

CSD(computational storage devices)架构介绍

CSD&#xff08;computational storage devices&#xff09;架构介绍 前言一、CSD与传统SSD的架构对比二、为什么要采用FPGA三、FPGA缺点四、个人总结reference 前言 虽然一直有接触CSD&#xff0c;但一直对其原理和架构知之甚少&#xff0c;半知不解。今天&#xff0c;趁着我还…

element-ui点击文字查看图片预览功能

今天做一个点击文字查看图片的功能&#xff0c;大体页面长这样子&#xff0c;点击查看显示对应的图片 引入el-image-viewer&#xff0c;点击的文字时候设置图片预览组件显示并传入图片的地址 关键代码 <el-link v-if"scope.row.fileList.length > 0" type&…

模型预测控制工具包——ACADO:简介、安装与测试

模型预测控制工具包——ACADO&#xff1a;简介、安装与测试 ACADO 工具包简介ubuntu20.04 安装 ACADO工具包安装依赖安装ACADOtoolkit 测试 ACADO 工具包简介 ACADO Toolkit 是一个用 C 编写的用于自动控制和动态优化的软件环境和算法集合。 它提供了一个通用框架&#xff0c;…

三菱FX3UPLC定位控制程序举例

测试程序的编写 1.输入输出的分配输入输出的分配如下表所示。 2、相关软元件的设定 相关软元件也有所不同。更改定位指令的脉冲输出端时&#xff0c;根因设定为定位指令的脉冲输出端的软元件不同&#xff0c;据更改的内容&#xff0c;需要变更设定的相关软元件。 3.程…

【大模型新书】掌握大语言模型:高级技术、应用、尖端方法和顶尖LLMs

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/93e5a5c008474f72a0335083ef9c4893.png)我已将 这本大模型书籍免费分享 出来&#xff0c;需要的小伙伴可以扫取。 主要特性 探索自然语言处理&#xff08;NLP&#xff09;基础和大语言模型基本原理&#xff0c;包括…

若依前端后打成一个JAR包部署

客户需要将项目前后端作为一个整体打包成jar&#xff0c;不使用nginx方式转发。使用框架是若依前后端分离&#xff0c;后端springboot&#xff0c;前端vue&#xff0c;目的就是把vue打入jar。 一、前端修改 ruoyi-ui/src/router/index.js文件 &#xff0c;将 mode: ‘history’…

一键生成二维码的源码系统 电脑+手机版自适应代码 带完整的安装代码包以及搭建部署教程

系统概述 一键生成二维码的源码系统是一款集二维码生成、管理和应用于一体的综合性平台。它采用先进的技术和算法&#xff0c;能够快速、准确地生成各种类型的二维码&#xff0c;包括文本、链接、图片等。同时&#xff0c;该系统还具备高度的灵活性和可扩展性&#xff0c;能够…

如何使用bpmn-js实现可视化流程管理

介绍 BPMN-JS是一个流行的开源库&#xff0c;用于在Web应用程序中可视化、创建、编辑和分析BPMN&#xff08;Business Process Model and Notation&#xff0c;业务流程建模与表示法&#xff09;2.0 图。BPMN是一种国际标准的图形化语言&#xff0c;用于描述企业中的业务流程&a…

mongodb 连接, 去重,索引

mongodb 去重,索引 MongoDB Community Server 下载: https://www.mongodb.com/try/download/community GUI: The Ultimate Client, IDE and GUI for MongoDB | Studio 3T 连接 设置允许远程(局域网)连接 (windows) 在打开文件 "<你的安装目录>\MongoDB\Server\…

k3s安装指定版本以及离线安装(docker)

首先下载你所需要版本的k3s安装包&#xff0c;目录结构如下所示&#xff0c;我这里是v1.19.15k3s2。 1.首先赋予可执行权限后进行安装。 # k3s 需要赋予可执行权限 sudo chmod x k3s sudo chmod x k3s-install.sh2.然后将k3s的二进制文件复制到/usr/local/bin/ cp k3s /us…

✨机器学习笔记(七)—— 交叉验证、偏差和方差、学习曲线、数据增强、迁移学习、精确率和召回率

机器学习笔记&#xff08;七&#xff09; 1️⃣评估模型&#x1f397;️使用测试集评估模型&#x1f397;️交叉验证集&#xff08;cross validation&#xff09; 2️⃣偏差和方差&#xff08;Bias / Variance&#xff09;3️⃣学习曲线&#xff08;Learning curves&#xff09…

自动化分析背后,一站式数据分析平台!

自动化分析背后&#xff0c;一站式数据分析平台&#xff01; 前言一站式数据分析平台 前言 在如今的企业管理中&#xff0c;数据已经不再是简单的存储和备份&#xff0c;而是成为了决策的核心驱动力。尤其是在面对海量数据的情况下&#xff0c;企业急需一个能够高效处理、分析…

学习笔记之指针进阶(10.11)

a[0]就相当于数组名arr&#xff0c;a[0]1就相当于arr1&#xff0c;arr1是数组中下一个元素的地址&#xff0c;所以a[0]1就是数组中下一个元素的地址&#xff0c;&#xff08;把二维数组中的每一个数组看作一个元素&#xff09; 以上解释是错误的&#xff0c;a[0]不是整个数组的…

Leetcode——数组:移除元素—27.移除元素

知识点 双指针&#xff0c;在设置时&#xff0c;设置两个指针&#xff0c;一个用来寻找目标值&#xff0c;一个用来表示新数组的下标。 当找到不是目标值的元素时&#xff0c;将其添加到新数组中&#xff0c;如果是目标值&#xff0c;直接掠过 寻找目标值的指针会遍历整个数…

从commit校验失效问题探究husky原理

一、背景 之前创建的项目&#xff0c;发现代码 commit 提交的时候没有了任何校验&#xff0c;具体表现&#xff1a; 一是 feat fix 等主题格式校验没有了二是代码 lint 不通过也能提交 尝试解决这个问题&#xff0c;并深入了解husky的实现原理&#xff0c;将相关的一些知识点…

Excalidraw:在线手绘风格白板、图表绘制工具

嗨&#xff0c;大家好&#xff0c;我是小华同学&#xff0c;关注我们获得“最新、最全、最优质”开源项目和高效工作学习方法 Excalidraw 是一个开源的虚拟白板&#xff0c;用于绘制手绘风格的图表、线框图等。它支持多人实时协作&#xff0c;并使用端到端加密&#xff0c;确保…