# STM32F103 SD卡读写程序

news2025/6/8 9:11:51

下面是一个基于STM32F103系列微控制器的SD卡读写完整程序,使用标准外设库(StdPeriph)和FatFs文件系统。

硬件准备

  • STM32F103C8T6开发板(或其他F103系列)
  • SD卡模块(SPI接口)
  • 连接线缆

硬件连接

SD卡模块  STM32F103
CS   -> PA4 (SPI1_NSS)
SCK  -> PA5 (SPI1_SCK)
MISO -> PA6 (SPI1_MISO)
MOSI -> PA7 (SPI1_MOSI)
VCC  -> 3.3V
GND  -> GND

完整代码

1. 主程序 (main.c)

#include "stm32f10x.h"
#include "ff.h"
#include "diskio.h"
#include "spi_sd.h"
#include <stdio.h>
#include <string.h>

FATFS fs;       /* FatFs文件系统对象 */
FIL fil;        /* 文件对象 */
FRESULT res;    /* FatFs函数返回结果 */
UINT bw;        /* 读写字节数 */

void RCC_Configuration(void);
void GPIO_Configuration(void);
void USART1_Init(void);

int main(void)
{
    char buffer[128];
    
    /* 系统时钟配置 */
    RCC_Configuration();
    
    /* GPIO配置 */
    GPIO_Configuration();
    
    /* USART1初始化 */
    USART1_Init();
    
    printf("STM32F103 SD Card Test\r\n");
    
    /* 挂载文件系统 */
    if(f_mount(&fs, "0:", 1) != FR_OK)
    {
        printf("Mount SD Card Failed!\r\n");
        while(1);
    }
    printf("SD Card Mounted Successfully!\r\n");
    
    /* 打开/创建文件 */
    res = f_open(&fil, "0:test.txt", FA_OPEN_ALWAYS | FA_WRITE | FA_READ);
    if(res != FR_OK)
    {
        printf("Open File Failed!\r\n");
        while(1);
    }
    
    /* 写入数据 */
    f_lseek(&fil, 0);
    f_printf(&fil, "Hello, STM32 SD Card!\r\n");
    f_printf(&fil, "This is a test file.\r\n");
    
    /* 读取数据 */
    f_lseek(&fil, 0);
    while(f_gets(buffer, sizeof(buffer), &fil))
    {
        printf("%s", buffer);
    }
    
    /* 关闭文件 */
    f_close(&fil);
    
    /* 卸载文件系统 */
    f_mount(NULL, "0:", 1);
    
    while(1)
    {
    }
}

void RCC_Configuration(void)
{
    /* 复位RCC时钟配置 */
    RCC_DeInit();
    
    /* 使能外部高速晶振 */
    RCC_HSEConfig(RCC_HSE_ON);
    
    /* 等待HSE就绪 */
    if(RCC_WaitForHSEStartUp() == SUCCESS)
    {
        /* 设置HCLK = SYSCLK */
        RCC_HCLKConfig(RCC_SYSCLK_Div1);
        
        /* 设置PCLK2 = HCLK */
        RCC_PCLK2Config(RCC_HCLK_Div1);
        
        /* 设置PCLK1 = HCLK/2 */
        RCC_PCLK1Config(RCC_HCLK_Div2);
        
        /* 设置FLASH延时 */
        FLASH_SetLatency(FLASH_Latency_2);
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
        
        /* 设置PLL时钟源为HSE, 9倍频 */
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
        
        /* 使能PLL */
        RCC_PLLCmd(ENABLE);
        
        /* 等待PLL就绪 */
        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
        
        /* 设置PLL为系统时钟源 */
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
        
        /* 等待系统时钟源切换完成 */
        while(RCC_GetSYSCLKSource() != 0x08);
    }
    
    /* 使能SPI1时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
    
    /* 使能GPIOA时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    
    /* 使能USART1时钟 */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
}

