历史上的今天
返回首页

历史上的今天

今天是:2024年09月19日(星期四)

正在发生

2018年09月19日 | STM32 SPI接口读写SPI flash实验

2018-09-19 来源:eefocus

STM32 SPI flash读写测试实验报告

一、实验目的

1.学习SPI的基本工作原理

2.通过实验加深对STM32SPI的理解

3. 利用STM32的SPI11和SPI接口的flash芯片进行通信,读写测试,并将测试结果用串口打印出来

二、实验原理

1.SPI基础知识

SPI特征

● 3线全双工同步传输

●  带或不带第三根双向数据线的双线单工同步传输

● 8或16位传输帧格式选择

●  主或从操作

●  支持多主模式

● 8个主模式波特率预分频系数(最大为fPCLK/2)

●  从模式频率(最大为fPCLK/2)

●  主模式和从模式的快速通信

●  主模式和从模式下均可以由软件或硬件进行NSS管理:主/从操作模式的动态改变

●  可编程的时钟极性和相位

●  可编程的数据顺序,MSB在前或LSB在前

●  可触发中断的专用发送和接收标志

● SPI总线忙状态标志

●  支持可靠通信的硬件CRC

─  在发送模式下,CRC值可以被作为最后一个字节发送

─  在全双工模式中对接收到的最后一个字节自动进行CRC校验

●  可触发中断的主模式故障、过载以及CRC错误标志

●  支持DMA功能的1字节发送和接收缓冲器:产生发送和接受请求

 

从选择(NSS)脚管理

有2种NSS模式:

图211 ●  软件NSS模式:可以通过设置SPI_CR1寄存器的SSM位来使能这种模式(见 )。在这种

模式下NSS引脚可以用作它用,而内部NSS信号电平可以通过写SPI_CR1的SSI位来驱动

●  硬件NSS模式,分两种情况:

─NSS输出被使能:当STM32F10xxx工作为主SPI,并且NSS输出已经通过SPI_CR2寄存

器的SSOE位使能,这时NSS引脚被拉低,所有NSS引脚与这个主SPI的NSS引脚相连并

配置为硬件NSS的SPI设备,将自动变成从SPI设备。

当一个SPI设备需要发送广播数据,它必须拉低NSS信号,以通知所有其它的设备它是主

设备;如果它不能拉低NSS,这意味着总线上有另外一个主设备在通信,这时将产生一个

硬件失败错误(Hard Fault)。

─NSS输出被关闭:允许操作于多主环境。

 

 

时钟信号的相位和极性可以组合成四种不同的模式,下面为其中来两种模式

数据帧格式

根据SPI_CR1寄存器中的LSBFIRST位,输出数据位时可以MSB在先也可以LSB在先。

根据SPI_CR1寄存器的DFF位,每个数据帧可以是8位或是16位。所选择的数据帧格式对发送和或接收都有效。

 

配置SPI为主模式

在主配置时,在SCK脚产生串行时钟。

配置步骤

1. 通过SPI_CR1寄存器的BR[2:0]位定义串行时钟波特率。

2. 选择CPOL和CPHA位,定义数据传输和串行时钟间的相位关系(见图212)。

3. 设置DFF位来定义8位或16位数据帧格式。

4. 配置SPI_CR1寄存器的LSBFIRST位定义帧格式。

5. 如果需要NSS引脚工作在输入模式,硬件模式下,在整个数据帧传输期间应把NSS脚连接

到高电平;在软件模式下,需设置SPI_CR1寄存器的SSM位和SSI位。如果NSS引脚工作

在输出模式,则只需设置SSOE位。

6. 必须设置MSTR位和SPE位(只当NSS脚被连到高电平,这些位才能保持置位)。

在这个配置中,MOSI引脚是数据输出,而MISO引脚是数据输入。

 

 

SPI模块能够以两种配置工作于单工方式:

● 1条时钟线和1条双向数据线;

● 1条时钟线和1条数据线(只接收或只发送);

 

SPI通信可以通过以下步骤使用CRC:

