3、按buffer写数据函数bsp_spi_nor_buffer_write,该函数实现任意长度数据写入,使用page写函数搭配算法,可以跨page进行写数据:
C void bsp_spi_nor_buffer_write(uint8_t* pbuffer, uint32_t write_addr, uint16_t num_byte_to_write) { uint8_t num_of_page = 0, num_of_single = 0, addr = 0, count = 0, temp = 0; addr = write_addr % SPI_FLASH_PAGE_SIZE; count = SPI_FLASH_PAGE_SIZE - addr; num_of_page = num_byte_to_write / SPI_FLASH_PAGE_SIZE; num_of_single = num_byte_to_write % SPI_FLASH_PAGE_SIZE; /* write_addr is SPI_FLASH_PAGE_SIZE aligned */ if(0 == addr){ /* num_byte_to_write < SPI_FLASH_PAGE_SIZE */ if(0 == num_of_page) bsp_spi_nor_page_write(pbuffer,write_addr,num_byte_to_write); /* num_byte_to_write > SPI_FLASH_PAGE_SIZE */ else{ while(num_of_page--){ bsp_spi_nor_page_write(pbuffer,write_addr,SPI_FLASH_PAGE_SIZE); write_addr += SPI_FLASH_PAGE_SIZE; pbuffer += SPI_FLASH_PAGE_SIZE; } bsp_spi_nor_page_write(pbuffer,write_addr,num_of_single); } }else{ /* write_addr is not SPI_FLASH_PAGE_SIZE aligned */ if(0 == num_of_page){ /* (num_byte_to_write + write_addr) > SPI_FLASH_PAGE_SIZE */ if(num_of_single > count){ temp = num_of_single - count; bsp_spi_nor_page_write(pbuffer,write_addr,count); write_addr += count; pbuffer += count; bsp_spi_nor_page_write(pbuffer,write_addr,temp); }else bsp_spi_nor_page_write(pbuffer,write_addr,num_byte_to_write); }else{ /* num_byte_to_write > SPI_FLASH_PAGE_SIZE */ num_byte_to_write -= count; num_of_page = num_byte_to_write / SPI_FLASH_PAGE_SIZE; num_of_single = num_byte_to_write % SPI_FLASH_PAGE_SIZE; bsp_spi_nor_page_write(pbuffer,write_addr, count); write_addr += count; pbuffer += count; while(num_of_page--){ bsp_spi_nor_page_write(pbuffer,write_addr,SPI_FLASH_PAGE_SIZE); write_addr += SPI_FLASH_PAGE_SIZE; pbuffer += SPI_FLASH_PAGE_SIZE; } if(0 != num_of_single) bsp_spi_nor_page_write(pbuffer,write_addr,num_of_single); } } }
4、按buffer读数据函数bsp_spi_nor_buffer_read,该函数实现任意地址读数据,该函数流程是:拉低片选->向NOR FLASH发送读指令READ(0x03)->从低地址到高地址发送要读的地址(每次进行读数据时,只需要给初始地址即可,读完一个数据后NOR FLASH内部会自动把地址+1)->读数据->拉高片选:
C void bsp_spi_nor_buffer_read(uint8_t* pbuffer, uint32_t read_addr, uint16_t num_byte_to_read) { /* select the flash: chip slect low */ bsp_spi_nor_cs_low(); /* send 'read from memory ' instruction */ driver_spi_master_transmit_receive_byte(&BOARD_SPI,READ); /* send read_addr high nibble address byte to read from */ driver_spi_master_transmit_receive_byte(&BOARD_SPI,(read_addr & 0xFF0000) >> 16); /* send read_addr medium nibble address byte to read from */ driver_spi_master_transmit_receive_byte(&BOARD_SPI,(read_addr& 0xFF00) >> 8); /* send read_addr low nibble address byte to read from */ driver_spi_master_transmit_receive_byte(&BOARD_SPI,read_addr & 0xFF); /* while there is data to be read */ while(num_byte_to_read--){ /* read a byte from the flash */ *pbuffer = driver_spi_master_transmit_receive_byte(&BOARD_SPI,NOR_DUMMY_BYTE); /* point to the next location where the byte read will be saved */ pbuffer++; } /* deselect the flash: chip select high */ bsp_spi_nor_cs_high(); }
11.4.4main函数实现
以下为main函数代码:
C int main(void) { //延时、共用驱动部分初始化 driver_init(); //初始化LED组和默认状态 bsp_led_group_init(); bsp_led_on(&LED1); bsp_led_off(&LED2); //初始化UART打印 bsp_uart_init(&BOARD_UART); //初始化SPI bsp_spi_init(&BOARD_SPI); //初始化SPI NOR bsp_spi_nor_init(); printf_log('nrSPI Flash:GD25Q configured...nr'); //读取flash id flash_id = bsp_spi_nor_read_id(); printf_log('nrThe Flash_ID:0x%Xnr',flash_id); //比对flash id是否一致 if(SFLASH_4B_ID == flash_id || SFLASH_16B_ID == flash_id) { printf_log('nrWrite to tx_buffer:nr'); //准备数据 for(uint16_t i = 0; i < BUFFER_SIZE; i++){ tx_buffer[i] = i; printf_log('0x%02X ',tx_buffer[i]); if(15 == i%16){ printf_log('nr'); } } printf_log('nr'); printf_log('nrRead from rx_buffer:nr'); //擦除要写入的sector bsp_spi_nor_sector_erase(FLASH_WRITE_ADDRESS); //写入数据 bsp_spi_nor_buffer_write(tx_buffer,FLASH_WRITE_ADDRESS,TX_BUFFER_SIZE); //延时等待写完成 delay_ms(10); //回读写入数据 bsp_spi_nor_buffer_read(rx_buffer,FLASH_READ_ADDRESS,RX_BUFFER_SIZE); /* printf_log rx_buffer value */ for(uint16_t i = 0; i < BUFFER_SIZE; i++){ printf_log('0x%02X ', rx_buffer[i]); if(15 == i%16){ printf_log('nr'); } } printf_log('nr'); //比较回读和写入数据 if(ERROR == memory_compare(tx_buffer,rx_buffer,BUFFER_SIZE)){ printf_log('Err:Data Read and Write aren't Matching.nr'); //写入错误 /* turn off all leds */ bsp_led_on(&LED2); /* turn off all leds */ bsp_led_on(&LED1); while(1); }else{ printf_log('nrSPI-GD25Q16 Test Passed!nr'); } }else{ //ID读取错误 /* spi flash read id fail */ printf_log('nrSPI Flash: Read ID Fail!nr'); /* turn off all leds */ bsp_led_on(&LED2); /* turn off all leds */ bsp_led_on(&LED1); while(1); } while(1){ /* turn off all leds */ bsp_led_toggle(&LED2); /* turn off all leds */ bsp_led_toggle(&LED1); delay_ms(200); } }
main函数中实现了向特定NOR FLASH地址写数据,并回读出来,并将写入的数据和回读出来的数据进行对比,看是否写入成功。
11.5实验结果
将本实验例程烧录到GD32H757紫海棠派开发板中,将会显示对外部SPI flash写入以及读取的数据以及最终的校验结果,如果写入读取校验正确,将会显示SPI-GD25QXX Test Passed,LED1和LED2将会交替闪烁。
上一篇:采用GD32F303的机械键盘方案设计
下一篇:最后一页
推荐阅读最新更新时间:2024-11-18 09:57
设计资源 培训 开发板 精华推荐
- FRDM-KW24D512: 面向Kinetis® KW2x MCU的Freedom开发平台
- LTC2301 演示板、12 位、1 通道 I2C 14ksps ADC
- DC2672A-B,使用 LTM4664 48VIN、双路 50A 稳压器和数字电源系统管理的演示板
- FM8002E PCB
- HestiaPi Touch:用于控制 HVAC 和水系统的开源智能恒温器
- 仿真8路流水灯
- LT5400 四路匹配电阻网络的典型应用
- LT3066IDE-5 电流监视器的典型应用电路
- 具有多功能电流控制功能的 LTC4211 热插拔控制器的典型应用
- L7885C 0.5 至 10 V 输出稳压器的典型应用