当前位置: 首页 >  业内资讯  >   >  正文

每日聚焦:STM32F429 Discovery开发板应用:实现SPI-SD Card文件写入(搭载FatFS文件系统)

  • 2023-06-07 14:23:26 来源:博客园
MCU:STM32F429ZIT6

开发环境:STM32CubeMX+MDK5


(资料图)

外购了一个SPI接口的SD Card模块,想要实现SD卡存储数据的功能。

首先需要打开STM32CubeMX工具。输入开发板MCU对应型号,找到开发板对应封装的MCU型号,双击打开(图中第三)。

此时,双击完后会关闭此界面,然后打开一个新界面。

然后,我们开始基本配置。

现在我们选择一个LED作为系统LED,该步骤可以忽略,只是本人喜欢这样子。以硬件原理图的LD3为例子。

基本配置除了时钟树外,基本上已经配置好了。

现在配置时钟树

基本配置已经配置完,现在开始配置实验使用的内容。

配置USART1,重定向printf函数作为串口输出。

然后配置SPI1,作为驱动SD Card读写的接口。

然后配置文件系统,可以让文件的使用更方便。

现在配置按键,触发中断处理一些事情。

配置完成,完善工程,生成工程。

到此,STM32CubeMX工具的使用结束!可以发现在桌面已经生成了SDCard_rw工程。

使用MDK5打开SDCard_rw工程打开。点击魔法棒,勾选微库。选择对应的下载器,勾选下载完复位允许。USB线一端接开发板USB_Device,一端接PC。

现在可以开始实验了

在usart.c中重定向printf函数,并在usart.h中声明。

1 //重定向c库函数printf到串口DEBUG_USART,重定向后可使用printf函数2 int fputc(int ch, FILE *f)3 {4     HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);    5     return (ch);6 }

在sdcard_write工程下创建UserCode文件夹,编写drive_spisd.c和drive_spisd.h。

然后在MDK5这里的SDCard_rw工程添加一个新文件夹UserCode,装入drive_spisd.c。并在魔法棒这里加入头文件路径。

drive_spisd.c如下

