基于STM32+VS1053B的MP3设计

news2024/11/16 18:05:37

目录

一、整体介绍

二、模块介绍

1.     stm32主控

2.     VS1053B音频解码

3.     按键

4.     OLED显示

 三、程序代码:

资料下载地址:基于STM32+VS1053B的MP3设计

一、整体介绍

话不多说,先看看整体原理图:

制作出来的实物图如下: 

  整体上,分为四个部分:
(1)    STM32主控部分;
(2)    VS1053B音频解码部分;
(3)    按键控制部分;
(4)    OLED显示部分;
 上电,通过一系列的测试和检测后,进入音乐播放界面,如图:
第一排显示的是标签,
第二行,显示的是当前播放歌曲的索引、总歌曲数目以及当前声音大小,
第三行,显示的是当前歌曲的播放进度以及位率,
第四行,显示的是当前歌曲名(因为没有取字库,所以我就把他翻译成了英文,肯定是不准确的,主要目的只是提示自己)。
此外,通过按键,可以对播放歌曲进行切换和音量的控制。
下面我们来分别看看这四个部分:

二、模块介绍

1.     stm32主控

这里我们使用的是stm32F103VET6,内部Flash有512K,100pin的外部引脚,属于大容量芯片,足够我们diy。对于本设计,stm32这一块用到的知识点有:SDIO驱动SD卡,SPI驱动VS1053B芯片,IIC驱动OLED;对于程序,用的是stm32标准库,小伙伴们可以根据自己的需要,自行决定是否需要补一下相关方面的知识。
主控就不再多做介绍了,因为太常见了,这里只是提一下。

2.     VS1053B音频解码

这一部分的原理图如图:

 

VS1053B,是一款功能比较强大的音频解码芯片,该芯片可以实现对MP3/OGG/WMA/FLAC/WAV/AAC/MIDI等音频格式的解码,同时还可以支持ADPCM/OGG等格式的编码,经过我的测试,建议大家用最常用的.MP3 格式的音乐文件;
具体的介绍,请看资料里面的资料手册,那里说的很清楚,我再多说,显得就很尴尬了。

3.     按键

这个常见到不能再常见了,因为需要按键对歌曲进行切换和音量大小的控制,所以,这里只是简单的把他列出来而已。

4.     OLED显示

OLED只是用来显示提示的作用,这里我们用的是0.96寸4pin的IIC驱动的OLED,也是非常常见的玩意儿,不清楚使用的,可以看看相关的资料。

 三、程序代码:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"                       
