用户工具

站点工具


icore4t_13

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

后一修订版
前一修订版
上一修订版 两侧同时换到之后的修订记录
icore4t_13 [2020/02/25 19:11]
zgf 创建
icore4t_13 [2020/02/25 19:27]
zgf
行 4: 行 4:
 |技术论坛|http://​www.eeschool.org||| |技术论坛|http://​www.eeschool.org|||
 ^  版本 ​ ^  日期 ​ ^  作者 ​ ^  修改内容 ​ ^ ^  版本 ​ ^  日期 ​ ^  作者 ​ ^  修改内容 ​ ^
-|  V1.0  |  2019-02- ​| ​ gingko ​ |  初次建立 ​ |  +|  V1.0  |  2019-02-25  ​| ​ gingko ​ |  初次建立 ​ |  
-=====  +\\ 
-STM32CubeMX教程十三——QSPI通信实验 =====+\\ 
 +\\ 
 +\\ 
 + 
 +=====STM32CubeMX教程十三——QSPI通信实验 ===== 
 +\\ 
 +\\ 
 +\\
  
 1.在主界面选择File-->​New Project ​  ​或者直接点击ACCEE TO MCU SELECTOR。  ​ 1.在主界面选择File-->​New Project ​  ​或者直接点击ACCEE TO MCU SELECTOR。  ​
行 36: 行 43:
   * **Copy all used libraries into the project folder**   * **Copy all used libraries into the project folder**
   * **将HAL库的所有.C和.H都复制到所建工程中**   * **将HAL库的所有.C和.H都复制到所建工程中**
-  ​* 优点:这样如果后续需要新增其他外设又可能不再用STM32CubeMX的时候便会很方便 +    ​* 优点:这样如果后续需要新增其他外设又可能不再用STM32CubeMX的时候便会很方便 
-  * 缺点:体积大,编译时间很长+    * 缺点:体积大,编译时间很长
   * **Copy only the necessary library files**   * **Copy only the necessary library files**
   * **只复制所需要的.C和.H(推荐)**   * **只复制所需要的.C和.H(推荐)**
-  ​* 优点:体积相对小,编译时间短,并且工程可复制拷贝 +    ​* 优点:体积相对小,编译时间短,并且工程可复制拷贝 
-  * 缺点:新增外设时需要重新用STM32CubeMX导入+    * 缺点:新增外设时需要重新用STM32CubeMX导入
   * **Add necessary library files as reference in the toolchain project configuration file**   * **Add necessary library files as reference in the toolchain project configuration file**
   * **不复制文件,直接从软件包存放位置导入.C和.H**   * **不复制文件,直接从软件包存放位置导入.C和.H**