void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    
    /* 配置SPI1引脚: SCK, MISO, MOSI */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    /* 配置SPI1 CS引脚 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_SetBits(GPIOA, GPIO_Pin_4);  // CS高电平
    
    /* 配置USART1 TX引脚 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    /* 配置USART1 RX引脚 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void USART1_Init(void)
{
    USART_InitTypeDef USART_InitStructure;
    
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    
    USART_Init(USART1, &USART_InitStructure);
    USART_Cmd(USART1, ENABLE);
}

/* 重定向printf到USART1 */
int fputc(int ch, FILE *f)
{
    USART_SendData(USART1, (uint8_t)ch);
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
    return ch;
}

2. SPI和SD卡驱动 (spi_sd.c)

#include "spi_sd.h"
#include "stm32f10x.h"
#include "delay.h"

/* SPI1读写一个字节 */
uint8_t SPI1_ReadWriteByte(uint8_t TxData)
{
    /* 等待发送缓冲区空 */
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
    
    /* 发送数据 */
    SPI_I2S_SendData(SPI1, TxData);
    
    /* 等待接收缓冲区非空 */
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
    
    /* 返回接收到的数据 */
    return SPI_I2S_ReceiveData(SPI1);
}

/* SPI1初始化 */
void SPI1_Init(void)
{
    SPI_InitTypeDef SPI_InitStructure;
    
    /* SPI1配置 */
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    
    SPI_Init(SPI1, &SPI_InitStructure);
    SPI_Cmd(SPI1, ENABLE);
    
    /* CS高电平 */
    SD_CS_HIGH();
}

/* SD卡初始化 */
uint8_t SD_Initialize(void)
{
    uint8_t retry = 0;
    uint8_t i;
    uint8_t buf[4];
    uint16_t count = 0;
    
    /* 初始化SPI */
    SPI1_Init();
    
    /* 延时至少74个时钟周期 */
    SD_CS_HIGH();
    for(i = 0; i < 10; i++)
    {
        SPI1_ReadWriteByte(0xFF);
    }
    
    /* 发送CMD0进入空闲状态 */
    while(SD_SendCmd(CMD0, 0, 0x95) != 0x01)
    {
        retry++;
        if(retry > 100)
        {
            return 1; // 超时
        }
    }
    
    /* 发送CMD8检查SD卡版本 */
    if(SD_SendCmd(CMD8, 0x1AA, 0x87) == 0x01)
    {
        /* SD卡v2.0 */
        for(i = 0; i < 4; i++)
        {
            buf[i] = SPI1_ReadWriteByte(0xFF);
        }
        
        /* 初始化SD卡 */
        while(SD_SendCmd(ACMD41, 0x40000000, 0x01) != 0x00)
        {
            count++;
            if(count > 0xFFFE)
            {
                return 2; // 初始化失败
            }
        }
        
        /* 读取OCR寄存器 */
        if(SD_SendCmd(CMD58, 0, 0x01) != 0x00)
        {
            return 3;
        }
        
        for(i = 0; i < 4; i++)
        {
            buf[i] = SPI1_ReadWriteByte(0xFF);
        }
        
        /* 检查CCS位 */
        if(buf[0] & 0x40)
        {
            CardType = SD_TYPE_V2HC; // SDHC/SDXC
        }
        else
        {
            CardType = SD_TYPE_V2;   // SDv2
        }
    }
    else
    {
        /* SD卡v1.x或MMC */
        if(SD_SendCmd(ACMD41, 0, 0x01) <= 1)
        {
            /* SD卡v1.x */
            CardType = SD_TYPE_V1;
            count = 0;
            
            /* 等待初始化完成 */
            while(SD_SendCmd(ACMD41, 0, 0x01) != 0x00)
            {
                count++;
                if(count > 0xFFFE)
                {
                    return 4; // 初始化失败
                }
            }
        }
        else
        {
            /* MMC卡 */
            CardType = SD_TYPE_MMC;
            count = 0;
            
            /* 等待初始化完成 */
            while(SD_SendCmd(CMD1, 0, 0x01) != 0x00)
            {
                count++;
                if(count > 0xFFFE)
                {
                    return 5; // 初始化失败
                }
            }
        }
    }
    
    /* 设置SPI时钟为高速模式 */
    SPI1_SetSpeed(SPI_BaudRatePrescaler_4);
    
    return 0; // 初始化成功
}