1 /* Includes ------------------------------------------------------------------*/  2 #include "drive_spisd.h"  3 /* Private includes ----------------------------------------------------------*/  4 #include "spi.h"  5 #include "ff.h"  6 #include "usart.h"  7 /* Private typedef -----------------------------------------------------------*/  8   9 /* Private define ------------------------------------------------------------*/ 10  11 /* Private macro -------------------------------------------------------------*/ 12  13 /* Private variables ---------------------------------------------------------*/ 14 uint8_t test; 15 uint8_t SD_TYPE = 0x00; 16 MSD_CARDINFO SD0_CardInfo; 17 char SD_FileName[] = "hello.txt"; 18 /* Private function prototypes -----------------------------------------------*/ 19 static int         SD_SendCMD(uint8_t cmd, uint32_t arg, uint8_t crc); 20 static uint8_t     SD_ReceiveData(uint8_t *data, uint16_t len); 21 static uint8_t     SD_SendBlock(uint8_t*buf, uint8_t cmd); 22 /* Private user code ---------------------------------------------------------*/ 23  24 /** 25   * @brief  SPI_CS片选 26   * @note   None 27   * @retval None 28   */ 29 void SPISD_CS(uint8_t p) 30 { 31     HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, (p==0)?GPIO_PIN_SET:GPIO_PIN_RESET); 32 } 33  34 /** 35   * @brief  发送命令(CMD0~CMD63),发完释放 36   * @note   命令格式:0+传输标志(1-命令、0-响应)+CONTENT(6+32)+7CRC+1 37   * @retval None 38   */ 39 static int SD_SendCMD(uint8_t cmd, uint32_t arg, uint8_t crc) 40 { 41     uint8_t r1,retry; 42  43     SPISD_CS(0);    //取消片选 44     HAL_Delay(20); 45     SPISD_CS(1);    //选通 46      47     //SD卡的SPI通信协议规定,每个命令操作之前都需要发送至少8个时钟周期 48     do 49     { 50         retry = SPI_ReadWrite(0xFF); 51     }while(retry != 0xFF); 52          53     SPI_ReadWrite(cmd | 0x40); 54     SPI_ReadWrite(arg >> 24); 55     SPI_ReadWrite(arg >> 16); 56     SPI_ReadWrite(arg >> 8); 57     SPI_ReadWrite(arg); 58     SPI_ReadWrite(crc); 59      60     if(cmd == CMD12)     61         SPI_ReadWrite(0xFF); 62     do 63     { 64         r1 = SPI_ReadWrite(0xFF); 65     }while(r1 & 0x80); 66      67     return r1; 68 } 69  70 //SD卡初始化 71 uint8_t SD_Init(void) 72 { 73     uint8_t     r1,i;     74     uint8_t     buff[6] = {0}; 75     uint16_t     retry;  76      77     SPI_SetSpeed(SPI_BAUDRATEPRESCALER_256); 78     SPISD_CS(0); 79     for(retry=0;retry<10;retry++) 80         SPI_ReadWrite(0xFF); 81      82     //SD卡进入IDLE状态 83     do 84     { 85         r1 = SD_SendCMD(CMD0 ,0, 0x95);     86     }while(r1 != 0x01); 87      88     //查看SD卡的类型 89     SD_TYPE = 0; 90     r1 = SD_SendCMD(CMD8, 0x1AA, 0x87); 91     if(r1 == 0x01) 92     { 93         for(i=0;i<4;i++) 94             buff[i] = SPI_ReadWrite(0xFF);                    //Get trailing return value of R7 resp 95         if( buff[2]==0X01 && buff[3]==0XAA )                //卡是否支持2.7~3.6V 96         {             97             retry = 0XFFFE;             98             do             99             {            100                 SD_SendCMD(CMD55, 0, 0X01);                    //发送CMD55101                 r1 = SD_SendCMD(CMD41, 0x40000000, 0X01);    //发送CMD41102             }while(r1&&retry--);103             104             if(retry && SD_SendCMD(CMD58, 0, 0X01) == 0)    //鉴别SD2.0卡版本开始105             {106                 for(i=0;i<4;i++)107                     buff[i] = SPI_ReadWrite(0XFF);            //得到OCR值108                 SD_TYPE = (buff[0]&0x40) ? V2HC:V2;    109             }110         }else111         {112             SD_SendCMD(CMD55, 0, 0X01);                        //发送CMD55113             r1 = SD_SendCMD(CMD41, 0, 0X01);                //发送CMD41114             if(r1<=1)115             {        116                 SD_TYPE = V1;117                 retry = 0XFFFE;118                 do                                             //等待退出IDLE模式119                 {120                     SD_SendCMD(CMD55, 0, 0X01);                //发送CMD55121                     r1 = SD_SendCMD(CMD41, 0, 0X01);        //发送CMD41122                 }while(r1&&retry--);123             }else                                            //MMC卡不支持CMD55+CMD41识别124             {125                 SD_TYPE = MMC;                                //MMC V3126                 retry = 0XFFFE;127                 do                                             //等待退出IDLE模式128                 {                                                129                     r1 = SD_SendCMD(CMD1, 0, 0X01);            //发送CMD1130                 }while(r1&&retry--);  131             }132             if( retry==0 || SD_SendCMD(CMD16, 512, 0X01)!=0 )133                 SD_TYPE = ERR;                                //错误的卡134         }135     }136     SPISD_CS(0);137     SPI_SetSpeed(SPI_BAUDRATEPRESCALER_4);138     139     return SD_TYPE?0:1;140 }141 142 void FileSystem_Init(void)143 {144     FATFS         *fs;145     DWORD         fre_clust, AvailableSize, UserSize;  146     uint8_t     res;147     uint8_t     *work;148     uint16_t     TotalSpace;149     150     res = SD_Init();        151     if(res == 1)152         printf("SD卡初始化失败! \r\n");        153     154     res = f_mount(&USERFatFS, USERPath, 1);                        //挂载155     if(res == FR_NO_FILESYSTEM)                                    //没有文件系统,格式化156     {157         printf("没有文件系统! \r\n");    158         159         work = malloc(_MIN_SS);160         res = f_mkfs(USERPath, FM_FAT, 0, work, _MIN_SS);        //格式化sd卡161         free(work);162         163         if(res == FR_OK)164         {        165             res = f_mount(NULL, USERPath, 1);                     //格式化后先取消挂载166             res = f_mount(&USERFatFS, USERPath, 1);                //重新挂载    167             if(res == FR_OK)168             {169                 printf("SD卡已经成功挂载,可以进进行文件写入测试! \r\n");170             }    171         }172         else173         {174             printf("格式化失败! \r\n");        175         }176     }else if(res == FR_OK)177     {178         printf("挂载成功! \r\n");        179     }else180     {181         printf("挂载失败! (%d)\r\n", res);182     }        183 184     res = f_getfree(USERPath, &fre_clust, &fs);  /* 根目录 */185     if ( res == FR_OK ) 186     {187         TotalSpace = (uint16_t)(((fs->n_fatent - 2) * fs->csize ) / 2 /1024);188         AvailableSize = (uint16_t)((fre_clust * fs->csize) / 2 /1024);189         UserSize = TotalSpace - AvailableSize;              190         /* Print free space in unit of MB (assuming 512 bytes/sector) */191         printf("\r\n%d MB total drive space.\r\n%ld MB available.\r\n%ld MB used.\r\n",TotalSpace, AvailableSize, UserSize);192     }193     else 194     {195         printf("Get SDCard Capacity Failed (%d)\r\n", res);196     }    197 //    f_mount(NULL, USERPath, 1);             //取消挂载198 } 199 200 /**201   * @brief  读取指定长度数据202   * @note   None203   * @retval None204   */205 static uint8_t SD_ReceiveData(uint8_t *data, uint16_t len)206 {207     uint8_t r1;208     209     SPISD_CS(1);                                       210     do211     { 212         r1 = SPI_ReadWrite(0xFF);    213         HAL_Delay(100);214     }while(r1 != 0xFE);    215     216     while(len--)217     {218         *data = SPI_ReadWrite(0xFF);219         data++;220     }221     SPI_ReadWrite(0xFF);222     SPI_ReadWrite(0xFF); 223     224     return 0;225 }226 227 /**228   * @brief  向SD卡写入一个数据包(512字节)的内容229   * @note   None230   * @retval None231   */232 static uint8_t SD_SendBlock(uint8_t*buf, uint8_t cmd)233 {    234     uint8_t     r1;    235     uint16_t     t;    236     237     do{238         r1 = SPI_ReadWrite(0xFF);239     }while(r1!=0xFF);240     241     SPI_ReadWrite(cmd);242     if(cmd != 0XFD)                    //不是结束指令243     {244         for(t=0; t<512; t++)245             SPI_ReadWrite(buf[t]);    //提高速度,减少函数传参时间246         SPI_ReadWrite(0xFF);        //忽略crc247         SPI_ReadWrite(0xFF);248         t = SPI_ReadWrite(0xFF);    //接收响应249         if( (t&0x1F) != 0x05 )250             return 2;                //响应错误                                                              251     }252     253     return 0;                        //写入成功254 }255 256 /**257   * @brief  CSD,卡的操作条件信息,128bit258   * @note   None259   * @retval None260   */261 uint8_t SD_GetCSD(uint8_t *csd_data)262 {263     uint8_t r1;    264     265     r1 = SD_SendCMD(CMD9, 0, 0x01);            //读取CSD寄存器266     if(r1 == 0x00)267         r1 = SD_ReceiveData(csd_data, 16);    //接收16个字节的数据 268     SPISD_CS(0);                            //取消片选269     270     return r1?1:0;271 }272 273 /**274   * @brief  CID,卡识别号,128bit275   * @note   None276   * @retval None277   */278 uint8_t SD_GetCID(uint8_t *cid_data)279 {280     uint8_t    r1;281     282     r1 = SD_SendCMD(CMD10, 0, 0x01);         //读取CID寄存器283     if(r1==0x00)284         r1 = SD_ReceiveData(cid_data, 16);    //接收16个字节的数据 285     SPISD_CS(0);                            //取消片选286     287     return r1?1:0;288 }289 290 //获取SD卡的总扇区数291 uint32_t SD_GetSectorCount(void)292 {293     uint8_t     n;294     uint8_t     csd[16];295     uint16_t     csize;296     uint32_t     Capacity;  297     298     if(SD_GetCSD(csd) != 0)         //取CSD信息,如果期间出错,返回0299         return 0;        300     301     if( (csd[0]&0xC0) == 0x40 )         //如果为SDHC卡,按照下面方式计算。V2.00的卡302     {    303         csize = csd[9] + ((uint16_t)csd[8] << 8) + 1;304         Capacity = (uint32_t)csize << 10;                //得到扇区数                305     }else                            //V1.xx的卡306     {    307         n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;308         csize = (csd[8] >> 6) + ((uint16_t)csd[7] << 2) + ((uint16_t)(csd[6] & 3) << 10) + 1;309         Capacity = (uint32_t)csize << (n - 9);            //得到扇区数   310     }311     312     return Capacity;313 }314 315 int MSD0_GetCardInfo(PMSD_CARDINFO SD0_CardInfo)316 {317     uint8_t r1;318     uint8_t CSD_Tab[16], CID_Tab[16];319     320     /* Send CMD9, Read CSD */321     r1 = SD_SendCMD(CMD9, 0, 0xFF);322     if(r1 != 0x00)323         return r1;324     if(SD_ReceiveData(CSD_Tab, 16))325         return 1;326     327     /* Send CMD10, Read CID */328     r1 = SD_SendCMD(CMD10, 0, 0xFF);329     if(r1 != 0x00)330         return r1;    331     if(SD_ReceiveData(CID_Tab, 16))332         return 2;333     334     /* Byte 0 */335     SD0_CardInfo->CSD.CSDStruct = (CSD_Tab[0] & 0xC0) >> 6;336     SD0_CardInfo->CSD.SysSpecVersion = (CSD_Tab[0] & 0x3C) >> 2;337     SD0_CardInfo->CSD.Reserved1 = CSD_Tab[0] & 0x03;338     /* Byte 1 */339     SD0_CardInfo->CSD.TAAC = CSD_Tab[1] ;340     /* Byte 2 */341     SD0_CardInfo->CSD.NSAC = CSD_Tab[2];342     /* Byte 3 */343     SD0_CardInfo->CSD.MaxBusClkFrec = CSD_Tab[3];344     /* Byte 4 */345     SD0_CardInfo->CSD.CardComdClasses = CSD_Tab[4] << 4;346     /* Byte 5 */347     SD0_CardInfo->CSD.CardComdClasses |= (CSD_Tab[5] & 0xF0) >> 4;348     SD0_CardInfo->CSD.RdBlockLen = CSD_Tab[5] & 0x0F;349     /* Byte 6 */350     SD0_CardInfo->CSD.PartBlockRead = (CSD_Tab[6] & 0x80) >> 7;351     SD0_CardInfo->CSD.WrBlockMisalign = (CSD_Tab[6] & 0x40) >> 6;352     SD0_CardInfo->CSD.RdBlockMisalign = (CSD_Tab[6] & 0x20) >> 5;353     SD0_CardInfo->CSD.DSRImpl = (CSD_Tab[6] & 0x10) >> 4;354     SD0_CardInfo->CSD.Reserved2 = 0; /* Reserved */355     SD0_CardInfo->CSD.DeviceSize = (CSD_Tab[6] & 0x03) << 10;356     /* Byte 7 */357     SD0_CardInfo->CSD.DeviceSize |= (CSD_Tab[7]) << 2;358     /* Byte 8 */359     SD0_CardInfo->CSD.DeviceSize |= (CSD_Tab[8] & 0xC0) >> 6;360     SD0_CardInfo->CSD.MaxRdCurrentVDDMin = (CSD_Tab[8] & 0x38) >> 3;361     SD0_CardInfo->CSD.MaxRdCurrentVDDMax = (CSD_Tab[8] & 0x07);362     /* Byte 9 */363     SD0_CardInfo->CSD.MaxWrCurrentVDDMin = (CSD_Tab[9] & 0xE0) >> 5;364     SD0_CardInfo->CSD.MaxWrCurrentVDDMax = (CSD_Tab[9] & 0x1C) >> 2;365     SD0_CardInfo->CSD.DeviceSizeMul = (CSD_Tab[9] & 0x03) << 1;366     /* Byte 10 */367     SD0_CardInfo->CSD.DeviceSizeMul |= (CSD_Tab[10] & 0x80) >> 7;368     SD0_CardInfo->CSD.EraseGrSize = (CSD_Tab[10] & 0x7C) >> 2;369     SD0_CardInfo->CSD.EraseGrMul = (CSD_Tab[10] & 0x03) << 3;370     /* Byte 11 */371     SD0_CardInfo->CSD.EraseGrMul |= (CSD_Tab[11] & 0xE0) >> 5;372     SD0_CardInfo->CSD.WrProtectGrSize = (CSD_Tab[11] & 0x1F);373     /* Byte 12 */374     SD0_CardInfo->CSD.WrProtectGrEnable = (CSD_Tab[12] & 0x80) >> 7;375     SD0_CardInfo->CSD.ManDeflECC = (CSD_Tab[12] & 0x60) >> 5;376     SD0_CardInfo->CSD.WrSpeedFact = (CSD_Tab[12] & 0x1C) >> 2;377     SD0_CardInfo->CSD.MaxWrBlockLen = (CSD_Tab[12] & 0x03) << 2;378     /* Byte 13 */379     SD0_CardInfo->CSD.MaxWrBlockLen |= (CSD_Tab[13] & 0xc0) >> 6;380     SD0_CardInfo->CSD.WriteBlockPaPartial = (CSD_Tab[13] & 0x20) >> 5;381     SD0_CardInfo->CSD.Reserved3 = 0;382     SD0_CardInfo->CSD.ContentProtectAppli = (CSD_Tab[13] & 0x01);383     /* Byte 14 */384     SD0_CardInfo->CSD.FileFormatGrouop = (CSD_Tab[14] & 0x80) >> 7;385     SD0_CardInfo->CSD.CopyFlag = (CSD_Tab[14] & 0x40) >> 6;386     SD0_CardInfo->CSD.PermWrProtect = (CSD_Tab[14] & 0x20) >> 5;387     SD0_CardInfo->CSD.TempWrProtect = (CSD_Tab[14] & 0x10) >> 4;388     SD0_CardInfo->CSD.FileFormat = (CSD_Tab[14] & 0x0C) >> 2;389     SD0_CardInfo->CSD.ECC = (CSD_Tab[14] & 0x03);390     /* Byte 15 */391     SD0_CardInfo->CSD.CSD_CRC = (CSD_Tab[15] & 0xFE) >> 1;392     SD0_CardInfo->CSD.Reserved4 = 1;393 394     if(SD0_CardInfo->CardType == V2HC)395     {396         /* Byte 7 */397         SD0_CardInfo->CSD.DeviceSize = (uint16_t)(CSD_Tab[8]) *256;398         /* Byte 8 */399         SD0_CardInfo->CSD.DeviceSize += CSD_Tab[9] ;400     }401     402     SD0_CardInfo->Capacity = SD0_CardInfo->CSD.DeviceSize * MSD_BLOCKSIZE * 1024;403     SD0_CardInfo->BlockSize = MSD_BLOCKSIZE;404     405     /* Byte 0 */406     SD0_CardInfo->CID.ManufacturerID = CID_Tab[0];407     /* Byte 1 */408     SD0_CardInfo->CID.OEM_AppliID = CID_Tab[1] << 8;409     /* Byte 2 */410     SD0_CardInfo->CID.OEM_AppliID |= CID_Tab[2];411     /* Byte 3 */412     SD0_CardInfo->CID.ProdName1 = CID_Tab[3] << 24;413     /* Byte 4 */414     SD0_CardInfo->CID.ProdName1 |= CID_Tab[4] << 16;415     /* Byte 5 */416     SD0_CardInfo->CID.ProdName1 |= CID_Tab[5] << 8;417     /* Byte 6 */418     SD0_CardInfo->CID.ProdName1 |= CID_Tab[6];419     /* Byte 7 */420     SD0_CardInfo->CID.ProdName2 = CID_Tab[7];421     /* Byte 8 */422     SD0_CardInfo->CID.ProdRev = CID_Tab[8];423     /* Byte 9 */424     SD0_CardInfo->CID.ProdSN = CID_Tab[9] << 24;425     /* Byte 10 */426     SD0_CardInfo->CID.ProdSN |= CID_Tab[10] << 16;427     /* Byte 11 */428     SD0_CardInfo->CID.ProdSN |= CID_Tab[11] << 8;429     /* Byte 12 */430     SD0_CardInfo->CID.ProdSN |= CID_Tab[12];431     /* Byte 13 */432     SD0_CardInfo->CID.Reserved1 |= (CID_Tab[13] & 0xF0) >> 4;433     /* Byte 14 */434     SD0_CardInfo->CID.ManufactDate = (CID_Tab[13] & 0x0F) << 8;435     /* Byte 15 */436     SD0_CardInfo->CID.ManufactDate |= CID_Tab[14];437     /* Byte 16 */438     SD0_CardInfo->CID.CID_CRC = (CID_Tab[15] & 0xFE) >> 1;439     SD0_CardInfo->CID.Reserved2 = 1;440     441     return 0;  442 }443 444 445 //写SD卡446 //buf:数据缓存区447 //sector:起始扇区448 //cnt:扇区数449 //返回值:0,ok;其他,失败.450 uint8_t SD_WriteDisk(uint8_t *buf, uint32_t sector, uint8_t cnt)451 {452     uint8_t r1;453     454     if(SD_TYPE != V2HC)455         sector *= 512;                            //转换为字节地址456     if(cnt == 1)457     {458         r1 = SD_SendCMD(CMD24, sector, 0x01);    //读命令459         if(r1 == 0)                                //指令发送成功460             r1=SD_SendBlock(buf, 0xFE);            //写512个字节       461     }else462     {463         if(SD_TYPE != MMC)464         {465             SD_SendCMD(CMD55, 0, 0x01);    466             SD_SendCMD(CMD23, cnt, 0x01);        //发送指令    467         }468          r1 = SD_SendCMD(CMD25, sector, 0x01);    //连续读命令469         if(r1 == 0)470         {471             do472             {473                 r1 = SD_SendBlock(buf,0xFC);    //接收512个字节     474                 buf += 512;  475             }while(--cnt && r1==0);476             r1 = SD_SendBlock(0,0xFD);            //接收512个字节 477         }478     }   479     SPISD_CS(0);                                //取消片选480     481     return r1;482 }    483 484 //读SD卡485 //buf:数据缓存区486 //sector:扇区487 //cnt:扇区数488 //返回值:0,ok;其他,失败.489 uint8_t SD_ReadDisk(uint8_t*buf,uint32_t sector,uint8_t cnt)490 {491     uint8_t r1;492     493     if(SD_TYPE != V2HC)494         sector <<= 9;                            //转换为字节地址495     if(cnt == 1)496     {497         r1 = SD_SendCMD(CMD17, sector, 0x01);    //读命令498         if(r1 == 0)        499             r1 = SD_ReceiveData(buf, 512);        //接收512个字节       500     }else501     {502         r1 = SD_SendCMD(CMD18, sector, 0x01);    //连续读命令503         do504         {505             r1 = SD_ReceiveData(buf, 512);        //接收512个字节     506             buf += 512;  507         }while(--cnt && r1==0);     508         SD_SendCMD(CMD12, 0, 0x01);                //发送停止命令509     }   510     SPISD_CS(0);                                //取消片选511     512     return r1;513 }514 515 uint8_t SPI_ReadWrite(uint8_t Txdata)516 {517     uint8_t Rxdata;    518     HAL_SPI_TransmitReceive(&hspi1, &Txdata, &Rxdata, 1, 100);519     return Rxdata;520 }521 522 //SPI1波特率设置523 void SPI_SetSpeed(uint8_t speed)524 {525     hspi1.Init.BaudRatePrescaler = speed;526     if (HAL_SPI_Init(&hspi1) != HAL_OK)527     {528         Error_Handler();529     }530 }531 ///////////////////////////END//////////////////////////////////////