#include "oled.h"
#include "bmp.h"
#include "key.h"      
#include "malloc.h"
#include "sdio_sdcard.h"  
#include "vs10xx.h"
#include "mp3player.h"
#include "exfuns.h"
//通过串口打印SD卡相关信息
void show_sdcard_info(void)
{
         switch(SDCardInfo.CardType)
         {
                  caseSDIO_STD_CAPACITY_SD_CARD_V1_1:printf("Card Type:SDSCV1.1\r\n");break;
                  caseSDIO_STD_CAPACITY_SD_CARD_V2_0:printf("Card Type:SDSCV2.0\r\n");break;
                  caseSDIO_HIGH_CAPACITY_SD_CARD:printf("Card Type:SDHC V2.0\r\n");break;
                  caseSDIO_MULTIMEDIA_CARD:printf("Card Type:MMC Card\r\n");break;
         }      
      printf("Card ManufacturerID:%d\r\n",SDCardInfo.SD_cid.ManufacturerID);    //制造商ID
        printf("CardRCA:%d\r\n",SDCardInfo.RCA);                 //卡相对地址
         printf("CardCapacity:%d MB\r\n",(u32)(SDCardInfo.CardCapacity>>20));        //显示容量
        printf("CardBlockSize:%d\r\n\r\n",SDCardInfo.CardBlockSize);                          //显示块大小
}
intmain(void)
{      
         delay_init();                   //延时函数初始化         
         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
         uart_init(115200);          //串口初始化为115200
        LED_Init();                               //初始化与LED连接的硬件接口
         KEY_Init();                                  //初始化按键
         VS_Init();                         //初始化VS1053
         delay_ms(1000);   //适当延时
         OLED_Init();   //OLED初始化
         OLED_ColorTurn(0);//0正常显示,1 反色显示
         OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示
         OLED_Refresh();  
         delay_ms(1000);   //适当延时
         my_mem_init(SRAMIN);                  //初始化内部内存池
         exfuns_init();                             //为fatfs相关变量申请内存  
        f_mount(fs[0],"0:",1);            //挂载SD卡
        f_mount(fs[1],"1:",1);            //挂载FLASH.
        while(SD_Init())//检测不到SD卡
         {
                  OLED_ShowString(0,0,"SD_ERROR!!",16);    //错误提示信息闪烁
                  delay_ms(200);
                  OLED_ShowString(0,0,"          ",16);
                  delay_ms(200);
                  LED1=!LED1;//DS1闪烁
         }
         show_sdcard_info();       //打印SD卡相关信息
         //检测SD卡成功
         OLED_ShowString(0,0,"SD_OK      ",16);         
         delay_ms(1000);
         OLED_ShowString(0,0,"LHSMD- MP3",16);
         while(1)
         {
                  LED1=0;
                  OLED_ShowString(0,16,"storagetest",16);
                  printf("RamTest:0X%04X\r\n",VS_Ram_Test());//打印RAM测试结果
                  OLED_ShowString(0,16,"sintest    ",16);
                  VS_Sine_Test();   //正弦波测试
                  delay_ms(1000);
                  LED1=1;
                  OLED_Clear();
                  OLED_ShowString(0,0,"  LHSMD - MP3",16);
                  mp3_play();  //放歌操作
         }   
}
mp3player.c文件:
#include "mp3player.h"
#include "vs10xx.h"         
#include "delay.h"
#include "led.h"
#include "key.h"
//#include "lcd.h"            
#include "malloc.h"
//#include "text.h"
#include "string.h"
#include "exfuns.h"  
#include "ff.h"   
#include "flac.h"     
#include "usart.h"   
#include "oled.h"
//显示曲目索引
//index:当前索引
//total:总文件数
void mp3_index_show(u16 index,u16 total)
{
         //显示当前曲目的索引,及总曲目数
         OLED_ShowNum(0,16,index,3,16);
         OLED_ShowString(24,16,"/",16);  
         OLED_ShowNum(32,16,total,3,16);
}
//显示当前音量
void mp3_vol_show(u8 vol)
{                                      
         OLED_ShowString(64,16,"VOL:",16);   
         OLED_ShowNum(105,16,vol,2,16);       //显示音量
}
u8 time_buf[16];
u16 f_kbps=0;//歌曲文件位率     
//显示播放时间,比特率 信息
//lenth:歌曲总长度
void mp3_msg_show(u32 lenth)
{      
         staticu16 playtime=0;//播放时间标记            
        u16 time=0;// 时间变量
         u16sec=0;// 时间变量
         u16temp=0;   
         if(f_kbps==0xffff)//未更新过
         {
                  playtime=0;
                  f_kbps=VS_Get_HeadInfo();     //获得比特率
         }               
         time=VS_Get_DecodeTime();//得到解码时间
         if(playtime==0)playtime=time;
         elseif((time!=playtime)&&(time!=0))//1s时间到,更新显示数据
         {
                  playtime=time;//更新时间                                       
                  temp=VS_Get_HeadInfo();//获得比特率                                    
                  if(temp!=f_kbps)
                  {
                          f_kbps=temp;//更新KBPS                                          
                  }                          
                  if(f_kbps)sec=(lenth/f_kbps)/125;//得到秒钟数(文件长度(字节)/(1000/8)/比特率=持续秒钟数
                  elsesec=0;//非法位率                  
                  //显示播放时间     
                  sprintf((char*)time_buf,"%02d:%02d/%02d:%02d%003d",time/60,time%60,sec/60,sec%60,f_kbps);
                  OLED_ShowString(0,32,time_buf,16);
                  LED1=!LED1;            //DS0翻转
         }            
}                                         
//得到path路径下,目标文件的总个数
//path:路径               
//返回值:总有效文件数
u16 mp3_get_tnum(u8 *path)
{         
         u8res;
         u16rval=0;
        DIR tdir;                  //临时目录
         FILINFOtfileinfo;    //临时文件信息            
         u8*fn;                                                                          
   res=f_opendir(&tdir,(const TCHAR*)path); //打开目录
      tfileinfo.lfsize=_MAX_LFN*2+1;                                                //长文件名最大长度
         tfileinfo.lfname=mymalloc(SRAMIN,tfileinfo.lfsize);   //为长文件缓存区分配内存
         if(res==FR_OK&&tfileinfo.lfname!=NULL)
         {
                  while(1)//查询总的有效文件数
                  {
                res=f_readdir(&tdir,&tfileinfo);                       //读取目录下的一个文件
                if(res!=FR_OK||tfileinfo.fname[0]==0)break;      //错误了/到末尾了,退出               
                    fn=(u8*)(*tfileinfo.lfname?tfileinfo.lfname:tfileinfo.fname);                       
                          res=f_typetell(fn);  
                          if((res&0XF0)==0X40)//取高四位,看看是不是音乐文件   
                          {
                                   rval++;//有效文件数增加1
                          }         
                  }  
         }
         myfree(SRAMIN,tfileinfo.lfname);
         returnrval;
}
//播放音乐
void mp3_play(void)
{
         u8res;
        DIR mp3dir;                     //目录
         FILINFOmp3fileinfo;//文件信息
         u8*fn;                           //长文件名
         u8*pname;                      //带路径的文件名
         u16totmp3num;            //音乐文件总数
         u16curindex;           //图片当前索引
         u8key;                               //键值               
        u16 temp;
         u16*mp3indextbl; //音乐索引表
        while(f_opendir(&mp3dir,"0:/music"))//打开图片文件夹
        {           
                  OLED_ShowString(0,32,"musicfile ERR!",16);            
delay_ms(200);      
                  OLED_ShowString(0,32,"               ",16);
                  delay_ms(200);               
         }                                                                             
         totmp3num=mp3_get_tnum("0:/music");//得到总有效文件数
      while(totmp3num==NULL)//音乐文件总数为0         
        {           
                  OLED_ShowString(0,32,"nomusic file  ",16); //没有音乐文件提示
                  delay_ms(200);                                                            
         }                                                                                         
      mp3fileinfo.lfsize=_MAX_LFN*2+1;                                                  //长文件名最大长度
         mp3fileinfo.lfname=mymalloc(SRAMIN,mp3fileinfo.lfsize);       //为长文件缓存区分配内存
        pname=mymalloc(SRAMIN,mp3fileinfo.lfsize);    //为带路径的文件名分配内存
        mp3indextbl=mymalloc(SRAMIN,2*totmp3num);        //申请2*totmp3num个字节的内存,用于存放音乐文件索引
        while(mp3fileinfo.lfname==NULL||pname==NULL||mp3indextbl==NULL)//内存分配出错
        {           
                  OLED_ShowString(0,32,"storageERR    ",16);
                  delay_ms(200);                                                   
         }     
         VS_HD_Reset();    //VS1053硬复位
         VS_Soft_Reset();  //VS1053软复位
         vsset.mvol=200;                                                 //默认设置音量为200.
         mp3_vol_show((vsset.mvol-100)/5);    //音量限制在:100~250,显示的时候,按照公式(vol-100)/5,显示,也就是0~30   
         //记录索引
   res=f_opendir(&mp3dir,"0:/music"); //打开目录
         if(res==FR_OK)
         {
                  curindex=0;//当前索引为0
                  while(1)//全部查询一遍
                  {
                          temp=mp3dir.index;                                                                     //记录当前index
                res=f_readdir(&mp3dir,&mp3fileinfo);                  //读取目录下的一个文件
                if(res!=FR_OK||mp3fileinfo.fname[0]==0)break;        //错误了/到末尾了,退出               
                    fn=(u8*)(*mp3fileinfo.lfname?mp3fileinfo.lfname:mp3fileinfo.fname);                     
                          res=f_typetell(fn);  
                          if((res&0XF0)==0X40)//取高四位,看看是不是音乐文件   
                          {
                                   mp3indextbl[curindex]=temp;//记录索引
                                   curindex++;
                          }         
                  }
         }   
     curindex=0;                                                                                             //从0开始显示
     res=f_opendir(&mp3dir,(constTCHAR*)"0:/music");  //打开目录
         while(res==FR_OK)//打开成功
         {      
                  dir_sdi(&mp3dir,mp3indextbl[curindex]);                       //改变当前目录索引      
       res=f_readdir(&mp3dir,&mp3fileinfo);                  //读取目录下的一个文件
       if(res!=FR_OK||mp3fileinfo.fname[0]==0)break;        //错误了/到末尾了,退出
           fn=(u8*)(*mp3fileinfo.lfname?mp3fileinfo.lfname:mp3fileinfo.fname);                     
                  strcpy((char*)pname,"0:/music/");                                  //复制路径(目录)
                  strcat((char*)pname,(constchar*)fn);                          //将文件名接在后面
                OLED_ShowString(0,48,"                ",16);     //清楚之前的显示
                  OLED_ShowString(0,48,fn,16);                                //显示歌曲名字
                  mp3_index_show(curindex+1,totmp3num);
                  key=mp3_play_song(pname);                                                //播放这个MP3   
                  if(key==2)                 //上一曲
                  {
                          if(curindex)curindex--;
                          elsecurindex=totmp3num-1;
                }else if(key<=1)//下一曲
                  {
                          curindex++;                  
                          if(curindex>=totmp3num)curindex=0;//到末尾的时候,自动从头开始
                }else break;     //产生了错误         
         }                                                                                               
         myfree(SRAMIN,mp3fileinfo.lfname);  //释放内存                          
         myfree(SRAMIN,pname);                                 //释放内存                          
         myfree(SRAMIN,mp3indextbl);                       //释放内存      
}
//播放一曲指定的歌曲                                                                                                                                       
//返回值:0,正常播放完成
//              1,下一曲
//      2,上一曲
//      0XFF,出现错误了
u8 mp3_play_song(u8 *pname)
{      
        FIL* fmp3;
   u16 br;
         u8res,rval;        
         u8*databuf;                    
         u16i=0;
         u8key;               
                             
         rval=0;         
         fmp3=(FIL*)mymalloc(SRAMIN,sizeof(FIL));//申请内存
         databuf=(u8*)mymalloc(SRAMIN,4096);               //开辟4096字节的内存区域
         if(databuf==NULL||fmp3==NULL)rval=0XFF;//内存申请失败.
         if(rval==0)
         {         
               VS_Restart_Play();                                           //重启播放
                  VS_Set_All();                                              //设置音量等信息                          
                  VS_Reset_DecodeTime();                                          //复位解码时间     
                  res=f_typetell(pname);                                   //得到文件后缀                                                                                       
                  if(res==0x4c)//如果是flac,加载patch
                  {      
                          VS_Load_Patch((u16*)vs1053b_patch,VS1053B_PATCHLEN);
                  }                                                                                                                  
                  res=f_open(fmp3,(constTCHAR*)pname,FA_READ);//打开文件        
                if(res==0)//打开成功.
                  {
                          VS_SPI_SpeedHigh();      //高速                                                   
                          while(rval==0)
                          {
                                   res=f_read(fmp3,databuf,4096,(UINT*)&br);//读出4096个字节  
                                   i=0;
                                   do//主播放循环
                              {     
                                            if(VS_Send_MusicData(databuf+i)==0)//给VS10XX发送音频数据
                                            {
                                                     i+=32;
                                            }else   
                                            {
                                                     key=KEY_Scan(0);
                                                     switch(key)
                                                     {
                                                             caseKEY1_PRES:
                                                                      rval=1;              //下一曲
                                                                      break;
                                                             caseKEY3_PRES:
                                                                      rval=2;              //上一曲
                                                                      break;
                                                             caseKEY2_PRES:    //音量增加
                                                                      if(vsset.mvol<250)
                                                                      {
                                                                               vsset.mvol+=5;
                                                                              VS_Set_Vol(vsset.mvol);         
                                                                      }elsevsset.mvol=250;
                                                                      mp3_vol_show((vsset.mvol-100)/5);//音量限制在:100~250,显示的时候,按照公式(vol-100)/5,显示,也就是0~30   
                                                                      break;
                                                             caseKEY4_PRES:    //音量减
                                                                      if(vsset.mvol>100)
                                                                      {
                                                                               vsset.mvol-=5;
                                                                              VS_Set_Vol(vsset.mvol);         
                                                                       }else vsset.mvol=100;
                                                                      mp3_vol_show((vsset.mvol-100)/5);    //音量限制在:100~250,显示的时候,按照公式(vol-100)/5,显示,也就是0~30   
                                                                      break;
                                                     }
                                                     mp3_msg_show(fmp3->fsize);//显示信息      
                                            }                       
                                   }while(i<4096);//循环发送4096个字节
                                   if(br!=4096||res!=0)
                                   {
                                            rval=0;
                                            break;//读完了.               
                                   }                                                           
                          }
                          f_close(fmp3);
                  }elserval=0XFF;//出现错误         
         }                                                               
         myfree(SRAMIN,databuf);                                    
         myfree(SRAMIN,fmp3);
         returnrval;                                      
}

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

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