/* 发送SD卡命令 */
uint8_t SD_SendCmd(uint8_t cmd, uint32_t arg, uint8_t crc)
{
    uint8_t res;
    
    /* 等待SD卡准备就绪 */
    SD_WaitReady();
    
    /* 发送命令 */
    SD_CS_LOW();
    SPI1_ReadWriteByte(cmd | 0x40);
    SPI1_ReadWriteByte(arg >> 24);
    SPI1_ReadWriteByte(arg >> 16);
    SPI1_ReadWriteByte(arg >> 8);
    SPI1_ReadWriteByte(arg);
    SPI1_ReadWriteByte(crc);
    
    /* 等待响应 */
    if(cmd == CMD12)
    {
        SPI1_ReadWriteByte(0xFF); // 跳过停止命令后的一个字节
    }
    
    /* 等待响应 */
    uint8_t retry = 0;
    do
    {
        res = SPI1_ReadWriteByte(0xFF);
        retry++;
    } while((res & 0x80) && (retry < 200));
    
    return res;
}

/* 等待SD卡准备就绪 */
uint8_t SD_WaitReady(void)
{
    uint32_t timeout = 0;
    
    do
    {
        if(SPI1_ReadWriteByte(0xFF) == 0xFF)
        {
            return 0;
        }
        timeout++;
    } while(timeout < 0xFFFFFF);
    
    return 1;
}

/* 读取SD卡一个扇区 */
uint8_t SD_ReadDisk(uint8_t *buf, uint32_t sector, uint8_t cnt)
{
    uint8_t res;
    
    if(CardType == SD_TYPE_V2HC)
    {
        sector *= 512; // SDHC/SDXC卡使用字节地址
    }
    
    if(cnt == 1)
    {
        /* 读取单个块 */
        res = SD_SendCmd(CMD17, sector, 0x01);
        if(res == 0)
        {
            /* 等待数据开始标记 */
            if(!SD_RecvData(buf, 512))
            {
                res = 1;
            }
        }
    }
    else
    {
        /* 读取多个块 */
        res = SD_SendCmd(CMD18, sector, 0x01);
        do
        {
            if(!SD_RecvData(buf, 512))
            {
                res = 1;
                break;
            }
            buf += 512;
        } while(--cnt);
        
        /* 发送停止传输命令 */
        SD_SendCmd(CMD12, 0, 0x01);
    }
    
    SD_CS_HIGH();
    SPI1_ReadWriteByte(0xFF);
    return res;
}

/* 接收数据 */
uint8_t SD_RecvData(uint8_t *buf, uint16_t len)
{
    uint16_t i;
    uint8_t res;
    
    /* 等待数据开始标记 */
    uint16_t retry = 0;
    do
    {
        res = SPI1_ReadWriteByte(0xFF);
        retry++;
    } while((res == 0xFF) && (retry < 0xFFFF));
    
    if(res != 0xFE)
    {
        return 1; // 数据开始标记错误
    }
    
    /* 接收数据 */
    for(i = 0; i < len; i++)
    {
        buf[i] = SPI1_ReadWriteByte(0xFF);
    }
    
    /* 接收CRC */
    SPI1_ReadWriteByte(0xFF);
    SPI1_ReadWriteByte(0xFF);
    
    return 0;
}

/* 写入SD卡一个扇区 */
uint8_t SD_WriteDisk(const uint8_t *buf, uint32_t sector, uint8_t cnt)
{
    uint8_t res;
    
    if(CardType == SD_TYPE_V2HC)
    {
        sector *= 512; // SDHC/SDXC卡使用字节地址
    }
    
    if(cnt == 1)
    {
        /* 写入单个块 */
        res = SD_SendCmd(CMD24, sector, 0x01);
        if(res == 0)
        {
            /* 发送数据开始标记 */
            if(!SD_SendData(buf, 0xFE))
            {
                res = 1;
            }
        }
    }
    else
    {
        /* 写入多个块 */
        if(CardType != SD_TYPE_MMC)
        {
            SD_SendCmd(CMD55, 0, 0x01);
            SD_SendCmd(CMD23, cnt, 0x01);
        }
        
        res = SD_SendCmd(CMD25, sector, 0x01);
        if(res == 0)
        {
            do
            {
                if(!SD_SendData(buf, 0xFC))
                {
                    res = 1;
                    break;
                }
                buf += 512;
            } while(--cnt);
            
            /* 发送停止传输标记 */
            if(!SD_SendData(0, 0xFD))
            {
                res = 1;
            }
        }
    }
    
    SD_CS_HIGH();
    SPI1_ReadWriteByte(0xFF);
    return res;
}