drive_spisd.h如下

1 /* Define to prevent recursive inclusion -------------------------------------*/  2 #ifndef __DRIVE_SPISD_H  3 #define __DRIVE_SPISD_H  4   5 #ifdef __cplusplus  6 extern "C" {  7 #endif  8   9 /* Includes ------------------------------------------------------------------*/ 10 #include "main.h" 11 /* Private includes ----------------------------------------------------------*/ 12 #include "fatfs.h" 13 /* Exported types ------------------------------------------------------------*/ 14 enum _CD_HOLD 15 { 16     HOLD = 0, 17     RELEASE = 1, 18 }; 19  20 typedef struct                       /* Card Specific Data */ 21 { 22     uint8_t  CSDStruct;                /* CSD structure */ 23     uint8_t  SysSpecVersion;           /* System specification version */ 24     uint8_t  Reserved1;                /* Reserved */ 25     uint8_t  TAAC;                     /* Data read access-time 1 */ 26     uint8_t  NSAC;                     /* Data read access-time 2 in CLK cycles */ 27     uint8_t  MaxBusClkFrec;            /* Max. bus clock frequency */ 28     uint16_t CardComdClasses;          /* Card command classes */ 29     uint8_t  RdBlockLen;               /* Max. read data block length */ 30     uint8_t  PartBlockRead;            /* Partial blocks for read allowed */ 31     uint8_t  WrBlockMisalign;          /* Write block misalignment */ 32     uint8_t  RdBlockMisalign;          /* Read block misalignment */ 33     uint8_t  DSRImpl;                  /* DSR implemented */ 34     uint8_t  Reserved2;                /* Reserved */ 35     uint32_t DeviceSize;               /* Device Size */ 36     uint8_t  MaxRdCurrentVDDMin;       /* Max. read current @ VDD min */ 37     uint8_t  MaxRdCurrentVDDMax;       /* Max. read current @ VDD max */ 38     uint8_t  MaxWrCurrentVDDMin;       /* Max. write current @ VDD min */ 39     uint8_t  MaxWrCurrentVDDMax;       /* Max. write current @ VDD max */ 40     uint8_t  DeviceSizeMul;            /* Device size multiplier */ 41     uint8_t  EraseGrSize;              /* Erase group size */ 42     uint8_t  EraseGrMul;               /* Erase group size multiplier */ 43     uint8_t  WrProtectGrSize;          /* Write protect group size */ 44     uint8_t  WrProtectGrEnable;        /* Write protect group enable */ 45     uint8_t  ManDeflECC;               /* Manufacturer default ECC */ 46     uint8_t  WrSpeedFact;              /* Write speed factor */ 47     uint8_t  MaxWrBlockLen;            /* Max. write data block length */ 48     uint8_t  WriteBlockPaPartial;      /* Partial blocks for write allowed */ 49     uint8_t  Reserved3;                /* Reserded */ 50     uint8_t  ContentProtectAppli;      /* Content protection application */ 51     uint8_t  FileFormatGrouop;         /* File format group */ 52     uint8_t  CopyFlag;                 /* Copy flag (OTP) */ 53     uint8_t  PermWrProtect;            /* Permanent write protection */ 54     uint8_t  TempWrProtect;            /* Temporary write protection */ 55     uint8_t  FileFormat;               /* File Format */ 56     uint8_t  ECC;                      /* ECC code */ 57     uint8_t  CSD_CRC;                  /* CSD CRC */ 58     uint8_t  Reserved4;                /* always 1*/ 59 }MSD_CSD; 60  61 typedef struct                         /*Card Identification Data*/ 62 { 63     uint8_t  ManufacturerID;           /* ManufacturerID */ 64     uint16_t OEM_AppliID;              /* OEM/Application ID */ 65     uint32_t ProdName1;                /* Product Name part1 */ 66     uint8_t  ProdName2;                /* Product Name part2*/ 67     uint8_t  ProdRev;                  /* Product Revision */ 68     uint32_t ProdSN;                   /* Product Serial Number */ 69     uint8_t  Reserved1;                /* Reserved1 */ 70     uint16_t ManufactDate;             /* Manufacturing Date */ 71     uint8_t  CID_CRC;                  /* CID CRC */ 72     uint8_t  Reserved2;                /* always 1 */ 73 }MSD_CID; 74  75 typedef struct 76 { 77     MSD_CSD     CSD; 78     MSD_CID     CID; 79     uint32_t     Capacity;              /* Card Capacity */ 80     uint32_t     BlockSize;             /* Card Block Size */ 81     uint16_t     RCA; 82     uint8_t     CardType; 83     uint32_t     SpaceTotal;            /* Total space size in file system */ 84     uint32_t     SpaceFree;             /* Free space size in file system */ 85 }MSD_CARDINFO, *PMSD_CARDINFO; 86  87 extern MSD_CARDINFO SD0_CardInfo; 88 /* Exported constants --------------------------------------------------------*/ 89  90 /* Exported macro ------------------------------------------------------------*/ 91 //SD卡类型 92 #define ERR             0x00 93 #define MMC                0x01 94 #define V1                0x02 95 #define V2                0x04 96 #define V2HC            0x06 97  98 #define DUMMY_BYTE        0xFF  99 #define MSD_BLOCKSIZE    512100 101 /*102     CMD定义103     bc:发送到所有卡,不返回响应104     bcr:发送到所有卡,同时接收所有卡的响应105     ac:发送到选定卡,无数据传输106     adtc:发送到选定卡,有数据传输107 */108 #define CMD0    0       //bc,卡复位到IDLE状态109 #define CMD1    1       110 #define CMD8    8       //bcr,读SD卡接口条件,包含主机支持的电压信息,并询问卡是否支持111 #define CMD9    9       //ac,读CSD数据112 #define CMD10   10      //ac,读CID数据113 #define CMD12   12      //ac,停止数据传输114 #define CMD16   16      //ac,设置块长度(对于SDHC卡块命令长度固定为512字节) 应返回0x00115 #define CMD17   17      //adtc,读单个块116 #define CMD18   18      //adtc,读多个块。连续读块,直到被CMD12中断。117 #define CMD23   23      //设置多sector写入前预先擦除N个block118 #define CMD24   24      //adtc,写单个块119 #define CMD25   25      //adtc,写多个块。连续写块,直到被CMD12中断。120 #define CMD41   41      //应返回0x00121 #define CMD55   55      //ac,指定下个命令为特定应用命令(ACMD),不是标准命令,应返回0x01122 #define CMD58   58      //读OCR信息123 #define CMD59   59      //使能/禁止CRC,应返回0x00124 125 //数据写入回应字意义126 #define MSD_DATA_OK                0x05127 #define MSD_DATA_CRC_ERROR         0x0B128 #define MSD_DATA_WRITE_ERROR       0x0D129 #define MSD_DATA_OTHER_ERROR       0xFF130 131 //SD卡回应标记字132 #define MSD_RESPONSE_NO_ERROR      0x00133 #define MSD_IN_IDLE_STATE          0x01134 #define MSD_ERASE_RESET            0x02135 #define MSD_ILLEGAL_COMMAND        0x04136 #define MSD_COM_CRC_ERROR          0x08137 #define MSD_ERASE_SEQUENCE_ERROR   0x10138 #define MSD_ADDRESS_ERROR          0x20139 #define MSD_PARAMETER_ERROR        0x40140 #define MSD_RESPONSE_FAILURE       0xFF141 142 /* Exported functions prototypes ---------------------------------------------*/143 void        SPISD_CS(uint8_t p);144 uint8_t        SD_Init(void);145 void         WritetoSD(BYTE write_buff[],uint8_t bufSize);146 void         FileSystem_Init(void);147 uint32_t      SD_GetSectorCount(void);148 uint8_t     SD_GetCID(uint8_t *cid_data);149 uint8_t     SD_GetCSD(uint8_t *csd_data);150 int            MSD0_GetCardInfo(PMSD_CARDINFO SD0_CardInfo);151 uint8_t     SD_ReadDisk(uint8_t*buf, uint32_t sector, uint8_t cnt);152 uint8_t     SD_WriteDisk(uint8_t*buf, uint32_t sector, uint8_t cnt);153 void         SPI_SetSpeed(uint8_t speed);154 uint8_t     SPI_ReadWrite(uint8_t Txdata);155 156 /* Private defines -----------------------------------------------------------*/157 extern uint8_t SD_TYPE;158 #ifdef __cplusplus159 }160 #endif161 162 #endif /* __DRIVE_SPISD_H */163 164 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