●  设置CPOL、CPHA、LSBFirst、BR、SSM、SSI和MSTR的值;

●  在SPI_CRCPR寄存器输入多项式;

●  通过设置SPI_CR1寄存器CRCEN位使能CRC计算,该操作也会清除寄存器SPI_RXCRCR

和SPI_TXCRC;

●  设置SPI_CR1寄存器的SPE位启动SPI功能;

●  启动通信并且维持通信,直到只剩最后一个字节或者半字;

●  在把最后一个字节或半字写进发送缓冲器时,设置SPI_CR1的CRCNext位,指示硬件在发

送完成最后一个数据之后,发送CRC的数值。在发送CRC数值期间,停止CRC计算;

●  当最后一个字节或半字被发送后,SPI发送CRC数值,CRCNext位被清除。同样,接收到

的CRC与SPI_RXCRCR值进行比较,如果比较不相配,则设置SPI_SR上的CRCERR标志

位,当设置了SPI_CR2寄存器的ERRIE时,则产生中断。

个人理解:CRC校验,计算发送端是CRC值,接收端计算CRC值,然后发送端将计算的CRC值发送出去,接收端接收到之后与接收端计算的值相比较,若不同则返回错误标志

 

 

利用DMA的SPI通信

为了达到最大通信速度,需要及时往SPI发送缓冲器填数据,同样接收缓冲器中的数据也必须及

时读走以防止溢出。为了方便高速率的数据传输,SPI实现了一种采用简单的请求/应答的DMA

机制。

当SPI_CR2寄存器上的对应使能位被设置时,SPI模块可以发出DMA传输请求。发送缓冲器和

接收缓冲器亦有各自的DMA请求(见)。

●  发送时,在每次TXE被设置为’1’时发出DMA请求,DMA控制器则写数据至SPI_DR寄存

器,TXE标志因此而被清除。

●  接收时,在每次RXNE被设置为’1’时发出DMA请求,DMA控制器则从SPI_DR寄存器读出数

据,RXNE标志因此而被清除。

当只使用SPI发送数据时,只需使能SPI的发送DMA通道。此时,因为没有读取收到的数据,

OVR被置为’1’(译注:软件不必理会这个标志)。

当只使用SPI接收数据时,只需使能SPI的接收DMA通道

 

SPI寄存器

SPI控制寄存器1   SPI_CR1

(其中每个位的作用参阅数据手册486页)

 

SPI控制寄存器2(SPI_CR2)

SPI 状态寄存器(SPI_SR)

SPI 数据寄存器(SPI_DR)

SPI CRC多项式寄存器

SPI Rx CRC寄存器(SPI_RXCRCR)

在启用CRC计算时,RXCRC[15:0]中包含了依据收到的字节计算的CRC数值。当在SPI_CR1

的CRCEN位写入’1’时,该寄存器被复位。CRC计算使用SPI_CRCPR中的多项式。

当数据帧格式被设置为8位时,仅低8位参与计算,并且按照CRC8的方法进行;当数据帧格式

为16位时,寄存器中的所有16位都参与计算,并且按照CRC16的标准。

 

SPI Tx CRC寄存器(SPI_TXCRCR)

在启用CRC计算时,TXCRC[15:0]中包含了依据将要发送的字节计算的CRC数值。当在

SPI_CR1中的CRCEN位写入’1’时,该寄存器被复位。CRC计算使用SPI_CRCPR中的多项

式。

当数据帧格式被设置为8位时,仅低8位参与计算,并且按照CRC8的方法进行;当数据帧格式

为16位时,寄存器中的所有16个位都参与计算,并且按照CRC16的标准

 

2.实验电路图

W25X16有8192个可编程页,每页256字节。用“页编程指令”每次可以编程256个字节。用“扇区(sector)指令”每次可以擦除16页,用“块(block)擦除指令”每次可以擦除256页,用“整片擦除指令”即可擦除整个芯片。W25X16有512个可擦除扇区或32个可擦除块。

W25X16支持标准的SPI接口,传输速率最大75MHz。

 

双输出SPI方式