/* 发送数据 */
uint8_t SD_SendData(const uint8_t *buf, uint8_t token)
{
    uint16_t i;
    uint8_t res;
    
    /* 等待SD卡准备就绪 */
    SD_WaitReady();
    
    /* 发送数据开始标记 */
    SPI1_ReadWriteByte(token);
    
    /* 发送数据 */
    if(token != 0xFD)
    {
        for(i = 0; i < 512; i++)
        {
            SPI1_ReadWriteByte(buf[i]);
        }
        
        /* 发送CRC */
        SPI1_ReadWriteByte(0xFF);
        SPI1_ReadWriteByte(0xFF);
        
        /* 获取数据响应 */
        res = SPI1_ReadWriteByte(0xFF);
        if((res & 0x1F) != 0x05)
        {
            return 1;
        }
    }
    
    /* 等待SD卡完成写入 */
    SD_WaitReady();
    return 0;
}

/* 设置SPI速度 */
void SPI1_SetSpeed(uint16_t Speed)
{
    SPI_Cmd(SPI1, DISABLE);
    SPI_InitTypeDef SPI_InitStructure;
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler = Speed;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init(SPI1, &SPI_InitStructure);
    SPI_Cmd(SPI1, ENABLE);
}

3. 头文件 (spi_sd.h)

#ifndef __SPI_SD_H
#define __SPI_SD_H

#include "stm32f10x.h"

/* SD卡类型定义 */
#define SD_TYPE_ERR     0x00
#define SD_TYPE_MMC     0x01
#define SD_TYPE_V1      0x02
#define SD_TYPE_V2      0x04
#define SD_TYPE_V2HC    0x06

/* SD卡命令定义 */
#define CMD0    0       // 复位SD卡
#define CMD1    1
#define CMD8    8       // 发送接口条件
#define CMD9    9       // 读取CSD数据
#define CMD10   10      // 读取CID数据
#define CMD12   12      // 停止数据传输
#define CMD16   16      // 设置块大小
#define CMD17   17      // 读取单个块
#define CMD18   18      // 读取多个块
#define CMD23   23      // 设置预擦除块数
#define CMD24   24      // 写入单个块
#define CMD25   25      // 写入多个块
#define CMD41   41      // 发送主机容量支持信息
#define CMD55   55      // 应用特定命令
#define CMD58   58      // 读取OCR寄存器
#define CMD59   59      // 设置CRC开/关
#define ACMD41  0x41    // ACMD41

/* SD卡片选控制 */
#define SD_CS_LOW()     GPIO_ResetBits(GPIOA, GPIO_Pin_4)
#define SD_CS_HIGH()    GPIO_SetBits(GPIOA, GPIO_Pin_4)

/* 全局变量 */
extern uint8_t CardType;

/* 函数声明 */
uint8_t SD_Initialize(void);
uint8_t SD_SendCmd(uint8_t cmd, uint32_t arg, uint8_t crc);
uint8_t SD_WaitReady(void);
uint8_t SD_ReadDisk(uint8_t *buf, uint32_t sector, uint8_t cnt);
uint8_t SD_WriteDisk(const uint8_t *buf, uint32_t sector, uint8_t cnt);
uint8_t SD_RecvData(uint8_t *buf, uint16_t len);
uint8_t SD_SendData(const uint8_t *buf, uint8_t token);
void SPI1_Init(void);
uint8_t SPI1_ReadWriteByte(uint8_t TxData);
void SPI1_SetSpeed(uint16_t Speed);