然后在文件系统文件夹里修改内容。

user_diskio.c如下

1 /* USER CODE BEGIN Header */  2 /**  3  ******************************************************************************  4   * @file    user_diskio.c  5   * @brief   This file includes a diskio driver skeleton to be completed by the user.  6   ******************************************************************************  7   * @attention  8   *  9   * Copyright (c) 2023 STMicroelectronics. 10   * All rights reserved. 11   * 12   * This software is licensed under terms that can be found in the LICENSE file 13   * in the root directory of this software component. 14   * If no LICENSE file comes with this software, it is provided AS-IS. 15   * 16   ****************************************************************************** 17   */ 18  /* USER CODE END Header */ 19  20 #ifdef USE_OBSOLETE_USER_CODE_SECTION_0 21 /* 22  * Warning: the user section 0 is no more in use (starting from CubeMx version 4.16.0) 23  * To be suppressed in the future. 24  * Kept to ensure backward compatibility with previous CubeMx versions when 25  * migrating projects. 26  * User code previously added there should be copied in the new user sections before 27  * the section contents can be deleted. 28  */ 29 /* USER CODE BEGIN 0 */ 30 /* USER CODE END 0 */ 31 #endif 32  33 /* USER CODE BEGIN DECL */ 34  35 /* Includes ------------------------------------------------------------------*/ 36 #include  37 #include "ff_gen_drv.h" 38  39 /* Private typedef -----------------------------------------------------------*/ 40 #include "drive_spisd.h" 41 /* Private define ------------------------------------------------------------*/ 42  43 /* Private variables ---------------------------------------------------------*/ 44 /* Disk status */ 45 static volatile DSTATUS Stat = STA_NOINIT; 46  47 /* USER CODE END DECL */ 48  49 /* Private function prototypes -----------------------------------------------*/ 50 DSTATUS USER_initialize (BYTE pdrv); 51 DSTATUS USER_status (BYTE pdrv); 52 DRESULT USER_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count); 53 #if _USE_WRITE == 1 54   DRESULT USER_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count); 55 #endif /* _USE_WRITE == 1 */ 56 #if _USE_IOCTL == 1 57   DRESULT USER_ioctl (BYTE pdrv, BYTE cmd, void *buff); 58 #endif /* _USE_IOCTL == 1 */ 59  60 Diskio_drvTypeDef  USER_Driver = 61 { 62   USER_initialize, 63   USER_status, 64   USER_read, 65 #if  _USE_WRITE 66   USER_write, 67 #endif  /* _USE_WRITE == 1 */ 68 #if  _USE_IOCTL == 1 69   USER_ioctl, 70 #endif /* _USE_IOCTL == 1 */ 71 }; 72  73 /* Private functions ---------------------------------------------------------*/ 74  75 /** 76   * @brief  Initializes a Drive 77   * @param  pdrv: Physical drive number (0..) 78   * @retval DSTATUS: Operation status 79   */ 80 DSTATUS USER_initialize ( 81     BYTE pdrv           /* Physical drive nmuber to identify the drive */ 82 ) 83 { 84   /* USER CODE BEGIN INIT */ 85     uint8_t res; 86     res = SD_Init(); 87     if(res)    //STM32 SPI的bug,在sd卡操作失败的时候如果不执行下面的语句,可能导致SPI读写异常 88     { 89         SPI_SetSpeed(SPI_BAUDRATEPRESCALER_256); 90         SPI_ReadWrite(0xff);    //提供额外的8个时钟 91         SPI_SetSpeed(SPI_BAUDRATEPRESCALER_4); 92     } 93     if(res)     94         return STA_NOINIT; 95     else  96         return RES_OK;  97   /* USER CODE END INIT */ 98 } 99 100 /**101   * @brief  Gets Disk Status102   * @param  pdrv: Physical drive number (0..)103   * @retval DSTATUS: Operation status104   */105 DSTATUS USER_status (106     BYTE pdrv       /* Physical drive number to identify the drive */107 )108 {109   /* USER CODE BEGIN STATUS */110     switch (pdrv)111     {112         case 0 :113             return RES_OK;114         case 1 :115             return RES_OK;116         case 2 :117             return RES_OK;118         default:119             return STA_NOINIT;120     }121   /* USER CODE END STATUS */122 }123 124 /**125   * @brief  Reads Sector(s)126   * @param  pdrv: Physical drive number (0..)127   * @param  *buff: Data buffer to store read data128   * @param  sector: Sector address (LBA)129   * @param  count: Number of sectors to read (1..128)130   * @retval DRESULT: Operation result131   */132 DRESULT USER_read (133     BYTE pdrv,      /* Physical drive nmuber to identify the drive */134     BYTE *buff,     /* Data buffer to store read data */135     DWORD sector,   /* Sector address in LBA */136     UINT count      /* Number of sectors to read */137 )138 {139   /* USER CODE BEGIN READ */140     uint8_t res;141     if( !count )142     {    143         return RES_PARERR;  /* count不能等于0,否则返回参数错误 */144     }145     switch (pdrv)146     {147         case 0:148             res = SD_ReadDisk(buff,sector,count);     149             if(res == 0)150                 return RES_OK;151             else152                 return RES_ERROR;                                             153         default:154             return RES_ERROR;155     }156   /* USER CODE END READ */157 }158 159 /**160   * @brief  Writes Sector(s)161   * @param  pdrv: Physical drive number (0..)162   * @param  *buff: Data to be written163   * @param  sector: Sector address (LBA)164   * @param  count: Number of sectors to write (1..128)165   * @retval DRESULT: Operation result166   */167 #if _USE_WRITE == 1168 DRESULT USER_write (169     BYTE pdrv,          /* Physical drive nmuber to identify the drive */170     const BYTE *buff,   /* Data to be written */171     DWORD sector,       /* Sector address in LBA */172     UINT count          /* Number of sectors to write */173 )174 {175   /* USER CODE BEGIN WRITE */176   /* USER CODE HERE */177     uint8_t  res;178     if( !count )179         return RES_PARERR;  /* count不能等于0,否则返回参数错误 */180     switch (pdrv)181     {182         case 0:183             res=SD_WriteDisk((uint8_t *)buff,sector,count);184                 if(res == 0)185                     return RES_OK;186                 else187                     return RES_ERROR;                                              188         default:189             return RES_ERROR;190     }191   /* USER CODE END WRITE */192 }193 #endif /* _USE_WRITE == 1 */194 195 /**196   * @brief  I/O control operation197   * @param  pdrv: Physical drive number (0..)198   * @param  cmd: Control code199   * @param  *buff: Buffer to send/receive control data200   * @retval DRESULT: Operation result201   */202 #if _USE_IOCTL == 1203 DRESULT USER_ioctl (204     BYTE pdrv,      /* Physical drive nmuber (0..) */205     BYTE cmd,       /* Control code */206     void *buff      /* Buffer to send/receive control data */207 )208 {209   /* USER CODE BEGIN IOCTL */210     DRESULT res;211     switch(cmd)212     {213         case CTRL_SYNC:214             SPISD_CS(1);215             do{216                 HAL_Delay(20);217             }while(SPI_ReadWrite(0xFF)!=0xFF);218             res=RES_OK;219             SPISD_CS(0);220             break;     221         case GET_SECTOR_SIZE:222             *(WORD*)buff = 512;223             res = RES_OK;224             break;     225         case GET_BLOCK_SIZE:226             *(WORD*)buff = 8;227             res = RES_OK;228             break;     229         case GET_SECTOR_COUNT:230             *(DWORD*)buff = SD_GetSectorCount();231             res = RES_OK;232             break;233         default:234             res = RES_PARERR;235             break;236     }237     return res;238   /* USER CODE END IOCTL */239 }240 #endif /* _USE_IOCTL == 1 */