W25X16支持SPI双输出方式,需要使用“快读双输出指令0x3B”,这时,传输速率相当于两倍的标准SPI速率。这个命令非常适合于在需要一上电就快速下载代码到内存中的情况或者需要缓存代码段到内存中运行的情况下。在使用“快速双输出指令”后,DIO引脚变为输出引脚。

指令:写使能(Write Enable),页编程(Page Program),扇区擦除(Sector Erase),块区擦除(Block Erase),芯片擦除(Chip Erase),写状态寄存器指令(Write Status Register)

 

三、实验内容

软件设计

配置STM32 的SPI为主模式来读取SPI  flash实现读写功能。

下面对SPI1部分进行配置。

在主模式时,SCK脚输出串行时钟。

 

配置步骤:

1)配置SPI串行时钟比特率

2)定义数据传输和串行间的相位关系

3)设置8位或16位数据帧格式

4)如果需要NSS引脚工作在输入模式,硬件模式下,在整个数据帧传输期间应该把NSS脚连接到高电平,在软件模式下,需要设置SPI1_CR1的SSM位和SSI位。如果NSS引脚工作在输出模式,则需要设置SSOE位。

5)必须设置MSTR和SPE位(只有当NSS脚被连接到高电平,这些为才能保持置位)

//串行外设接口SPI的初始化,SPI配置成主模式                                                          

//本例程选用SPI1对W25X16进行读写操作,对SPI1进行初始化

void SPIx_Init(void)

{

        SPI_InitTypeDef  SPI_InitStructure;

        GPIO_InitTypeDef GPIO_InitStructure;

        

        /* Enable SPI1 and GPIOA clocks */

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOC|RCC_APB2Periph_SPI1|RCC_APB2Periph_AFIO, ENABLE);

        

        /* Configure SPI1 pins: NSS, SCK, MISO and MOSI */

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;

        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

        GPIO_Init(GPIOA, &GPIO_InitStructure);

        

        //SPI1 NSS

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

    GPIO_Init(GPIOC, &GPIO_InitStructure);

 

        GPIO_SetBits(GPIOC, GPIO_Pin_4);

 

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

    GPIO_Init(GPIOA, &GPIO_InitStructure);

        GPIO_SetBits(GPIOA, GPIO_Pin_4);   

 

        /* SPI1 configuration */

        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //SPI1设置为两线全双工

        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                           //设置SPI1为主模式

        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                  //SPI发送接收8位帧结构

        SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;                                        //串行时钟在不操作时,时钟为高电平

        SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                               //第二个时钟沿开始采样数据

        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                                       //NSS信号由软件(使用SSI位)管理

        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; //定义波特率预分频的值:波特率预分频值为8

        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                                   //数据传输从MSB位开始

        SPI_InitStructure.SPI_CRCPolynomial = 7;                                                   //CRC值计算的多项式

        SPI_Init(SPI1, &SPI_InitStructure);

        /* Enable SPI1  */

        SPI_Cmd(SPI1, ENABLE);                                                                                           //使能SPI1外设

}   

 

 

 

SPI接口读写Flash一个字节

//SPIx 读写一个字节

//返回值:读取到的字节

u8 SPIx_ReadWriteByte(u8 TxData)

{                

        u8 retry=0;                                

        while((SPI1->SR&1<<1)==0)//等待发送区空        

        {

                retry++;

                if(retry>200)return 0;

        }                          

        SPI1->DR=TxData;                   //发送一个byte

        retry=0;

        while((SPI1->SR&1<<0)==0) //等待接收完一个byte  

        {

                retry++;

                if(retry>200)return 0;

        }                                                             

        return SPI1->DR;          //返回收到的数据                                   

}

 

 

获取SPI flash ID

//读取芯片ID W25X16的ID:0XEF14

u16 SPI_Flash_ReadID(void)