#endif

4. FatFs磁盘接口 (diskio.c)

#include "diskio.h"
#include "spi_sd.h"

/* 获取磁盘状态 */
DSTATUS disk_status(BYTE pdrv)
{
    return 0;
}

/* 初始化磁盘 */
DSTATUS disk_initialize(BYTE pdrv)
{
    if(SD_Initialize() == 0)
    {
        return 0;
    }
    return STA_NOINIT;
}

/* 读取扇区 */
DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count)
{
    if(SD_ReadDisk(buff, sector, count) == 0)
    {
        return RES_OK;
    }
    return RES_ERROR;
}

/* 写入扇区 */
DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count)
{
    if(SD_WriteDisk(buff, sector, count) == 0)
    {
        return RES_OK;
    }
    return RES_ERROR;
}

/* 其他控制命令 */
DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
{
    switch(cmd)
    {
        case CTRL_SYNC:
            return RES_OK;
            
        case GET_SECTOR_COUNT:
            *(DWORD*)buff = 1024*1024; // 假设SD卡容量为512MB
            return RES_OK;
            
        case GET_SECTOR_SIZE:
            *(WORD*)buff = 512;
            return RES_OK;
            
        case GET_BLOCK_SIZE:
            *(DWORD*)buff = 8;
            return RES_OK;
            
        default:
            return RES_PARERR;
    }
}

5. 头文件 (diskio.h)

#ifndef _DISKIO
#define _DISKIO

#include "integer.h"

/* 状态码 */
#define STA_NOINIT      0x01    /* 驱动器未初始化 */
#define STA_NODISK      0x02    /* 无介质 */
#define STA_PROTECT     0x04    /* 写保护 */

/* 命令码 */
#define CTRL_SYNC       0       /* 完成挂起的写入过程 */
#define GET_SECTOR_COUNT 1      /* 获取扇区数 */
#define GET_SECTOR_SIZE 2       /* 获取扇区大小 */
#define GET_BLOCK_SIZE  3       /* 获取擦除块大小 */
#define CTRL_POWER      4       /* 控制电源状态 */
#define CTRL_LOCK       5       /* 锁定/解锁介质移除 */
#define CTRL_EJECT      6       /* 弹出介质 */
#define MMC_GET_TYPE    10      /* 获取卡类型 */
#define MMC_GET_CSD     11      /* 读取CSD */
#define MMC_GET_CID     12      /* 读取CID */
#define MMC_GET_OCR     13      /* 读取OCR */
#define MMC_GET_SDSTAT  14      /* 读取SD状态 */

/* 结果码 */
typedef enum {
    RES_OK = 0,         /* 成功 */
    RES_ERROR,          /* 读写错误 */
    RES_WRPRT,          /* 写保护 */
    RES_NOTRDY,         /* 设备未就绪 */
    RES_PARERR          /* 无效参数 */
} DRESULT;

/* 函数声明 */
DSTATUS disk_initialize(BYTE pdrv);
DSTATUS disk_status(BYTE pdrv);
DRESULT disk_read(BYTE pdrv, BYTE *buff, DWORD sector, UINT count);
DRESULT disk_write(BYTE pdrv, const BYTE *buff, DWORD sector, UINT count);
DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff);

#endif