main.c

1 /* USER CODE BEGIN Header */  2 /**  3   ******************************************************************************  4   * @file           : main.c  5   * @brief          : Main program body  6   ******************************************************************************  7   * @attention  8   *  9   * Copyright (c) 2023 STMicroelectronics. 10   * All rights reserved. 11   * 12   * This software is licensed under terms that can be found in the LICENSE file 13   * in the root directory of this software component. 14   * If no LICENSE file comes with this software, it is provided AS-IS. 15   * 16   ****************************************************************************** 17   */ 18 /* USER CODE END Header */ 19 /* Includes ------------------------------------------------------------------*/ 20 #include "main.h" 21 #include "fatfs.h" 22 #include "spi.h" 23 #include "usart.h" 24 #include "gpio.h" 25  26 /* Private includes ----------------------------------------------------------*/ 27 /* USER CODE BEGIN Includes */ 28 #include "drive_spisd.h" 29 /* USER CODE END Includes */ 30  31 /* Private typedef -----------------------------------------------------------*/ 32 /* USER CODE BEGIN PTD */ 33  34 /* USER CODE END PTD */ 35  36 /* Private define ------------------------------------------------------------*/ 37 /* USER CODE BEGIN PD */ 38 /* USER CODE END PD */ 39  40 /* Private macro -------------------------------------------------------------*/ 41 /* USER CODE BEGIN PM */ 42  43 /* USER CODE END PM */ 44  45 /* Private variables ---------------------------------------------------------*/ 46  47 /* USER CODE BEGIN PV */ 48 uint8_t     status = 0; 49 uint8_t        writeBuf[] = "demo program forever no bug!!!\r\n";  50 /* USER CODE END PV */ 51  52 /* Private function prototypes -----------------------------------------------*/ 53 void SystemClock_Config(void); 54 /* USER CODE BEGIN PFP */ 55  56 /* USER CODE END PFP */ 57  58 /* Private user code ---------------------------------------------------------*/ 59 /* USER CODE BEGIN 0 */ 60  61 /* USER CODE END 0 */ 62  63 /** 64   * @brief  The application entry point. 65   * @retval int 66   */ 67 int main(void) 68 { 69   /* USER CODE BEGIN 1 */ 70     UINT     Bw; 71     FIL     file; 72     uint16_t cb_task = 0; 73     uint8_t res1 = 0, res2 = 0; 74   /* USER CODE END 1 */ 75  76   /* MCU Configuration--------------------------------------------------------*/ 77  78   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ 79   HAL_Init(); 80  81   /* USER CODE BEGIN Init */ 82  83   /* USER CODE END Init */ 84  85   /* Configure the system clock */ 86   SystemClock_Config(); 87  88   /* USER CODE BEGIN SysInit */ 89  90   /* USER CODE END SysInit */ 91  92   /* Initialize all configured peripherals */ 93   MX_GPIO_Init(); 94   MX_SPI1_Init(); 95   MX_USART1_UART_Init(); 96   MX_FATFS_Init(); 97   /* USER CODE BEGIN 2 */ 98     FileSystem_Init();    //初始化文件系统 99     100     status = 1;101     res1 = f_open(&file, "sdRW1.txt", FA_OPEN_ALWAYS | FA_WRITE);102     if((res1 & FR_DENIED) == FR_DENIED)103         printf("卡存储已满,写入失败! \r\n");104   /* USER CODE END 2 */105 106   /* Infinite loop */107   /* USER CODE BEGIN WHILE */108   while (1)109   {110     /* USER CODE END WHILE */111 112     /* USER CODE BEGIN 3 */113     if(status == 1)114     {115         if(res1 == FR_OK)116         {117             f_lseek(&file, f_size(&file));                                //确保写入不会覆盖之前的数据118             res2 = f_write(&file, writeBuf, sizeof(writeBuf), &Bw);        //写数据到SD卡            119             if(res2 != FR_OK)120             {121                 printf("文件写入失败! \r\n");122                 HAL_GPIO_WritePin(User_led_GPIO_Port, User_led_Pin, GPIO_PIN_RESET);123             }else124             {125                 HAL_GPIO_WritePin(User_led_GPIO_Port, User_led_Pin, GPIO_PIN_SET);126             }                127         }128         else129         {130             printf("打开文件失败! %d\r\n",res1);131         }    132         if(++cb_task%4096==0)133             f_sync(&file);            134     }else if(status == 2)135     {136         f_close(&file);137         f_mount(NULL, USERPath, 1);             //取消挂载138         HAL_GPIO_WritePin(User_led_GPIO_Port, User_led_Pin, GPIO_PIN_RESET);139         status = 0;140     }141     HAL_Delay(10);142   }143   /* USER CODE END 3 */144 }145 146 /**147   * @brief System Clock Configuration148   * @retval None149   */150 void SystemClock_Config(void)151 {152   RCC_OscInitTypeDef RCC_OscInitStruct = {0};153   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};154 155   /** Configure the main internal regulator output voltage156   */157   __HAL_RCC_PWR_CLK_ENABLE();158   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);159   /** Initializes the RCC Oscillators according to the specified parameters160   * in the RCC_OscInitTypeDef structure.161   */162   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;163   RCC_OscInitStruct.HSEState = RCC_HSE_ON;164   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;165   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;166   RCC_OscInitStruct.PLL.PLLM = 4;167   RCC_OscInitStruct.PLL.PLLN = 168;168   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;169   RCC_OscInitStruct.PLL.PLLQ = 4;170   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)171   {172     Error_Handler();173   }174   /** Initializes the CPU, AHB and APB buses clocks175   */176   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK177                               |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;178   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;179   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;180   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;181   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;182 183   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)184   {185     Error_Handler();186   }187 }188 189 /* USER CODE BEGIN 4 */190 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)191 {192     if(GPIO_Pin == User_Key_Pin)193     {194         status = 2;195     }196 }197 /* USER CODE END 4 */198 199 /**200   * @brief  This function is executed in case of error occurrence.201   * @retval None202   */203 void Error_Handler(void)204 {205   /* USER CODE BEGIN Error_Handler_Debug */206   /* User can add his own implementation to report the HAL error return state */207   __disable_irq();208   while (1)209   {210   }211   /* USER CODE END Error_Handler_Debug */212 }213 214 #ifdef  USE_FULL_ASSERT215 /**216   * @brief  Reports the name of the source file and the source line number217   *         where the assert_param error has occurred.218   * @param  file: pointer to the source file name219   * @param  line: assert_param error line source number220   * @retval None221   */222 void assert_failed(uint8_t *file, uint32_t line)223 {224   /* USER CODE BEGIN 6 */225   /* User can add his own implementation to report the file name and line number,226      ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */227   /* USER CODE END 6 */228 }229 #endif /* USE_FULL_ASSERT */