{

        u16 Temp = 0;          

        SPI_FLASH_CS=0;                                   

        SPIx_ReadWriteByte(0x90);//发送读取ID命令           

        SPIx_ReadWriteByte(0x00);            

        SPIx_ReadWriteByte(0x00);            

        SPIx_ReadWriteByte(0x00);                                     

        Temp|=SPIx_ReadWriteByte(0xFF)<<8;  

        Temp|=SPIx_ReadWriteByte(0xFF);        

        SPI_FLASH_CS=1;                                   

        return Temp;

}  

 

 

在指定位置开始读取指定长度的数据

//读取SPI FLASH  

//在指定地址开始读取指定长度的数据

//pBuffer:数据存储区

//ReadAddr:开始读取的地址(24bit)

//NumByteToRead:要读取的字节数(最大65535)

void SPI_Flash_Read(u8* pBuffer,u32 ReadAddr,u16 NumByteToRead)   

{

        u16 i;                                                                                                       

        SPI_FLASH_CS=0;                            //使能器件   

    SPIx_ReadWriteByte(W25X_ReadData);         //发送读取命令   

    SPIx_ReadWriteByte((u8)((ReadAddr)>>16));  //发送24bit地址   

    SPIx_ReadWriteByte((u8)((ReadAddr)>>8));   

    SPIx_ReadWriteByte((u8)ReadAddr);   

    for(i=0;i

        {

        pBuffer[i]=SPIx_ReadWriteByte(0XFF);   //循环读数  

    }

        SPI_FLASH_CS=1;                            //取消片选                   

}  

 

 

在指定位置写入指定长度的数据

 

//写SPI FLASH  

//在指定地址开始写入指定长度的数据

//该函数带擦除操作!

//pBuffer:数据存储区

//WriteAddr:开始写入的地址(24bit)

//NumByteToWrite:要写入的字节数(最大65535)                     

u8 SPI_FLASH_BUF[4096];

void SPI_Flash_Write(u8* pBuffer,u32 WriteAddr,u16 NumByteToWrite)   

{

        u32 secpos;

        u16 secoff;

        u16 secremain;           

        u16 i;  

        secpos=WriteAddr/4096;//扇区地址 0~511 for w25x16

        secoff=WriteAddr%4096;//在扇区内的偏移

        secremain=4096-secoff;//扇区剩余空间大小   

        if(NumByteToWrite<=secremain)secremain=NumByteToWrite;//不大于4096个字节

        while(1)

        {        

                SPI_Flash_Read(SPI_FLASH_BUF,secpos*4096,4096);//读出整个扇区的内容

                for(i=0;i

                {

                        if(SPI_FLASH_BUF[secoff+i]!=0XFF)break;//需要擦除            

                }

                if(i

                {

                        SPI_Flash_Erase_Sector(secpos);//擦除这个扇区

                        for(i=0;i

                        {

                                SPI_FLASH_BUF[i+secoff]=pBuffer[i];          

                        }

                        SPI_Flash_Write_NoCheck(SPI_FLASH_BUF,secpos*4096,4096);//写入整个扇区  

 

                }else SPI_Flash_Write_NoCheck(pBuffer,WriteAddr,secremain);//写已经擦除了的,直接写入扇区剩余区间.                                    

                if(NumByteToWrite==secremain)break;//写入结束了

                else//写入未结束

                {

                        secpos++;//扇区地址增1

                        secoff=0;//偏移位置为0         

 

                           pBuffer+=secremain;  //指针偏移

                        WriteAddr+=secremain;//写地址偏移           

                           NumByteToWrite-=secremain;                                //字节数递减

                        if(NumByteToWrite>4096)secremain=4096;        //下一个扇区还是写不完

                        else secremain=NumByteToWrite;                        //下一个扇区可以写完了

                }        

        };                 

}

 

 

 

在main函数中,先向Flash中写入指定长度的数据,然后在读出并打印到串口,比较读出和写入的数据,并将结果显示到串口

int main(void)

{

        u8 i=0;

        u8 datatemp[SIZE];

        

        GPIO_Configuration();

        USART_Configuration();

        GPIO_SetBits(GPIOF, GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9);

        

        

        

        SPI_Flash_Init();   

        

        while(SPI_Flash_ReadID()!=FLASH_ID)//检测不到W25X16

        {           

                i=SPI_Flash_ReadID();

                printf("\n\r ID:%d",i);

                printf("\n\r没有读到正确的W25X16芯片ID,请检查硬件连接");

                Delay(0xaFFFF);

                Delay(0xaFFFF);

                GPIO_ResetBits(GPIOF,  GPIO_Pin_7);

                GPIO_SetBits(GPIOF,  GPIO_Pin_7);

        

        }

        

        printf("\n\r开始写入W25X16 SPI FLASH芯片....");

        SPI_Flash_Write((u8*)TEXT_Buffer,1000,SIZE);//从1000字节处开始,写入SIZE长度的数据

        printf("\n\r写入完成!");//提示传送完成

        printf("\n\r");

        Delay(0xFFFFFF);

        printf("\n\r");

        

        printf("\n\r开始从W25X16 SPI FLASH芯片读取数据.... ");

        SPI_Flash_Read(datatemp,1000,10000);//从1000地址处开始,读出SIZE个字节

        printf("\n\r读取完成,读出的数据为: %s  ",datatemp);//提示传送完成

        

        while(1)

        {

                

                i++;

                Delay(0xFFFF);

                if(i>0&& i<100)

                {

                        GPIO_SetBits(GPIOF, GPIO_Pin_6);;//提示系统正在运行        

                }

                else if(i >= 100 && i < 200)

                {

                        GPIO_ResetBits(GPIOF, GPIO_Pin_6);;//提示系统正在运行        

                }        

                i = i % 200;           

                }

        

        }


推荐阅读

史海拾趣

Efficient Power Conversion公司的发展小趣事

在追求自身发展的同时,EPC公司也积极寻求与行业内其他企业的合作。通过与全球知名的汽车制造商、通信设备制造商以及消费电子企业建立合作关系,EPC公司将其氮化镓技术广泛应用于各个领域,推动了整个电子行业的发展。同时,EPC公司也积极参与行业标准的制定和推广工作,为行业的健康发展做出了积极贡献。

芯旺微电子(ChipON)公司的发展小趣事

芯旺微电子自2012年成立以来,始终致力于高可靠性MCU器件的研发设计。公司凭借其自主研发的KungFu内核架构处理器,迅速在汽车级和工业级混合信号MCU领域崭露头角。随着技术的不断积累和市场的深入拓展,芯旺微电子逐渐从一家初创公司发展成为国内车规级MCU市场的领军企业。

COILCRAFT公司的发展小趣事

多年来,COILCRAFT公司凭借其卓越的产品质量、创新能力和良好的服务赢得了广泛的赞誉。在电子行业中,COILCRAFT已经成为高性能磁性元件设计、制造和分销领域的知名品牌。许多知名企业都选择与其合作,共同推动电子行业的发展。同时,COILCRAFT还积极参与行业交流和合作,为推动行业的进步贡献自己的力量。

以上这些故事只是COILCRAFT公司发展历程中的一部分,它们共同展示了这家公司在电子行业中的成长与壮大。未来,随着科技的不断发展和市场需求的不断变化,COILCRAFT将继续保持创新精神,为客户提供更优质的产品和服务。

Dean Technology公司的发展小趣事

近年来,随着电子行业的快速发展和市场竞争的加剧,Dean Technology公司也面临着前所未有的挑战。为了应对这些挑战,公司积极调整战略方向,加强内部管理和团队建设。同时,他们还密切关注行业趋势和市场需求的变化,及时调整产品结构和市场策略。这些努力使得Dean Technology在应对行业变革和挑战时更加从容和自信。

请注意,以上故事是基于对Dean Technology公司一般情况的了解而编写的,可能不完全符合公司的实际发展历程。如需更详细的信息,请查阅相关资料或联系公司官方渠道。

Adafruit公司的发展小趣事

Dean Technology公司起源于上世纪80年代,当时电子行业正经历着飞速的发展。创始人凭借其深厚的电子技术背景和敏锐的市场洞察力,决定进入高压二极管领域。他带领研发团队不断攻克技术难题,成功推出了一系列性能稳定、品质可靠的高压二极管产品,奠定了公司在行业中的技术领先地位。

Cardinal Components公司的发展小趣事

随着时间的推移,Cardinal不断推出新的产品系列以满足市场需求。2013年,公司推出了CJ速差器系列,这一系列产品以其高性能和稳定性受到了市场的广泛好评。随后,在2015年,CJ系列被移植到2.5×2.0封装尺寸,进一步提高了产品的集成度和可靠性。这些产品系列的拓展与升级不仅丰富了公司的产品线,也为客户提供了更多的选择。

问答坊 | AI 解惑

基于SYSTEM C的FPGA设计方法

摘 要: 随着VLSI的集成度越来越高,设计也越趋复杂。传统的设计方法如原理图输入、HDL语言描述在进行复杂系统设计时,设计效率往往比较低。特别是在算法由软件转化为硬件的环节上,传统的设计方法的效率不是很高,设计者往往要耗费大量的时间和精 ...…

查看全部问答>

学习

我是初学者,才用2051片和1302做了个定时器,还加了电池但掉电后数字复零,不知为啥请各位老师指导.我的QQ:754862083.电话:029-81227236…

查看全部问答>

串口通信波特率

   使用115200波特率的串口,但是MCU上说明可能会存在4%的频率偏移,那就是产生偏移以后的频率可能范围是110592到119808,请问大牛们,这个偏移对串口的通信影响会不会很大?…

查看全部问答>

串口中断与定时中断同时存在造成的问题(急!!!!!!)

利用PC104单板机,DOS操作系统,在程序中使用100ms定时中断来处理输入输出等操作,利用串口中断来进行串口数据通讯。在发生串口中断时将所有中断屏蔽。串口设置为最常用的9600,现在遇到一个问题就是串口数据通讯成功率不高,有很多数据丢失的现象 ...…

查看全部问答>

如何设置ADS的ARM Linker

请教各位大侠,设置ARM Linker的Output时,RO Base 如何设置,我在编译时,老是说“Entry point lies outside the image.”还有一个Warning: Ignoring -first command.Cannot find section 2410 init.s(Init). 谢谢! …

查看全部问答>

请问当arm通过网口下载了映像后,为什么tshell执行i没有问题,串口一执行i就死掉?

请问当arm通过网口下载了映像后,为什么tshell执行i没有问题,串口一执行i就死掉? 为了验证串口是否好用,在映像起来后,做了个周期打印的程序,可以在串口打印,没有问题,但是只要一执行i,马上打出部分东东,串口就死掉了,同时通过tshell可以 ...…

查看全部问答>

新手求教“JTAGCommunicationfailured”

这一阵开始学习STM32,从网上下了一例子,是按钮控制小灯的,但后来就一直不能下程序,总出现“JTAG Communication failured”,先前一直不知道什么原因,在论坛里找帖子才知道是自己在程序里把JTAG口禁用了,这样导致再也下载不下去程序了, ...…

查看全部问答>

关于CM3的中断嵌套

我们都知道CM3内核支持中断嵌套,即当一个中断正在进行处理时来了一个抢占优先级高于当前正在被处理的中断的新的中断,则内核会将当前中断挂起,转而执行抢占优先级更高的新来中断,这种中断嵌套属于被动式抢占;还有一种情况,就是,当前正在处理 ...…

查看全部问答>

团购的RL78/G14光盘里的USB Drivers安装失败!

电脑是win7 64位的!如果大家的安装成功了  麻烦你下,发一份 912973694@qq.com…

查看全部问答>

求一个IAR for 8051 IAR 8.20.2版本的安装包,有个小case要用ble

本帖最后由 lyzhangxiang 于 2015-5-7 16:28 编辑 如题, 求一个IAR for 8051 IAR 8.20.2版本的安装包,有个小case要用ble 论坛之前有搞过sensortag的活动,应该有大把的这个软件吧,网上找不到。。 痛苦,下载了个9.1的和arm的冲突。…

查看全部问答>