使用说明

  1. 将上述代码分别保存到对应的文件中
  2. 创建一个新的STM32工程,添加这些文件
  3. 需要包含FatFs文件系统(可以从官网http://elm-chan.org/fsw/ff/00index_e.html下载)
  4. 编译并下载到STM32F103开发板
  5. 连接SD卡模块
  6. 通过串口调试工具(如Putty)查看输出结果

功能说明

这个程序实现了以下功能:

  1. 初始化SD卡(支持SDv1, SDv2和SDHC卡)
  2. 挂载FAT文件系统
  3. 创建/打开文件"test.txt"
  4. 向文件写入两行文本
  5. 从文件读取内容并通过串口输出
  6. 关闭文件并卸载文件系统

注意事项

  1. 确保SD卡已格式化为FAT16或FAT32文件系统
  2. 如果使用不同的SPI引脚,需要修改GPIO配置
  3. SD卡工作电压为3.3V,不要使用5V电压
  4. 如果读写失败,可以尝试降低SPI时钟速度

希望这个完整的SD卡读写程序对你有帮助!

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

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

相关文章

微软PowerBI考试 PL300-使用适用于 Power BI 的 Copilot 创建交互式报表

微软PowerBI考试 PL300-使用适用于 Power BI 的 Copilot 创建交互式报表 Microsoft Power BI 可帮助您通过交互式报表准备数据并对数据进行可视化。 如果您是 Power BI 的新用户&#xff0c;可能很难知道从哪里开始&#xff0c;并且创建报表可能很耗时。 通过适用于 Power BI …

Prompt提示工程指南#Kontext图像到图像

重要提示&#xff1a;单个prompt的最大token数为512 # 核心能力 Kontext图像编辑系统能够&#xff1a; 理解图像上下文语义实现精准的局部修改保持原始图像风格一致性支持复杂的多步迭代编辑 # 基础对象修改 示例场景&#xff1a;改变汽车颜色 Prompt设计&#xff1a; Change …

产品经理课程(十一)

&#xff08;一&#xff09;复习 1、用户需求不等于产品需求&#xff0c;挖掘用户的本质需求 2、功能设计的前提&#xff1a;不违背我们的产品的基础定位&#xff08;用一句话阐述我们的产品&#xff1a;工具&#xff1a;产品画布&#xff09; 3、判断设计好坏的标准&#xf…

Moldflow充填分析设置

1. 如何选择注塑机&#xff1a; 注塑机初选按注射量来选择&#xff1a; 点网格统计;选择三角形, 三角形体积就是产品的体积 47.7304 cm^3 点网格统计;选择柱体, 柱体的体积就是浇注系统的体积2.69 cm^3 所以总体积产品体积浇注系统体积 47.732.69 cm^3 材料的熔体密度与固体…

Imprompter: Tricking LLM Agents into Improper Tool Use

原文&#xff1a;Imprompter: Tricking LLM Agents into Improper Tool Use 代码&#xff1a;Reapor-Yurnero/imprompter: Codebase of https://arxiv.org/abs/2410.14923 实机演示&#xff1a;Imprompter 摘要&#xff1a; 新兴发展的Agent可以将LLM与外部资源工具相结合&a…

【大模型:知识图谱】--3.py2neo连接图数据库neo4j

【图数据库】--Neo4j 安装_neo4j安装-CSDN博客 需要打开图数据库Neo4j&#xff0c; neo4j console 目录 1.图数据库--连接 2.图数据库--操作 2.1.创建节点 2.2.删除节点 2.3.增改属性 2.4.建立关系 2.5.查询节点 2.6.查询关系 3.图数据库--实例 1.图数据库--连接 fr…

如何理解机器人课程的技术壁垒~壁垒和赚钱是两件不同的事情

答疑&#xff1a; 有部分朋友私聊说博客内容&#xff0c;越来越不适合人类阅读习惯…… 可以做这种理解&#xff0c;我从23年之后&#xff0c;博客会不会就是写给机器看的。 或者说我在以黑盒方式测试AI推荐的风格。 主观-客观-主观螺旋式发展过程。 2015最早的一篇博客重…

selinux firewalld

一、selinux 1.说明 SELinux 是 Security-Enhanced Linux 的缩写&#xff0c;意思是安全强化的 linux&#xff1b; SELinux 主要由美国国家安全局&#xff08;NSA&#xff09;开发&#xff0c;当初开发的目的是为了避免资源的误用 DAC&#xff08;Discretionary Access Cont…

408第一季 - 数据结构 - 字符串和KMP算法

闲聊 这章属于难点但考频低 3个名词记一下&#xff1a;模式匹配&#xff0c;主串&#xff0c;字串&#xff08;模式串&#xff09; 举个例子 主串 aabaaaabaab 字串 aabaab 模式匹配 从主串找到字串 暴力解法 也是不多说 很暴力就是了 KMP算法 next数组 它只和字串有关 先…

如何查看自己电脑安装的Java——JDK

开始->运行->然后输入cmd进入dos界面 &#xff08;快捷键windows->输入cmd&#xff09; 输入java -version&#xff0c;回车 出现了一下信息就是安装了jdk 输入java -verbose&#xff0c;回车 查看安装目录

电力系统时间同步系统之三

2.6 电力系统时间同步装置 时间同步装置主要完成时间信号和时间信息的同步传递&#xff0c;并提供相应的时间格式和物理接口。时间同步装置主要由三大部分组成&#xff1a;时间输入、内部时钟和时间输出&#xff0c;如图 2-25 所示。输入装置的时间信号和时间信息的精度必须不…

火语言RPA--界面应用详解

新建一个界面应用后&#xff0c;软件将自动弹出一个界面设计器&#xff0c;本篇将介绍下流程设计器中各部分的功能。 UI控件列表 显示软件中自带的所有UI控件流程库 流程是颗粒组件的容器&#xff0c;可在建立的流程中添加颗粒组件编写成规则流程。 流程编辑好后再绑定UI控件…

基于Spring Boot的云音乐平台设计与实现

基于Spring Boot的云音乐平台设计与实现——集成协同过滤推荐算法的全栈项目实战 &#x1f4d6; 文章目录 项目概述技术选型与架构设计数据库设计后端核心功能实现推荐算法设计与实现前端交互设计系统优化与性能提升项目部署与测试总结与展望 项目概述 &#x1f3af; 项目背…

Neovim - 打造一款属于自己的编辑器(一)

文章目录 前言&#xff08;劝退&#xff09;neovim 安装neovim 配置配置文件位置第一个 hello world 代码拆分 neovim 配置正式配置 neovim基础配置自定义键位Lazy 插件管理器配置tokyonight 插件配置BufferLine 插件配置自动补全括号 / 引号 插件配置 前言&#xff08;劝退&am…

RAG检索系统的两大核心利器——Embedding模型和Rerank模型

在RAG系统中&#xff0c;有两个非常重要的模型一个是Embedding模型&#xff0c;另一个则是Rerank模型&#xff1b;这两个模型在RAG中扮演着重要角色。 Embedding模型的作用是把数据向量化&#xff0c;通过降维的方式&#xff0c;使得可以通过欧式距离&#xff0c;余弦函数等计算…

CLion社区免费后,使用CLion开发STM32相关工具资源汇总与入门教程

Clion下载与配置 Clion推出社区免费&#xff0c;就是需要注册一个账号使用&#xff0c;大家就不用去找破解版版本了&#xff0c;jetbrains家的IDEA用过的都说好&#xff0c;这里嵌入式领域也推荐使用。 CLion官网下载地址 安装没有什么特别&#xff0c;下一步就好。 启动登录…

第21讲、Odoo 18 配置机制详解

Odoo 18 配置机制详解&#xff1a;res.config.settings 与 ir.config_parameter 原理与实战指南 在现代企业信息化系统中&#xff0c;灵活且可维护的系统参数配置是模块开发的核心能力之一。Odoo 作为一款高度模块化的企业管理软件&#xff0c;其参数配置机制主要依赖于两个关…

【计算机网络】Linux下简单的TCP服务器(超详细)

服务端 创建套接字 &#x1f4bb;我们将TCP服务器封装成一个类&#xff0c;当我们定义出一个服务器对象后需要马上对服务器进行初始化&#xff0c;而初始化TCP服务器要做的第一件事就是创建套接字。 TCP服务器在调用socket函数创建套接字时&#xff0c;参数设置如下&#xff1…

最新Spring Security实战教程(十七)企业级安全方案设计 - 多因素认证(MFA)实现

&#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Micro麦可乐的博客 &#x1f425;《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程&#xff0c;入门到实战 &#x1f33a;《RabbitMQ》…

html+css+js趣味小游戏~Cookie Clicker放置休闲(附源码)

下面是一个简单的记忆卡片配对游戏的完整代码&#xff0c;使用HTML、CSS和JavaScript实现&#xff1a; html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"wid…