实测是可以的,但是写速度并没有网上说的1M/s那么快,也有可能是我引线的问题。

标签:

最新推荐

每日聚焦:STM32F429 Discovery开发板应用:实现SPI-SD Card文件写入(搭载FatFS文件系统)

MCU:STM32F429ZIT6开发环境:STM32CubeMX+MDK5外购了一个SPI接口的SDC

可以融资融券的股票是不是都可以买跌?(可以融资融券的股票一共有那些)_焦点热议

来为大家解答以上的问题。可以融资融券的股票是不是都可以买跌?,可以

湖北能源:截至一季度末,公司长协煤与市场采购煤比例约为3:1

每经AI快讯,有投资者在投资者互动平台提问:你好,想咨询贵司:1 目前

天天看点:《皮克敏4》新中文版序幕预告片公布!将于7月发售

任天堂确认《皮克敏4(Pikmin4)》将于7月21日发售,全区支持简体中文

紫金矿业与哈萨克投资国有公司达成矿产开发协议

紫金矿业与哈萨克投资国有公司达成矿产开发协议 【紫金矿业与哈萨

网易开盘涨近5% 本月将发布四款游戏|快看点

同时提到,网易的营运利润增长已经连续七个季度超过游戏收入的增长,预

环球快播:网络用语中方言词语的生成条件及现实影响_刺挠是什么意思网络用语是哪里的方言