-  ​* 优点:体积小,比较节约硬盘空间 +    ​* 优点:体积小,比较节约硬盘空间 
-  * 缺点:复制到其他电脑上或者软件包位置改变,就需要修改相对应的路径+    * 缺点:复制到其他电脑上或者软件包位置改变,就需要修改相对应的路径
   * 自行选择方式即可   * 自行选择方式即可
 13.然后点击GENERATE CODE  创建工程。 13.然后点击GENERATE CODE  创建工程。
 {{ :​icore4t:​icore4t_cube_13_15.png?​direct |}}  {{ :​icore4t:​icore4t_cube_13_15.png?​direct |}} 
 创建成功,打开工程。 创建成功,打开工程。
 +\\
 +\\
 +===== 实验十三:QSPI通信实验——读写测试SPI FLASH =====
 +
 +==== 一、 实验目的与意义 ====
 +  - 了解STM32 QSPI结构。
 +  - 了解STM32 QSPI特征。
 +  - 掌握QSPI的使用方法。
 +  - 掌握STM32 HAL库中QSPI属性的配置方法。
 +  - 掌握KEILMDK 集成开发环境使用方法。
 +==== 二、 实验设备及平台 ====
 +  - iCore4T 双核心板。[[https://​item.taobao.com/​item.htm?​spm=a1z10.1-c.w137644-251734891.3.5923532fDrMDOe&​id=610595120319|点击购买]]
 +  - JLINK(或相同功能)仿真器。[[https://​item.taobao.com/​item.htm?​id=554869837940|点击购买]]
 +  - Micro USB线缆。
 +  - Keil MDK 开发平台。
 +  - STM32CubeMX开发平台。
 +  - 装有WIN XP(及更高版本)系统的计算机。
 +==== 三、 实验原理 ====
 +=== 1.QSPI简介 ===
 +
 +  * QSPI是Queued SPI的简写,是Motorola公司推出的SPI接口的扩展,比SPI应用更加广泛。在SPI协议的基础上,Motorola公司对其功能进行了增强,增加了队列传输机制,推出了队列串行外围接口协议(即QSPI协议)。QSPI是一种专用的通信接口,连接单、双或四(条数据线)SPI Flash存储介质。
 +  * 该接口可以在以下三种模式下工作:
 +  * **① 间接模式**:使用QSPI寄存器执行全部操作。
 +  * **② 状态轮询模式**:周期性读取外部Flash状态寄存器,而且标志位置1时会产生中断(如擦除或烧写完成,会产生中断)。
 +  * **③ 内存映射模式**:外部Flash映射到微控制器地址空间,从而系统将其视作内部存储器。
 +  * 采用双闪存模式时,将同时访问两个Quad-SPI Flash,吞吐量和容量均可提高二倍。
 +=== 2.QSPI命令序列 ===
 +  * QUADSPI通过命令与Flash通信,每条命令包括指令、地址、交替字节、空指令和数据这五个阶段,任一阶段均可跳过,但至少要包含指令、地址、交替字节或数据阶段之一。nCS在每条指令开始前下降,在每条指令完成后再次上升。如图为QSPI四线模式下的读命令时序。
 +{{ :​icore4t:​icore4t_arm_hal_13_1.png?​direct |}}
 +== (1) 指令阶段 ==
 +
 +  * 这一阶段,将在QUADSPI_CCR[7:​0]寄存器的INSTRUCTION字段中配置的一条8位指令发送到Flash,指定待执行操作的类型。尽管大多数 Flash从IO0/​SO信号(单线 SPI 模式)只能以一次1位的方式接收指令,但指令阶段可选择一次发送2位(在双线SPI模式中通过IO0/​IO1)或一次发送4位(在四线SPI模式中通过IO0/​IO1/​IO2/​IO3)。这可通过 QUADSPI_CCR[9:​8]寄存器中的IMODE[1:​0]字段进行配置。
 +  * 若IMODE = 00,则跳过指令阶段,命令序列从地址阶段(如果存在)开始。
 +== (2) 地址阶段 ==
 +
 +  * 在地址阶段,将1-4字节发送到Flash,指示操作地址。待发送的地址字节数在QUADSPI_CCR[13:​12]寄存器的ADSIZE[1:​0]字段中进行配置。在间接模式和自动轮询模式下,待发送的地址字节在QUADSPI_AR寄存器的ADDRESS[31:​0]中指定在内存映射模式下,则通过 AHB(来自于 Cortex ® 或 DMA)直接给出地址。地址阶段可一次发送1 位(在单线SPI模式中通过SO)、2位(在双线SPI模式中通过IO0/​IO1)或4位(在四线 SPI 模式中通过 IO0/​IO1/​IO2/​IO3)。这可通过QUADSPI_CCR[11:​10]寄存器中的ADMODE[1:​0]字段进行配置。
 +  * 若ADMODE = 00,则跳过地址阶段,命令序列直接进入下一阶段(如果存在)。
 +== (3) 交换字节阶段 ==
 +
 +  * 在交替字节阶段,将1-4字节发送到Flash,一般用于控制操作模式。待发送的交替字节数在QUADSPI_CCR[17:​16]寄存器的ABSIZE[1:​0]字段中进行配置。待发送的字节在QUADSPI_ABR寄存器中指定。
 +  * 交替字节阶段可一次发送1位(在单线 SPI 模式中通过 SO)、2位(在双线SPI模式中通过 IO0/​IO1)或4位(在四线SPI模式中通IO0/​IO1/​IO2/​IO3)。这可通过QUADSPI_CCR[15:​14]寄存器中的ABMODE[1:​0]字段进行配置。
 +  * 若ABMODE = 00,则跳过交替字节阶段,命令序列直接进入下一阶段(如果存在)。交替字节阶段存在仅需发送单个半字节而不是一个全字节的情况,比如采用双线模式并且仅使用两个周期发送交替字节时。在这种情况下,固件可采用四线模式(ABMODE = 11)并发送一个字节,方法是ALTERNATE的位7和3置“1”(IO3 保持高电平)且位6和2置“0”(IO2 线保持低电平)。此时,半字节的高 2 位存放在ALTERNATE的位 4:3,低 2位存放在位1和0中。例如,如果半字节2 (0010) 通过IO0/​IO1发送,则ALTERNATE 应设置为0x8A (1000_1010)。
 +== (4) 空指令周期阶段 ==
 +
 +  * 在空指令周期阶段,给定的1-31个周期内不发送或接收任何数据,目的是当采用更高的时钟频率时,给Flash留出准备数据阶段的时间。这一阶段中给定的周期数在QUADSPI_CCR[22:​18]寄存器的DCYC[4:​0]字段中指定。在SDR和DDR模式下,持续时间被指定为一定个数的全时钟周期。若DCYC为零,则跳过空指令周期阶段,命令序列直接进入数据阶段(如果存在)。空指令周期阶段的操作模式由DMODE确定。为确保数据信号从输出模式转变为输入模式有足够的“周转”时间,使用双线和四线模式从Flash接收数据时,至少需要指定一个空指令周期。
 +== (5) 数据阶段 ==
 +
 +  * 在数据阶段,可从Flash接收或向其发送任意数量的字节。
 +  * 在间接模式和自动轮询模式下,待发送/​接收的字节数在QUADSPI_DLR寄存器中指定。在间接写入模式下,发送到Flash的数据必须写入QUADSPI_DR寄存器。在间接读取模式下,通过读取QUADSPI_DR寄存器获得从 Flash 接收的数据。在内存映射模式下,读取的数据通过AHB直接发送回Cortex或DMA。数据阶段可一次发送/​接收1位(在单线SPI 模式中通过SO)、2位(在双线 SPI 模式中通过IO0/​IO1)或4位(在四线SPI模式中通过IO0/​IO1/​IO2/​IO3)。这可通过QUADSPI_CCR[15:​14] 寄存器中的ABMODE[1:​0]字段进行配置。若DMODE = 00,则跳过数据阶段,命令序列在拉高nCS时立即完成。这一配置仅可用于仅间接写入模式。
 +==== 四、 实验程序 ====
 +
 +=== 1.主函数 ===
 +<code c>
 +int main(void)  ​
 +{  ​
 +    int i;  ​
 +    int temp;  ​
 +    unsigned char write_buffer[4096];  ​
 +    unsigned char read_buffer[4096];  ​
 +    HAL_Init();  ​
 +
 +    SystemClock_Config();  ​
 +    i2c.initialize();  ​
 +    axp152.initialize();  ​
 +    axp152.set_dcdc1(3500);//​[ARM & FPGA BK1/2/6 &​OTHER]  ​
 +    axp152.set_dcdc2(1200);//​[FPGA INT & PLL D]  ​
 +    axp152.set_aldo1(2500);//​[FPGA PLL A]  ​
 +    axp152.set_dcdc4(3300);//​[POWER_OUTPUT]  ​
 +      ​
 +    axp152.set_dcdc3(3300);//​[FPGA BK4][Adjustable]  ​
 +    axp152.set_aldo2(3300);//​[FPGA BK3][Adjustable]  ​
 +    axp152.set_dldo1(3300);//​[FPGA BK7][Adjustable]  ​
 +    axp152.set_dldo2(3300);//​[FPGA BK5][Adjustable]  ​
 +  ​
 +    MX_GPIO_Init();  ​
 +    MX_USART2_UART_Init();  ​
 +    MX_QUADSPI_Init();  ​
 +    BSP_QSPI_Init();  ​
 +    usart2.initialize(115200);  ​
 +    usart2.printf("​\x0c"​); ​                      //​清屏
 +    usart2.printf("​\033[1;​32;​40m"​); ​             //​设置终端字体为绿色 ​
 +    usart2.printf("​Hello,​I am iCore4T!\r\n\r\n"​); ​        
 +    temp = BSP_QSPI_FLASH_ReadID();  ​
 +    usart2.printf("​FLASH ID: 0x%X\r\n",​temp);  ​
 +   for(i = 0;i < 4096;i ++){      ​
 +        write_buffer[i] = i % 256;  ​
 +        read_buffer[i] = 0;  ​
 +    }  ​
 +    BSP_QSPI_Write(write_buffer,​0,​4096); ​ //写数据
 +    BSP_QSPI_Read(read_buffer,​0,​4096); ​    //​读数据
 +    for(i = 0;i < 4096;i ++){     
 +        if(read_buffer[i] != write_buffer[i]){  ​
 +            usart2.printf("​FLASH ERROR!\r\n"​);  ​
 +            while(1);  ​
 +        }  ​
 +    }  ​
 +    usart2.printf("​FLASH TEST OK!\r\n"​); ​     ​
 +    while (1)  ​
 +    {   
 +    }  ​
 +}  ​
 +
 +</​code>​
 + 
 +=== 2.QSPI初始化函数 ===
 +初始化好QSPI外设后,还要初始化初始化QSPI存储器,需要先复位存储器,使能写操作,配置状态寄存器才可进行数据读写操作。
 +<code c>
 +uint8_t BSP_QSPI_Init(void)  ​
 +{  ​
 +  QSPIHandle.Instance = QUADSPI;  ​
 +  /* 调用DeInit函数重置驱动程序 */  ​
 +  if (HAL_QSPI_DeInit(&​QSPIHandle) != HAL_OK)  ​
 +  {  ​
 +    return QSPI_ERROR;  ​
 +  }  ​
 +  /* 系统级初始化 */  ​
 +  BSP_QSPI_MspInit(&​QSPIHandle,​ NULL);  ​
 +  /*  QSPI初始化 */  ​
 +  /* 时钟预分频器设置为1,因此QSPI时钟= 240MHz /(1 + 1)= 120MHz */ 
 +  QSPIHandle.Init.ClockPrescaler ​    = 1;  ​
 +  QSPIHandle.Init.FifoThreshold ​     = POSITION_VAL(W25Q64_FLASH_SIZE) - 1;  ​
 +  QSPIHandle.Init.SampleShifting ​    = QSPI_SAMPLE_SHIFTING_NONE;  ​
 +  QSPIHandle.Init.FlashSize ​         = POSITION_VAL(W25Q64_FLASH_SIZE) - 1;  ​
 +  QSPIHandle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_6_CYCLE;  ​
 +  QSPIHandle.Init.ClockMode ​         = QSPI_CLOCK_MODE_0;  ​
 +  QSPIHandle.Init.FlashID ​           = QSPI_FLASH_ID_1;  ​
 +  QSPIHandle.Init.DualFlash ​         = QSPI_DUALFLASH_DISABLE;  ​
 +  if (HAL_QSPI_Init(&​QSPIHandle) != HAL_OK)  ​
 +  {  ​
 +    return QSPI_ERROR;  ​
 +  }  ​
 +  return QSPI_OK;  ​
 +}  ​
 +
 +</​code> ​
 +=== 3.QSPI读函数 ===
 +要从存取器中读取数据,首先要用一个指针指向读回来的数据,并确定数据的首地址,数据大小,通过库函数HAL_QSPI_Command发送配置命令,然后调用库函数HAL_QSPI_Receive接收数据,最后等待操作完成,代码如下:
 +<code c>
 +uint8_t BSP_QSPI_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size)  ​
 +{  ​
 +  QSPI_CommandTypeDef s_command;  ​
 +  /* 初始化读取命令 */  ​
 +  s_command.InstructionMode ​  = QSPI_INSTRUCTION_1_LINE;  ​
 +  s_command.Instruction ​      = QUAD_OUT_FAST_READ_CMD;  ​
 +  s_command.AddressMode ​      = QSPI_ADDRESS_1_LINE;  ​
 +  s_command.AddressSize ​      = QSPI_ADDRESS_24_BITS;  ​
 +  s_command.Address ​          = ReadAddr;  ​
 +  s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;  ​
 +  s_command.DataMode ​         = QSPI_DATA_4_LINES;  ​
 +  s_command.DummyCycles ​      = W25Q64_DUMMY_CYCLES_READ_QUAD;  ​
 +  s_command.NbData ​           = Size;  ​
 +  s_command.DdrMode ​          = QSPI_DDR_MODE_DISABLE;  ​
 +  s_command.DdrHoldHalfCycle ​ = QSPI_DDR_HHC_ANALOG_DELAY;  ​
 +  s_command.SIOOMode ​         = QSPI_SIOO_INST_EVERY_CMD; ​    
 +  /* 配置命令 */  ​
 +  if (HAL_QSPI_Command(&​QSPIHandle,​ &​s_command,​ HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)  ​
 +  {  ​
 +    return QSPI_ERROR;  ​
 +  }  ​
 +  /* 数据接收 */  ​
 +  if (HAL_QSPI_Receive(&​QSPIHandle,​ pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)  ​
 +  {  ​
 +    return QSPI_ERROR;  ​
 +  }  ​
 +  return QSPI_OK;  ​
 +}  ​
 +
 +</​code> ​
 +pData:指向要读取的数据的指针
 +ReadAddr:读取起始地址
 +Size:要读取的数据大小
 +=== 4.QSPI写函数 ===
 +
 +要从存取器中写入数据,首先要用一个指针指向写入的数据,并确定数据的首地址,数据大小,根据写入地址及大小判断存储器的页面,然后通过库函数HAL_QSPI_Command发送配置命令,再调用库函数HAL_QSPI_Transmit逐页写入数据,最后等待操作完成。代码如下:
 +<code c>
 +uint8_t BSP_QSPI_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size)
 +{  ​
 +  QSPI_CommandTypeDef s_command;  ​
 +  uint32_t end_addr, current_size,​ current_addr;  ​
 +  /* 计算写地址和页面末尾之间的大小 */  ​
 +  current_size = W25Q64_PAGE_SIZE - (WriteAddr % W25Q64_PAGE_SIZE);  ​
 +  /* 检查数据大小是否小于页面中的剩余位置*/  ​
 +  if (current_size > Size)  ​
 +  {  ​
 +    current_size = Size;  ​
 +  }  ​
 +  /* 初始化地址变量 */  ​
 +  current_addr = WriteAddr;  ​
 +  end_addr = WriteAddr + Size;  ​
 +  /* 初始化程序命令 */  ​
 +  s_command.InstructionMode ​  = QSPI_INSTRUCTION_1_LINE;  ​
 +  s_command.Instruction ​      = QUAD_IN_FAST_PROG_CMD;  ​
 +  s_command.AddressMode ​      = QSPI_ADDRESS_1_LINE;  ​
 +  s_command.AddressSize ​      = QSPI_ADDRESS_24_BITS;  ​
 +  s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;  ​
 +  s_command.DataMode ​         = QSPI_DATA_4_LINES;  ​
 +  s_command.DummyCycles ​      = 0;  ​
 +  s_command.DdrMode ​          = QSPI_DDR_MODE_DISABLE;  ​
 +  s_command.DdrHoldHalfCycle ​ = QSPI_DDR_HHC_ANALOG_DELAY;  ​
 +  s_command.SIOOMode ​         = QSPI_SIOO_INST_EVERY_CMD;  ​
 +  /* 逐页执行写入*/  ​
 +  do  ​
 +  {  ​
 +    s_command.Address = current_addr;  ​
 +    s_command.NbData ​ = current_size;  ​
 +    /* 启用写操作 */  ​
 +    if (QSPI_WriteEnable(&​QSPIHandle) != QSPI_OK)  ​
 +    {  ​
 +      return QSPI_ERROR;  ​
 +    }  ​
 +     /* 配置命令 */  ​
 +    if (HAL_QSPI_Command(&​QSPIHandle,​ &​s_command,​ HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)  ​
 +    {  ​
 +      return QSPI_ERROR;  ​
 +    }  ​
 +    /* 传输数据 */  ​
 +    if (HAL_QSPI_Transmit(&​QSPIHandle,​ pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)  ​
 +    {  ​
 +      return QSPI_ERROR;  ​
 +    }  ​
 +    /* 配置自动轮询模式以等待程序结束 */  ​
 +    if (QSPI_AutoPollingMemReady(&​QSPIHandle,​ HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK)  ​
 +    {  ​
 +      return QSPI_ERROR;  ​
 +    }  ​
 +      /* 为下一页编程更新地址和变量大小 */  ​
 +    current_addr += current_size;  ​
 +    pData += current_size;  ​
 +    current_size = ((current_addr + W25Q64_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : W25Q64_PAGE_SIZE;  ​
 +  } while (current_addr < end_addr);  ​
 +  return QSPI_OK;  ​
 +}  ​
 +
 +</​code> ​
 +pData:指向要写入的数据的指针
 +ReadAddr:写入起始地址
 +Size:要写入的数据大小
 +=== 5.QSPI_CommandTypeDe通信配置命令结构体 ===
 +<code c>
 +typedef struct  ​
 +{  ​
 +  uint32_t Instruction; ​       /* 设置通信指令,指定要发送到外部 SPI 设备的指令。仅可在 BUSY = 0 时修改该字段*/  ​
 +  uint32_t Address; ​           /* 指定要发送到外部 Flash 的地址,BUSY = 0 或 FMODE = 11(内存映射模式)时,将忽略写入该字段。在双闪存模式下,由于地址始终为偶地址,ADDRESS[0] 自动保持为“0” */  ​
 +  uint32_t AlternateBytes; ​    /* 指定要在地址后立即发送到外部 SPI 设备的可选数据,仅可在 BUSY = 0 时修改该字段。*/  ​
 +  uint32_t AddressSize; ​       /* 定义地址长度,可以是8位,16位,24位或者32位 */  ​
 +uint32_t AlternateBytesSize;​ /* 定义交替字节长度,可以是8位,16位,24位或者32位 */  ​
 +  uint32_t DummyCycles; ​       /* 定义空指令阶段的持续时间,在 SDR 和 DDR 模式下,它指定 CLK 周期数 (0-31) */  ​
 +  uint32_t InstructionMode; ​   /* 定义指令阶段的操作模式,00:无指令;01:单线传输指令;10:双线传输指令;11:四线传输指令*/  ​
 +  uint32_t AddressMode; ​       /* 定义地址阶段的操作模式,00:无地址;01:单线传输地址;10:双线传输地址;11:四线传输地址*/  ​
 +  uint32_t AlternateByteMode; ​ /* 定义交替字节阶段的操作模式00:无交替字节;01:单线传输交替字节;10:双线传输交替字节;11:四线传输交替字节 */  ​
 +  uint32_t DataMode; ​          /* 定义数据阶段的操作模式,00:无数据;01:单线传输数据;10:双线传输数据;11:四线传输数据。该字段还定义空指令阶段的操作模式 */  ​
 +  uint32_t NbData; ​            /* 设置数据长度,在间接模式和状态轮询模式下待检索的数据数量(值 + 1)。对状态轮询模式应使用不大于 3 的值(表示 4 字节)*/  ​
 +  uint32_t DdrMode; ​           /* 为地址、交替字节和数据阶段设置 DDR 模式,0:禁止 DDR 模式;1:使能 DDR 模式 */  ​
 +  uint32_t DdrHoldHalfCycle; ​  /* 设置DDR 模式下数据输出延迟 1/4 个 QUADSPI 输出时钟周期,0:使用模拟延迟来延迟数据输出;1:数据输出延迟 1/4 个 QUADSPI 输出时钟周期。仅在 DDR 模式下激活*/  ​
 +  uint32_t SIOOMode; ​          /* 设置仅发送指令一次模式,IMODE = 00 时,该位不起作用。0:在每个事务中发送指令;1:仅为第一条命令发送指令 */  ​
 +}QSPI_CommandTypeDef;  ​
 +
 +</​code> ​
 +==== 五、 实验步骤 ====
 +
 +  - 把仿真器与iCore4T的SWD调试口相连(直接相连或者通过转接器相连);
 +  - 把iCore4T通过Micro USB线与计算机相连,为iCore4T供电;
 +  - 打开Keil MDK 开发环境,并打开本实验工程;
 +  - 烧写程序到iCore4T上;
 +  - 也可以进入Debug 模式,单步运行或设置断点验证程序逻辑。
 +==== 六、 实验现象 ====
 +读写测试成功,在终端显示出“FLASH TEST OK!”。测试失败,则在终端显示“FLASH ERROR!”
 +{{ :​icore4t:​icore4t_arm_hal_13_2.png?​direct |}}
  
icore4t_13.txt · 最后更改: 2022/03/22 10:40 由 sean