相关文章

vulnhub----natraj靶机

文章目录 一.信息收集1.网段探测2.端口扫描3.版本服务探测4.漏扫5.目录扫描 二.漏洞利用1.分析信息2..fuzz工具 三.getshell四.提权六.nmap提权 一.信息收集 1.网段探测 因为使用的是VMware&#xff0c;靶机的IP地址是192.168.9.84 ┌──(root㉿kali)-[~/kali/vulnhub] └─…

嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记14:PWM捕获

系列文章目录 嵌入式|蓝桥杯STM32G431&#xff08;HAL库开发&#xff09;——CT117E学习笔记01&#xff1a;赛事介绍与硬件平台 嵌入式|蓝桥杯STM32G431&#xff08;HAL库开发&#xff09;——CT117E学习笔记02&#xff1a;开发环境安装 嵌入式|蓝桥杯STM32G431&#xff08;…

SQLite的架构(十一)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLite下一代查询规划器(十&#xff09; 下一篇&#xff1a;SQLite—系列文章目录 介绍 本文档介绍SQLite库的架构。 这里的信息对那些想要了解或 修改SQLite的内部工作原理。 接口SQL 命令处理器虚拟机B-树…

深入理解npm常用命令

npm&#xff08;Node Package Manager&#xff09;是 Node.js 的包管理工具&#xff0c;用于管理 Node.js 应用程序的依赖包。除了安装、更新和卸载依赖包外&#xff0c;npm 还提供了许多其他功能&#xff0c;如初始化项目、运行脚本、查看依赖树等。本文将详细介绍一些常用的 …

阿里云弹性计算通用算力型u1实例性能评测,性价比高

阿里云服务器u1是通用算力型云服务器&#xff0c;CPU采用2.5 GHz主频的Intel(R) Xeon(R) Platinum处理器&#xff0c;ECS通用算力型u1云服务器不适用于游戏和高频交易等需要极致性能的应用场景及对业务性能一致性有强诉求的应用场景(比如业务HA场景主备机需要性能一致)&#xf…

续二叉搜索树递归玩法

文章目录 一、插入递归二、寻找递归&#xff08;非常简单&#xff0c;走流程就行&#xff09;三、插入递归&#xff08;理解起来比较麻烦&#xff09; 先赞后看&#xff0c;养成习惯&#xff01;&#xff01;&#xff01;^ _ ^<3 ❤️ ❤️ ❤️ 码字不易&#xff0c;大家的…

将 Elasticsearch 向量数据库引入到数据上的 Azure OpenAI 服务(预览)

作者&#xff1a;来自 Elastic Aditya Tripathi Microsoft 和 Elastic 很高兴地宣布&#xff0c;全球下载次数最多的向量数据库 Elasticsearch 是公共预览版中 Azure OpenAI Service On Your Data 官方支持的向量存储和检索增强搜索技术。 这项突破性的功能使你能够利用 GPT-4 …

Android MediaRecorder

AndroidManifest.xml中添加权限标记 <uses-permission android:name"android.permission.RECORD_AUDIO"/> 动态添加权限MainActivity requestPermissions(new String[]{Manifest.permission.CAMERA,Manifest.permission.RECORD_AUDIO},100); 创建MediaReco…

阿里云服务器ECS经济型e实例优惠价格99元一年

阿里云服务器99元一年配置为云服务器ECS经济型e实例&#xff0c;2核2G配置、3M固定带宽和40G ESSD Entry系统盘&#xff0c;新用户和老用户均可买&#xff0c;续费不涨价依旧是99元一年&#xff0c;阿里云服务器网aliyunfuwuqi.com来详细说下阿里云99元服务器性能测评&#xff…

ST表---算法

相当于二分的思想&#xff0c;一直比较最值 ST的创建 现在创建成功&#xff0c;是应该如何查询的问题 ST表的查询 虽然这两区间有重叠&#xff0c;但是可以一个往前数&#xff0c;一个往后数&#xff0c;互不影响 时间复杂度 创建st表的复杂度为n*logn 使用时的复杂度为O(…

Vol.34 Good Men Project:一个博客网站,每月90万访问量,通过付费订阅和广告变现

今天给大家分享的案例网站是&#xff1a;Good Men Project&#xff0c;这是一个专门针对男性成长的博客网站&#xff0c;内容包括人际关系、家庭、职业发展等话题。 它的网址是&#xff1a;The Good Men Project - The Conversation No One Else Is Having 流量情况 我们先看…

【c/c++】深入探秘:C++内存管理的机制

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好&#xff0c;本篇文章我们详细讲解c中的动态内存管理 目录 1.C/C内存分布2.C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free3.c内存管理方式3.1new/delete对内…

二叉树层序遍历 及相关题目

1&#xff0c;力扣102 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]]示例…

常见滤波算法(PythonC版本)

简介 受限于MCU自身的ADC外设缺陷&#xff0c;精度和稳定性通常较差&#xff0c;很多场景下需要用滤波算法进行补偿。滤波的主要目的是减少噪声与干扰对数据的影响&#xff0c;让数据更加接近真实值。 一阶低通滤波 一阶低通滤波是一种信号处理技术&#xff0c;用于去除信号中…

【C++入门】初识C++

&#x1f49e;&#x1f49e; 前言 hello hello~ &#xff0c;这里是大耳朵土土垚~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#x…

【Linux】寿司线程池{单例模式之懒汉模式下的线程池}

文章目录 回顾单例模式0.多线程下的单例模式的意义1.什么是单例模式1.0设计模式1.1C单例模式的介绍及原理1.2拷贝构造和赋值重载的处理1.3if (nullptr ptr)&#xff0c;nullptr放在比较运算符的前面?1.4实现单例模式的方式 2.实现懒汉方式的单例模式2.1单线程的单例模式2.2多…

StarRocks实战——携程火车票指标平台建设

目录 前言 一、早期OLAP架构与痛点 二、指标平台重构整体设计 2.1 指标查询过程 2.1.1 明细类子查询 2.1.2 汇总类子查询 2.1.3 “缓存” 2.2 数据同步 三、Starrocks使用经验分享 3.1 建表经验 3.2 数据查询 3.3 函数问题 四、查询性能大幅提升 五、 后续优化方…

算法——分治(快速排序)

T04BF &#x1f44b;专栏: 算法|JAVA|MySQL|C语言 &#x1faf5; 小比特 大梦想 此篇文章与大家分享分治算法关于排序排序的专题 对于快速排序在我个人主页专栏 <排序> 有详细的介绍,此专题对快排进行了优化操作,并介绍了优化后的快排的几种运用 如果有不足的或者错误的请…

利用Lora调整和部署 LLM

使用 NVIDIA TensorRT-LLM 调整和部署 LoRA LLM 大型语言模型 (LLM) 能够从大量文本中学习并为各种任务和领域生成流畅且连贯的文本&#xff0c;从而彻底改变了自然语言处理 (NLP)。 然而&#xff0c;定制LLM是一项具有挑战性的任务&#xff0c;通常需要完整的培训过程&#xf…

C++ 2024-4-1 作业

#include <iostream> using namespace std;class A { public:int a;A(int a):a(a){cout<<"A的有参构造"<<endl;} }; class B:virtual public A { public:int b;B(int a,int b):A(a),b(b){cout<<"B的有参构造"<<endl;} }; cl…