想必现在有很多小伙伴对于刺挠是什么意思网络用语,是哪里的方言方面的

丹阳属于哪个市哪个区_丹阳属于江苏的哪个市 世界视讯

1、丹阳属于江苏的哪个市2、丹阳是一个县级市,隶属于江苏省镇江市。3

56亿持续抄底!-环球快看点

中国基金报记者天心6月5日,A股市场表现分化,上证指数上涨0 07%,深证

当前信息:董子春秋义法辞考论_关于董子春秋义法辞考论的简介

音频解说1、余治平编著的《董子春秋义法辞考论》是一部从义、法、辞三

沧州五中录取分数线2023年_沧州五中|热门

1、不论是初中还是高中。2、十四中都要强过五中的!。本文就为大家分享

科技!体验无人驾驶汽车采摘汉南甜玉米

科技!体验无人驾驶汽车采摘汉南甜玉米​六月,汉南甜玉米进入成熟期,

陈品杰:多走多看把大陆好的资讯带回台湾|全球实时

台湾极限运动超铁协会理事长陈品杰接受中评社访问表示,大陆对台湾开了

演出服“穿完就退”,网店店主:快被汗臭味熏晕!“ 7 天无理由退货”到底要怎么退?|世界消息

七天无理由退货是为了保护消费者合法权益,但有人却利用这一规定占卖家

ps的边缘调整怎么和图层融合_ps中如何让边缘与背景融合-全球聚焦

1、PS中有一下几种有代表性的方法:使用选区工具中的【羽化】先按照边

火龙辅助官网下载安装_火龙辅助官网_焦点快播

1、这个是真的很厉害。2、我前几天买了逆天辅助。3、通宵玩。本文为大

3.68亿元!快乐8大派奖来啦

重磅消息!记者从中福彩中心获悉,为回馈广大购彩者对中国福利彩票的关

ios17升级名单 iPhone 8和iPhone X不支持更新iOS17

iOS17发布之后,惯例苹果会给出支持更新升级的设备以及不支持的设备,

Steam一周销量榜:《街霸6》强势登顶 《永劫无间》进入前三

近日V社公布了本周Steam游戏销量周榜,CAPCOM旗下经典格斗游戏系列《街

当前热讯:沈阳医学院:大手牵小手 育人共筑梦

初夏的沈阳医学院,绿草如茵,繁花盛开。在波光粼粼的博学湖畔的草地上

环球微资讯!飞天茅台在英国“定价”曝光,国内外差异明显,网友:看碟下菜?

在国外市场上,白酒饮用口感和茅台酒存在的口感风格是有所不同的,茅台

大宗交易:罗普特成交338.79万元,折价5.03%(06-06) 天天热推荐

2023年6月6日,罗普特发生1笔大宗交易,总成交23万股,成交金额338 79

商业连锁板块震荡走强 小商品城等涨超8%|环球今日讯

商业连锁板块震荡走强,截至发稿,小商品城、第一医药等涨超8%,国药一

可以靠颜值出圈却拼实力,四千年美女鞠婧祎活出自我,走出精彩

当身边不少人都否定你的付出,你心中肯定也是百感交集的,鞠婧祎自然也

焦点资讯:爱心送考再出征

据了解,高考期间,考生或家长只要看到贴有“爱心送考”车标并系有“绿

天气丨明夜至后天白天有雷阵雨

天气转好气温回升明夜至后天白天有雷阵雨今明天气今天上午雨止转阴,下

热消息:詹琳:产教融合培养工业互联网人才

最新数据显示,我国工业互联网覆盖45大类经济行业,连接设备逾8000万台

今日美元指数汇率走势分析:美元指数受到经济数据低迷的影响

周二早盘,美元指数保持在104 00附近的防御态势,此前一周开盘波动较大

