spi概述spi是串行外设接口(serial peripheral interface)的缩写,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为pcb的布局上节省空间,提供方便,正是出于这种简单易用的特性,越来越多的芯片集成了这种通信协议,比如 eeprom,flash,实时时钟,ad转换器。 w25q64 是一款spi接口的flash芯片,其存储空间为 64mbit,相当于8m字节。w25q64可以支持 spi 的模式 0 和模式 3,也就是 cpol=0/cpha=0 和cpol=1/cpha=1 这两种模式。 最近在弄st和gd的课程,需要gd样片的可以加群申请:6_15061293 。
视频教学[https://www.bilibili.com/video/bv13g411z7gi/]
csdn课程课程更加详细。
[https://download.csdn.net/course/detail/37152]
生成例程这里准备了自己绘制的开发板进行验证。
配置时钟树,配置时钟为64m。
查看原理图,pa9和pa10设置为开发板的串口。
配置串口。
由于需要输入数据,开启dma进行接收。
中断。
spi配置在开发板中有arduino接口,配置这几个接口为spi。
本次实验使用的spi与flash通信,配置如下。 spi的通信原理很简单,它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根也可以(单向传输时)。也是所有基于spi的设备共有的,它们是miso(主设备数据输入)、mosi(主设备数据输出)、sclk(时钟)、cs(片选)。
(1)miso– master input slave output,主设备数据输入,从设备数据输出;
(2)mosi– master output slave input,主设备数据输出,从设备数据输入;
(3)sclk – serial clock,时钟信号,由主设备产生;
(4)cs – chip select,从设备使能信号,由主设备控制。
负责通讯的3根线了。通讯是通过数据交换完成的,这里先要知道spi是串行通讯协议,也就是说数据是一位一位的传输的。这就是sclk时钟线存在的原因,由sclk提供时钟脉冲,sdi,sdo则基于此脉冲完成数据传输。数据输出通过 sdo线,数据在时钟上升沿或下降沿时改变,在紧接着的下降沿或上升沿被读取。完成一位数据传输,输入也使用同样原理。因此,至少需要8次时钟信号的改变(上沿和下沿为一次),才能完成8位数据的传输。 时钟信号线sclk只能由主设备控制,从设备不能控制。同样,在一个基于spi的设备中,至少有一个主设备。这样的传输方式有一个优点,在数据位的传输过程中可以暂停,也就是时钟的周期可以为不等宽,因为时钟线由主设备控制,当没有时钟跳变时,从设备不采集或传送数据。spi还是一个数据交换协议:因为spi的数据输入和输出线独立,所以允许同时完成数据的输入和输出。芯片集成的spi串行同步时钟极性和相位可以通过寄存器配置,io模拟的spi串行同步时钟需要根据从设备支持的时钟极性和相位来通讯。 最后,spi接口的一个缺点:没有指定的流控制,没有应答机制确认是否接收到数据。
其中,cs是从芯片是否被主芯片选中的控制信号,也就是说只有片选信号为预先规定的使能信号时(高电位或低电位),主芯片对此从芯片的操作才有效。这就使在同一条总线上连接多个spi设备成为可能。 随便配置一个端口为cs片选,并且命名为cs。
nor flashnor flash是一种非易失闪存技术,是intel在1988年创建。是市场上两种主要的非易失闪存技术之一。 以gd25q64e为例,该 flash为64m-bit大小,即8192k-byte。
w25q64将8m的容量分为127个块(block),每个块大小为64k字节,每个块又分为16个扇区(sector),每个扇区4k个字节。w25q64的最小擦除单位为一个扇区,也就是每次必须擦除4k个字节。 即4k16128=8192k=8m
w25q64的原理及应用复位初始化对于复位,需要发送0x66和0x99
代码中的初始化。
/* reset operations */#define reset_enable_cmd 0x66#define reset_memory_cmd 0x99/** * @brief initializes the w25q128fv interface. * @retval none */uint8_t bsp_w25qx_init(void){ /* reset w25qxxx */ bsp_w25qx_reset(); return bsp_w25qx_getstatus();}/** * @brief this function reset the w25qx. * @retval none */static void bsp_w25qx_reset(void){ uint8_t cmd[2] = {reset_enable_cmd,reset_memory_cmd}; w25qx_enable(); /* send the reset command */ hal_spi_transmit(&hspi1, cmd, 2, w25qx_timeout_value); w25qx_disable();}
id对于兆易创新w25q64,主要有三种查询id方式。
可以使用90h查询设备id,以判断是否是w25q64设备。
/* identification operations */#define read_id_cmd 0x9f/** * @brief read manufacture/device id. * @param return value address * @retval none */void bsp_w25qx_read_id(uint8_t *id){ uint8_t cmd[4] = {read_id_cmd,0x00,0x00,0x00}; w25qx_enable(); /* send the read id command */ hal_spi_transmit(&hspi1, cmd, 4, w25qx_timeout_value); /* reception of the data */ hal_spi_receive(&hspi1,id, 2, w25qx_timeout_value); w25qx_disable();}
读取数据对于兆易创新w25q64,读取数据使用0x03指令,后面添加需要读取的数据地址。 数据可以一直进行读取,当不需要读取数据时候将片选cs拉高,关闭时钟sclk即可。
#define read_cmd 0x03/** * @brief reads an amount of data from the qspi memory. * @param pdata: pointer to data to be read * @param readaddr: read start address * @param size: size of data to read * @retval qspi memory status */uint8_t bsp_w25qx_read(uint8_t* pdata, uint32_t readaddr, uint32_t size){ uint8_t cmd[4]; /* configure the command */ cmd[0] = read_cmd; cmd[1] = (uint8_t)(readaddr > > 16); cmd[2] = (uint8_t)(readaddr > > 8); cmd[3] = (uint8_t)(readaddr); w25qx_enable(); /* send the read id command */ hal_spi_transmit(&hspi1, cmd, 4, w25qx_timeout_value); /* reception of the data */ if (hal_spi_receive(&hspi1, pdata,size,w25qx_timeout_value) != hal_ok) { return w25qx_error; } w25qx_disable(); return w25qx_ok;}以读取10个数据为例子,波形如下所示。
bsp_w25qx_read(rdata2,0x1000,0x00a);
擦除扇区最小的擦除单位是扇区,擦除指令为0x20和3字节的地址。
#define sector_erase_cmd 0x20uint8_t bsp_w25qx_erase_block(uint32_t address){ uint8_t cmd[4]; uint32_t tickstart = hal_gettick(); cmd[0] = sector_erase_cmd; cmd[1] = (uint8_t)(address > > 16); cmd[2] = (uint8_t)(address > > 8); cmd[3] = (uint8_t)(address); /* enable write operations */ bsp_w25qx_writeenable(); /*select the flash: chip select low */ w25qx_enable(); /* send the read id command */ hal_spi_transmit(&hspi1, cmd, 4, w25qx_timeout_value); /*deselect the flash: chip select high */ w25qx_disable(); /* wait the end of flash writing */ while(bsp_w25qx_getstatus() == w25qx_busy); { /* check for the timeout */ if((hal_gettick() - tickstart) > w25q128fv_sector_erase_max_time) { return w25qx_timeout; } } return w25qx_ok;}
写数据对于写数据到flash中,使用0x02指令进行写数据,后面还需要指定24位地址,才能进行写数据。
#define page_prog_cmd 0x02/** * @brief writes an amount of data to the qspi memory. * @param pdata: pointer to data to be written * @param writeaddr: write start address * @param size: size of data to write,no more than 256byte. * @retval qspi memory status */uint8_t bsp_w25qx_write(uint8_t* pdata, uint32_t writeaddr, uint32_t size){ uint8_t cmd[4]; uint32_t end_addr, current_size, current_addr; uint32_t tickstart = hal_gettick(); /* calculation of the size between the write address and the end of the page */ current_addr = 0; while (current_addr 256 bytes } current_size = current_addr - writeaddr; /* check if the size of the data is less than the remaining place in the page */ if (current_size > size) { current_size = size; } /* initialize the adress variables *///写入地址大小范围 current_addr = writeaddr; end_addr = writeaddr + size; /* perform the write page by page */ do { /* configure the command */ cmd[0] = page_prog_cmd; cmd[1] = (uint8_t)(current_addr > > 16); cmd[2] = (uint8_t)(current_addr > > 8); cmd[3] = (uint8_t)(current_addr); /* enable write operations */ bsp_w25qx_writeenable(); w25qx_enable(); /* send the command */ if (hal_spi_transmit(&hspi1,cmd, 4, w25qx_timeout_value) != hal_ok) { return w25qx_error; } /* transmission of the data */ if (hal_spi_transmit(&hspi1, pdata,current_size, w25qx_timeout_value) != hal_ok) { return w25qx_error; } w25qx_disable(); /* wait the end of flash writing */ while(bsp_w25qx_getstatus() == w25qx_busy); { /* check for the timeout */ if((hal_gettick() - tickstart) > w25qx_timeout_value) { return w25qx_timeout; } } /* update the address and size variables for next page programming */ current_addr += current_size; pdata += current_size; current_size = ((current_addr + w25q128fv_page_size) > end_addr) ? (end_addr - current_addr) : w25q128fv_page_size; } while (current_addr w25qx_timeout_value) { return w25qx_timeout; } } return w25qx_ok;}/** * @brief read manufacture/device id. * @param return value address * @retval none */void bsp_w25qx_read_id(uint8_t *id){ uint8_t cmd[4] = {read_id_cmd,0x00,0x00,0x00}; w25qx_enable(); /* send the read id command */ hal_spi_transmit(&hspi1, cmd, 4, w25qx_timeout_value); /* reception of the data */ hal_spi_receive(&hspi1,id, 2, w25qx_timeout_value); w25qx_disable();}/** * @brief reads an amount of data from the qspi memory. * @param pdata: pointer to data to be read * @param readaddr: read start address * @param size: size of data to read * @retval qspi memory status */uint8_t bsp_w25qx_read(uint8_t* pdata, uint32_t readaddr, uint32_t size){ uint8_t cmd[4]; /* configure the command */ cmd[0] = read_cmd; cmd[1] = (uint8_t)(readaddr > > 16); cmd[2] = (uint8_t)(readaddr > > 8); cmd[3] = (uint8_t)(readaddr); w25qx_enable(); /* send the read id command */ hal_spi_transmit(&hspi1, cmd, 4, w25qx_timeout_value); /* reception of the data */ if (hal_spi_receive(&hspi1, pdata,size,w25qx_timeout_value) != hal_ok) { return w25qx_error; } w25qx_disable(); return w25qx_ok;}/** * @brief writes an amount of data to the qspi memory. * @param pdata: pointer to data to be written * @param writeaddr: write start address * @param size: size of data to write,no more than 256byte. * @retval qspi memory status */uint8_t bsp_w25qx_write(uint8_t* pdata, uint32_t writeaddr, uint32_t size){ uint8_t cmd[4]; uint32_t end_addr, current_size, current_addr; uint32_t tickstart = hal_gettick(); /* calculation of the size between the write address and the end of the page */ current_addr = 0; while (current_addr 256 bytes } current_size = current_addr - writeaddr; /* check if the size of the data is less than the remaining place in the page */ if (current_size > size) { current_size = size; } /* initialize the adress variables *///写入地址大小范围 current_addr = writeaddr; end_addr = writeaddr + size; /* perform the write page by page */ do { /* configure the command */ cmd[0] = page_prog_cmd; cmd[1] = (uint8_t)(current_addr > > 16); cmd[2] = (uint8_t)(current_addr > > 8); cmd[3] = (uint8_t)(current_addr); /* enable write operations */ bsp_w25qx_writeenable(); w25qx_enable(); /* send the command */ if (hal_spi_transmit(&hspi1,cmd, 4, w25qx_timeout_value) != hal_ok) { return w25qx_error; } /* transmission of the data */ if (hal_spi_transmit(&hspi1, pdata,current_size, w25qx_timeout_value) != hal_ok) { return w25qx_error; } w25qx_disable(); /* wait the end of flash writing */ while(bsp_w25qx_getstatus() == w25qx_busy); { /* check for the timeout */ if((hal_gettick() - tickstart) > w25qx_timeout_value) { return w25qx_timeout; } } /* update the address and size variables for next page programming */ current_addr += current_size; pdata += current_size; current_size = ((current_addr + w25q128fv_page_size) > end_addr) ? (end_addr - current_addr) : w25q128fv_page_size; } while (current_addr > 16); cmd[2] = (uint8_t)(address > > 8); cmd[3] = (uint8_t)(address); /* enable write operations */ bsp_w25qx_writeenable(); /*select the flash: chip select low */ w25qx_enable(); /* send the read id command */ hal_spi_transmit(&hspi1, cmd, 4, w25qx_timeout_value); /*deselect the flash: chip select high */ w25qx_disable(); /* wait the end of flash writing */ while(bsp_w25qx_getstatus() == w25qx_busy); { /* check for the timeout */ if((hal_gettick() - tickstart) > w25q128fv_sector_erase_max_time) { return w25qx_timeout; } } return w25qx_ok;}/** * @brief erases the entire qspi memory.this function will take a very long time. * @retval qspi memory status */uint8_t bsp_w25qx_erase_chip(void){ uint8_t cmd[4]; uint32_t tickstart = hal_gettick(); cmd[0] = sector_erase_cmd; /* enable write operations */ bsp_w25qx_writeenable(); /*select the flash: chip select low */ w25qx_enable(); /* send the read id command */ hal_spi_transmit(&hspi1, cmd, 1, w25qx_timeout_value); /*deselect the flash: chip select high */ w25qx_disable(); /* wait the end of flash writing */ while(bsp_w25qx_getstatus() != w25qx_busy); { /* check for the timeout */ if((hal_gettick() - tickstart) > w25q128fv_bulk_erase_max_time) { return w25qx_timeout; } } return w25qx_ok;}w25qx.h/*********************************************************************************************************** file : w25qx.h* hardware environment: * build environment : realview mdk-arm version: 5.15* version : v1.0* by : ** (c) copyright 2005-2015, waveshare* http://www.waveshare.net* all rights reserved**********************************************************************************************************//* define to prevent recursive inclusion -------------------------------------*/#ifndef __w25qx_h#define __w25qx_h#ifdef __cplusplus extern c {#endif /* includes ------------------------------------------------------------------*/#include stm32f1xx.h#include spi.h/** @addtogroup bsp * @{ */ /** @addtogroup components * @{ */ /** @addtogroup w25q128fv * @{ *//** @defgroup w25q128fv_exported_types * @{ *//** * @} */ /** @defgroup w25q128fv_exported_constants * @{ *//** * @brief w25q128fv configuration */ #define w25q128fv_flash_size 0x1000000 /* 128 mbits = > 16mbytes */#define w25q128fv_sector_size 0x10000 /* 256 sectors of 64kbytes */#define w25q128fv_subsector_size 0x1000 /* 4096 subsectors of 4kbytes */#define w25q128fv_page_size 0x100 /* 65536 pages of 256 bytes */#define w25q128fv_dummy_cycles_read 4#define w25q128fv_dummy_cycles_read_quad 10#define w25q128fv_bulk_erase_max_time 250000#define w25q128fv_sector_erase_max_time 3000#define w25q128fv_subsector_erase_max_time 800#define w25qx_timeout_value 1000/** * @brief w25q128fv commands */ /* reset operations */#define reset_enable_cmd 0x66#define reset_memory_cmd 0x99#define enter_qpi_mode_cmd 0x38#define exit_qpi_mode_cmd 0xff/* identification operations */#define read_id_cmd 0x90#define dual_read_id_cmd 0x92#define quad_read_id_cmd 0x94#define read_jedec_id_cmd 0x9f/* read operations */#define read_cmd 0x03#define fast_read_cmd 0x0b#define dual_out_fast_read_cmd 0x3b#define dual_inout_fast_read_cmd 0xbb#define quad_out_fast_read_cmd 0x6b#define quad_inout_fast_read_cmd 0xeb/* write operations */#define write_enable_cmd 0x06#define write_disable_cmd 0x04/* register operations */#define read_status_reg1_cmd 0x05#define read_status_reg2_cmd 0x35#define read_status_reg3_cmd 0x15#define write_status_reg1_cmd 0x01#define write_status_reg2_cmd 0x31#define write_status_reg3_cmd 0x11/* program operations */#define page_prog_cmd 0x02#define quad_input_page_prog_cmd 0x32/* erase operations */#define sector_erase_cmd 0x20#define chip_erase_cmd 0xc7#define prog_erase_resume_cmd 0x7a#define prog_erase_suspend_cmd 0x75/* flag status register */#define w25q128fv_fsr_busy ((uint8_t)0x01) /*!< busy */#define w25q128fv_fsr_wren ((uint8_t)0x02) /*!< write enable */#define w25q128fv_fsr_qe ((uint8_t)0x02) /*!< quad enable */#define w25qx_enable() hal_gpio_writepin(cs_gpio_port, cs_pin, gpio_pin_reset)#define w25qx_disable() hal_gpio_writepin(cs_gpio_port, cs_pin, gpio_pin_set)#define w25qx_ok ((uint8_t)0x00)#define w25qx_error ((uint8_t)0x01)#define w25qx_busy ((uint8_t)0x02)#define w25qx_timeout ((uint8_t)0x03)uint8_t bsp_w25qx_init(void);static void bsp_w25qx_reset(void);static uint8_t bsp_w25qx_getstatus(void);uint8_t bsp_w25qx_writeenable(void);void bsp_w25qx_read_id(uint8_t *id);uint8_t bsp_w25qx_read(uint8_t* pdata, uint32_t readaddr, uint32_t size);uint8_t bsp_w25qx_write(uint8_t* pdata, uint32_t writeaddr, uint32_t size);uint8_t bsp_w25qx_erase_block(uint32_t address);uint8_t bsp_w25qx_erase_chip(void);/** * @} *//** @defgroup w25q128fv_exported_functions * @{ */ /** * @} */ /** * @} */ /** * @} */ /** * @} */#ifdef __cplusplus}#endif#endif /* __w25qx_h */案例向0扇区(0块0扇区),17扇区(1块1扇区),34扇区(2块2扇区)分别写入0x200的数据。
头文件定义/* user code begin includes */#include stdio.h#include w25qx.h/* user code end includes */串口接收和flash数组定义/* user code begin pv */#define buffersize 255 //可以接收的最大字符个数 uint8_t receivebuff[buffersize]; //接收缓冲区uint8_t recv_end_flag = 0,rx_len;//接收完成中断标志,接收到字符长度uint8_t wdata1[0x200];uint8_t wdata2[0x200];uint8_t wdata3[0x200];uint8_t rdata1[0x200];uint8_t rdata2[0x200];uint8_t rdata3[0x200];uint8_t id[4];uint32_t i;uint8_t flag[1] ;int i_flag = 0;/* user code end pv */串口重定向/* user code begin pfp */void uart1_data(void);#ifdef __gnuc__ //串口重定向#define putchar_prototype int __io_putchar(int ch)#else#define putchar_prototype int fputc(int ch, file *f)#endif putchar_prototype{ hal_uart_transmit(&huart1 , (uint8_t *)&ch, 1, 0xffff); return ch;}/* user code end pfp */串口中断设置#include stm32f1xx_it.c文件中断外部变量引用:
/* user code begin 0 */#define buffersize 255 //可接收的最大数据量extern uint8_t recv_end_flag,rx_len,bootfirst;/* user code end 0 */串口2中断函数:
/** * @brief this function handles usart2 global interrupt. */void usart1_irqhandler(void){ /* user code begin usart2_irqn 0 */ /* user code end usart2_irqn 0 */ hal_uart_irqhandler(&huart1); /* user code begin usart2_irqn 1 */ uint32_t temp; if(usart1 == huart1.instance)//判断是否为串口2中断 { if(reset != __hal_uart_get_flag(&huart1,uart_flag_idle))//如果为串口2 { __hal_uart_clear_idleflag(&huart1);//清除中断标志 hal_uart_dmastop(&huart1);//停止dma接收 temp = __hal_dma_get_counter(&hdma_usart1_rx);//获取dma当前还有多少未填充 rx_len = buffersize - temp; //计算串口接收到的数据个数 recv_end_flag = 1; } } /* user code end usart2_irqn 1 */}主程序读取id和flash数据及擦除。
/* user code begin 2 */ printf(gd nor flash案例n); __hal_uart_enable_it(&huart1, uart_it_idle);//使能串口1 idle中断 /*##-1- read the device id ########################*/ bsp_w25qx_init();//初始化w25q128 bsp_w25qx_read_id(id);//读取id if((id[0] != 0xc8) | (id[1] != 0x16)) { error_handler();//如果 id不对打印错误 } else//id正确,打印id { printf(w25q64 id : ); for(i=0;i< 2;i++) { printf(0x%02x ,id[i]); } printf(rnrn); }/**************************读取第0扇区数据**************************************************************/ /*##-3- read the flash ########################*/ /*读取数据,rdata读取数据的指针,起始地址0x00,读取数据长度0x200*/ if(bsp_w25qx_read(rdata1,0x0,0x200)== w25qx_ok) printf(读取原始的0个扇区数据成功!n); else error_handler(); /*打印数据*/ printf(读取原始的0个扇区数据为: rn); for(i =0;i< 0x200;i++) { if(i%20==0) printf(n0扇区第%d到%d的数据为:rn,i,i+19); printf(0x%02x ,rdata1[i]); } printf(n);/**************************读取第17扇区数据**************************************************************/ /*##-3- read the flash ########################*/ /*读取数据,rdata读取数据的指针,起始地址0x1000,读取数据长度0x200*/ if(bsp_w25qx_read(rdata2,0x11000,0x200)== w25qx_ok) printf(读取原始的17个扇区数据成功!n); else error_handler(); /*打印数据*/ printf(读取原始的2个扇区数据为:); for(i =0;i< 0x200;i++) { if(i%20==0) printf(n17扇区第%d到%d的数据为:rn,i,i+19); printf(0x%02x ,rdata2[i]); } printf(n); /**************************读取第34扇区数据**************************************************************/ /*##-3- read the flash ########################*/ /*读取数据,rdata读取数据的指针,起始地址0x2000,读取数据长度0x200*/ if(bsp_w25qx_read(rdata3,0x22000,0x200)== w25qx_ok) printf(读取原始的34个扇区数据成功!n); else error_handler(); /*打印数据*/ printf(读取原始的34个扇区数据为: ); for(i =0;i< 0x200;i++) { if(i%20==0) printf(n34扇区第%d到%d的数据为:rn,i,i+19); printf(0x%02x ,rdata3[i]); } printf(n); /**************************清除第0扇区数据为0**************************************************************/ /*##-2- erase block ##################################*/ if(bsp_w25qx_erase_block(0) == w25qx_ok) printf( qspi erase block okrn); else error_handler(); /*##-2- written to the flash ########################*/ /* fill buffer */ printf( 初始化数据,清零第0扇区前0x200的数据!rn); for(i =0;i< 0x200;i ++) { wdata1[i] = 0; rdata1[i] = 0; } /*写入数据,wdata写入数据的指针,起始地址0x00,写入数据长度0x200*/ if(bsp_w25qx_write(wdata1,0x00,0x200)== w25qx_ok) printf(清零第0扇区前0x200的数据成功!rn); else error_handler(); /*##-3- read the flash ########################*/ /*读取数据,rdata读取数据的指针,起始地址0x00,读取数据长度0x200*/ if(bsp_w25qx_read(rdata1,0x00,0x200)== w25qx_ok) printf(读取第0扇区前0x200数据成功!rnrn); else error_handler(); /*打印数据*/ printf(读取第0扇区前0x200数据为: rn); for(i =0;i< 0x200;i++) { if(i%20==0) printf(n第%d到%d的数据为:rn,i,i+19); printf(0x%02x ,rdata1[i]); } printf(n);/**************************清除第17扇区数据为0**************************************************************/ /*##-2- erase block ##################################*/ if(bsp_w25qx_erase_block(0x11000) == w25qx_ok) printf( qspi erase block okrn); else error_handler(); /*##-2- written to the flash ########################*/ /* fill buffer */ printf( 初始化数据,清零第17扇区前0x200的数据!rn); for(i =0;i< 0x200;i ++) { wdata2[i] = 0; rdata2[i] = 0; } /*写入数据,wdata写入数据的指针,起始地址0x1000,写入数据长度0x200*/ if(bsp_w25qx_write(wdata2,0x11000,0x200)== w25qx_ok) printf(清零第2扇区前0x200的数据成功!rn); else error_handler(); /*##-3- read the flash ########################*/ /*读取数据,rdata读取数据的指针,起始地址0x00,读取数据长度0x200*/ if(bsp_w25qx_read(rdata2,0x11000,0x200)== w25qx_ok) printf(读取第17扇区前0x200数据成功!rnrn); else error_handler(); /*打印数据*/ printf(读取第17扇区前0x200数据为: rn); for(i =0;i< 0x200;i++) { if(i%20==0) printf(n第%d到%d的数据为:rn,i,i+19); printf(0x%02x ,rdata2[i]); } printf(n);/**************************清除第34扇区数据为0**************************************************************/ /*##-2- erase block ##################################*/ if(bsp_w25qx_erase_block(0x22000) == w25qx_ok) printf( qspi erase block okrn); else error_handler(); /*##-2- written to the flash ########################*/ /* fill buffer */ printf( 初始化数据,清零第34扇区前0x200的数据!rn); for(i =0;i< 0x200;i ++) { wdata3[i] = 0; rdata3[i] = 0; } /*写入数据,wdata写入数据的指针,起始地址0x22000,写入数据长度0x200*/ if(bsp_w25qx_write(wdata3,0x22000,0x200)== w25qx_ok) printf(清零第34扇区前0x200的数据成功!rn); else error_handler(); /*##-3- read the flash ########################*/ /*读取数据,rdata读取数据的指针,起始地址0x00,读取数据长度0x200*/ if(bsp_w25qx_read(rdata3,0x22000,0x200)== w25qx_ok) printf(读取第34扇区前0x200数据成功!rnrn); else error_handler(); /*打印数据*/ printf(读取第34扇区前0x200数据为: rn); for(i =0;i< 0x200;i++) { if(i%20==0) printf(n第%d到%d的数据为:rn,i,i+19); printf(0x%02x ,rdata3[i]); } printf(n); /* user code end 2 */主程序。
/* infinite loop */ /* user code begin while */ while (1) { /* user code end while */ /* user code begin 3 */ uart2_data(); hal_delay(100); } /* user code end 3 */数据处理/* user code begin 4 */void uart2_data(void){ if(recv_end_flag ==1)//接收完成标志 {if(receivebuff[0]==0x00) { printf(写入数据长度:%dn,rx_len-2); for(int i =0;i< rx_len-2;i++) { wdata1[ (i+receivebuff[1]) ] = receivebuff[i+2]; } /*##-2- erase block ##################################*/ if(bsp_w25qx_erase_block(0) == w25qx_ok) printf( qspi erase block okrn); else error_handler(); /*写入数据,wdata写入数据的指针,起始地址0x00,写入数据长度0x200*/ if(bsp_w25qx_write(wdata1,0x00,0x200)== w25qx_ok) printf(扇区0数据成功~~~~~~~~~~~~~~~~~~~~~~~~~~!rn); else error_handler(); if(bsp_w25qx_read(rdata1,0x00,0x200)== w25qx_ok) printf(读取扇区0前0x200数据成功!rnrn); else error_handler(); /*打印数据*/ printf(读取扇区0前0x200数据为: rn); for(i =0;i< 0x200;i++) { if(i%20==0) printf(n第%d到%d的数据为:rn,i,i+19); printf(0x%02x ,wdata1[i]); } printf(n); } else if(receivebuff[0]==0x17) { printf(写入数据长度:%dn,rx_len-2); for(int i =0;i< rx_len-2;i++) {// data[i]=receivebuff[i+2]; wdata2[ (i+receivebuff[1]) ] = receivebuff[i+2]; } /*##-17- erase block ##################################*/ if(bsp_w25qx_erase_block(0x11000) == w25qx_ok) printf( qspi erase block okrn); else error_handler(); /*写入数据,wdata写入数据的指针,起始地址0x11000,写入数据长度0x200*/ if(bsp_w25qx_write(wdata2,0x11000,0x200)== w25qx_ok) printf(扇区17数据成功~~~~~~~~~~~~~~~~~~~~~~~~~~!rn); else error_handler(); if(bsp_w25qx_read(rdata2,0x11000,0x200)== w25qx_ok) printf(读取扇区17前0x200数据成功!rnrn); else error_handler(); /*打印数据*/ printf(读取扇区17前0x200数据为: rn); for(i =0;i< 0x200;i++) { if(i%20==0) printf(n第%d到%d的数据为:rn,i,i+19); printf(0x%02x ,rdata2[i]); } printf(n); } else if(receivebuff[0]==0x34) { printf(写入数据长度:%dn,rx_len-2); for(int i =0;i< rx_len-2;i++) {// data[i]=receivebuff[i+2]; wdata3[ (i+receivebuff[1]) ] = receivebuff[i+2]; } /*##-22- erase block ##################################*/ if(bsp_w25qx_erase_block(0x22000) == w25qx_ok) printf( qspi erase block okrn); else error_handler(); /*写入数据,wdata写入数据的指针,起始地址0x22000,写入数据长度0x200*/ if(bsp_w25qx_write(wdata3,0x22000,0x200)== w25qx_ok) printf(扇区34数据成功~~~~~~~~~~~~~~~~~~~~~~~~~~!rn); else error_handler(); if(bsp_w25qx_read(rdata3,0x22000,0x200)== w25qx_ok) printf(读取扇区34前0x200数据成功!rnrn); else error_handler(); /*打印数据*/ printf(读取扇区34前0x200数据为: rn); for(i =0;i< 0x200;i++) { if(i%20==0) printf(n第%d到%d的数据为:rn,i,i+19); printf(0x%02x ,rdata3[i]); } printf(n); } else printf(输入错误!); for(int i = 0; i < rx_len ; i++) //清空接收缓存区 receivebuff[i]=0;//置0 rx_len=0;//接收数据长度清零 recv_end_flag=0;//接收标志位清零 //开启下一次接收 hal_uart_receive_dma(&huart1,(uint8_t*)receivebuff,buffersize); }}/* user code end 4 */演示w25q64芯片型号的id为0xef17,下方读取为0xc816,所以读取成功。
开机会打印出0,17,34扇区的前0x200个数据。
打印完原始数据之后将数据全部清零,清零完成如下图所示。
串口定义了receivebuff[0]的数据为写入什么扇区,receivebuff[0]为1写入扇区1,receivebuff[0]为2写入扇区2,receivebuff[0]为3写入扇区3,若为其他数据,则打印输入错误;receivebuff[1]则为写入的位置。 输入:00 05 01 02 03 04 向扇区0的的05号位置开始写入数据01 02 03 04。
输入:00 28 11 12 13 14 15 向扇区0的的40(28是十六进制)号位置开始写入数据11 12 13 14 15。
输入:17 10 aa bb 向扇区17的的16(10是十六进制)号位置开始写入数据aa bb。
Gigantic巨页与CMA的完全结合
海尔中央空调通过线上线下N个触点网络 全方位联动升级用户体验
基于GEF的MiniGUI可视化开发工具设计
养老院IPTV数字电视系统概述及功能
Python程序语法元素及程序格式框架分析
STM32CUBEMX开发GD32F303(16)----移植兆易创新SPI Nor Flash之GD25Q64Flash
配网故障定位:关键步骤与解决方案
数字人民币支付应用范围再升级,手机没有信号也可进行支付
了解3D成像/检测
三星推出全新移动固态硬盘T7 Touch 顺序读取速度高达1050MB/s并搭载指纹识别
俄罗斯推液体黄金手机?苹果iPhone X只需要3万?
Mouser引入Panasonic PAN1760模块 为您揭秘蓝牙技术
基于芯片实现高精度数字温度计测量系统的设计
魅族PRO 6s直降200,现售2499元!魅族PRO 6s大降价:5.2寸压感屏,4G+64G+24W快充!
被高通骁龙835卡住喉咙的小米6、诺基亚8结局是又被推迟!
美国推出采血机器人 有望解决使无数护士头疼的事
同轴电缆有屏蔽层吗
人工智能如何带给一个真实的世界
微控制器布局
10 亿!湖北鄂州数字乡村和智慧城市新型基础设施项目