全球头条:摩托车强制报废的车辆补贴多少钱

摩托车强制报废的车辆补贴根据摩托车登记年限而定。提前一年报废的补贴

关于名著的手抄报初中简单-关于名著的手抄报_独家焦点

1、我想这个不是几句话就能说明白的。2、看你这么着急,给你一些建议和

今天起,铁路12306为学生提供这项服务

铁路12306手机客户端5日起提供学生优惠资质在线核验服务记者从中国铁路

全球快资讯丨全省前四月新增税费缓减76.07亿元

全省前四月新增税费缓减76 07亿元,主流媒体,山西门户。山西新闻网是经

湖南开出首趟跨省“水泥专列” 后续每3天发运2趟|世界微动态

华声在线6月4日讯(全媒体记者彭可心通讯员彭维刘雯)6月3日10时许,一

世界快看:腾讯今日头条_腾讯新闻今日头条新闻

1、没有区别,腾讯新闻布局新闻类早,有自己团队。2、头条都是拿来主义

素描中的细节

————————陶罐主体陶罐是在静物画中经常出现的一个种类,是能够

涉嫌职务犯罪外逃人员苏茂生回国投案

6月4日,在山东省委反腐败协调小组国际追逃追赃工作办公室统筹协调下,

人老了才明白,不管和谁交往,都要做到“五不过”

断舍离,是一生的必修课。人到了晚年,就要过低配生活,道理很容易被接

低优先级队列最快解除_低优先级队列怎么解除 焦点速看

1、LOLs6低优先级队列怎么解除?LOL低优先级队列是什么意思?LOLs6低优

郭富城古天乐《扫毒3》提档7月6日上映:全新海报公布

由邱礼涛执导,郭富城、古天乐、刘青云领衔主演的动作犯罪电影《扫毒3

word斜线表头输入文字(word斜线表头怎么输入文字)

word斜线表头输入文字,word斜线表头怎么输入文字这个很多人还不知道,

售价下探至20万元内 哪吒S 520 Lite版/520版静态体验 每日快播

哪吒汽车旗下产品有一个共同点,售价都相对亲民。这一次,哪吒S继续延

珠宝店买到假“阿玛尼”,集体起诉!法院判“退一赔三”_全球新资讯

花上千元在珠宝店买的“阿玛尼”手表竟是假的9名消费者要求“退一赔三

天天报道:宝鸡市工业企业景气指数信心指数稳步回升

记者从市统计局获悉,从近日出炉的规上工业企业生产经营景气状况季度调

亿胜生物科技(01061)6月5日注销28.2万股已回购股份_头条焦点

智通财经APP讯,亿胜生物科技(01061)发布公告,于2023年6月5日,该公司

市场监管总局:对妨碍全国统一大市场建设的政策措施开展专项清理

人民网北京6月5日电(记者杨曦)国务院新闻办公室今日举行国务院政策例行

热门看点:讯息:信用卡逾期太多会连累家人吗?信用卡逾期了多久会被起诉?

信用卡逾期太多会连累家人吗如果您的信用卡逾期太多,可能会对您的

乌克兰反攻来了?俄国防部称乌军大规模进攻被挫败 世界速讯

中新网6月5日电综合外媒报道,俄罗斯国防部发言人伊戈尔·科纳申科夫称

6月5日南京炭青TDI报价平稳-热消息

南京炭青化学品有限公司TDI报价平稳,上海货执行16500元 吨。供方积极

全球消息!高考倒计时!考生什么情况下要戴口罩?

一年一度的高考即将开始考生面对考试北京市疾控中心提醒考生、家长及学

X 广告
X 广告

精彩放送

两部门:开展“春雨润苗”专项行动 助力小微经营主体发展

今日最新!视频热传,三亚凌晨通报

世界快资讯:天津2023高考考点+考场示意图汇总

环球要闻:初中化学教学工作总结及教学反思(初中化学教学工作总结)

全球时讯:日本"无菜单"寿司风靡中国:高端套餐人均2000元!

市场监督管理总局:将加快推进全国统一大市场建设|天天滚动

全球快讯:金融租赁业2022年总资产规模同比增加5.6% “新规”促行业加速回归租赁本源

日经225股指期货 (OSE) (M3) 当日内交易策略: 在 31750.00 之上 目标价位为 32190.00(20230605) 每日热议

“不满”量化继续“独大”,这批“深度研究型”基金经理要“上场对抗“

果丹皮可以空腹吃吗?果丹皮可以多吃吗? 今日快看

环球微动态丨沙特宣布将在7月份每日额外减产原油100万桶

最好听的乡村歌曲_乡村歌曲-焦点快报

世界百事通!ChatGPT 标注指南来了!数据是关键

新乡市气象台发布大雾橙色预警【Ⅱ级/严重】【2023-06-05】_当前速读

胎教从什么时候开始最好_胎教开始的时间-环球滚动

天天播报:大中国歌曲歌词曲_大中国歌曲歌词

当前通讯!移徒指的是什么意思(移徒)

环球快报:泰国球员谢尔曼首夺高尔夫女子中巡赛冠军

全球快讯:高考主要考什么内容语文

高考生注意了!这6样东西千万不要发朋友圈

理我一下93章微博截图(微博戳了你一下什么意思)

每日报道:大余县气象台发布雷电黄色预警信号【III级/较重】【2023-06-04】

横亘的意思是什么呢(横亘的意思) 焦点速看

安宝国际药业 厦门有限公司_环球速看料

关注全生命周期眼健康,提高近视手术可及性|世界观热点

莫比尔大学(关于莫比尔大学的简介)_全球时快讯

养兔子要注意什么 兔子会认主人吗-信息

世界百事通!荒僻的拼音和解释是什么(荒僻的拼音 荒僻的造句简介介绍)

恭喜!中国三人女篮晋级世界杯四强

matlab画矩形_画矩形

前沿资讯!我市举办环境日公益宣传活动 做生态文明建设的践行者

神奇解压脑洞官网在哪下载 最新官方下载安装地址 天天看热讯

酿酒的谷壳可以养花吗?

dnf结婚满属性多少_戒指婚房满属性_当前速递

情人节礼物推荐排行榜(送男友情人节礼物排行) 环球今热点

全球播报:微信莫名其妙被拉进群然后无限邀请朋友(微信莫名其妙被下线了)

夜色阑珊歌曲_夜色阑珊

胸模大赛首轮海选高能对决:18位佳丽争妍斗艳,气氛紧张刺激

三连胜!2023世界女排联赛中国女排3:1战胜荷兰队-环球播报

“七星课堂”走进防城港 优秀课例提高当地教学水平

黄渤王一博主演电影《热烈》担任第25届上影节闭幕片-环球关注

贝弗利谈甜瓜退役:向他致敬 他本可以再打4-5年的

世界观热点:中国人去年喝掉了多少葡萄酒?OIV数据来了!

【原】看了《后浪》才知道,端午节必备的艾草,原来一个夏天都这么有用! 全球新视野

两岸青少年共同探寻诗词中的“山河美”

中国星辰|这是一封中国航天员从“天宫”发来的回信|快报

assertion failed什么意思_debug assertion failed

做人流最佳时间休息多少天_做人流最佳时间 资讯推荐

美团单车接入武汉碳普惠平台 联手构建低碳出行场景-天天速看

观点:出现可能不支持此配件关不掉_可能不支持此配件关不掉

Copyright ©  2015-2022 世界律师网版权所有  备案号:琼ICP备2022009675号-1   联系邮箱:435 227 67@qq.com