当前位置: 首页 > news >正文

郯城网站建设什么是企业网站

郯城网站建设,什么是企业网站,高端网站鉴赏,写出网站建设的基本流程文章目录目的基础说明使用示例总结目的 Winbond#xff08;华邦#xff09;的 W25Qxx 系列 SPI FLASH 是比较常用的芯片#xff0c;这篇文章将演示单片机中通过SPI使用该芯片的操作过程。 本文使用沁恒官方的开发板 #xff08;CH32V307-EVT-R1沁恒RISC-V模块MCU赤兔评估… 文章目录目的基础说明使用示例总结目的 Winbond华邦的 W25Qxx 系列 SPI FLASH 是比较常用的芯片这篇文章将演示单片机中通过SPI使用该芯片的操作过程。 本文使用沁恒官方的开发板 CH32V307-EVT-R1沁恒RISC-V模块MCU赤兔评估板 进行演示。 基础说明 SPI的基础概念见下面文章 SPI基础概念https://blog.csdn.net/Naisu_kun/article/details/118102844 下面的例程中其实真正直接涉及到SPI的也就初始化、读取标志、收发数据几个操作。真正大头的都是根据芯片手册来操作。通常的操作就是主机向芯片写命令然后根据命令类型紧接着写入或读取数据。 芯片的命令可以参考芯片手册中 INSTRUCTIONS 章节比如我这里使用的 W25Q32FV 的手册《W25Q32FV Datasheet》 需要注意的是FLASH写操作的时候因为物理特性通常bit可以写0无法写1所以对已经写过数据的地址上写入数据前需要先擦除。另外擦除只能按扇区对于W25Qxx而已一个扇区为4k字节、块或者全片擦除。写入一次最多可以写入一页256字节。 使用示例 下面代码源自沁恒CH32V307官方例程这里调整了下代码次序和注释 #include debug.h/*此例程通过CH32V307的SPI1与W25Q系列Flash进行通讯引脚连接如下MCU Flash 说明PA2 CS 片选引脚低电平选中PA5 CLK 时钟PA7(SPI1_MOSI) DI 主机发送从机接收PA6(SPI1_MISO) DO 从机发送主机接收GND GND 地3.3V VCC 电源3.3V HOLD(RESET) 复位*//******************** 以下为SPI1基本操作函数声明 ********************/ void SPI1_Init(void); u8 SPI1_ReadWriteByte(u8 TxData);/******************** 以下为华邦Falsh ID ********************/ #define W25Q80 0XEF13 #define W25Q16 0XEF14 #define W25Q32 0XEF15 #define W25Q64 0XEF16 #define W25Q128 0XEF17/******************** 以下为华邦Falsh操作指令 ********************/ #define W25X_WriteEnable 0x06 #define W25X_WriteDisable 0x04 #define W25X_ReadStatusReg 0x05 #define W25X_WriteStatusReg 0x01 #define W25X_ReadData 0x03 #define W25X_FastReadData 0x0B #define W25X_FastReadDual 0x3B #define W25X_PageProgram 0x02 #define W25X_BlockErase 0xD8 #define W25X_SectorErase 0x20 #define W25X_ChipErase 0xC7 #define W25X_PowerDown 0xB9 #define W25X_ReleasePowerDown 0xAB #define W25X_DeviceID 0xAB #define W25X_ManufactDeviceID 0x90 #define W25X_JedecDeviceID 0x9F/******************** 以下为Falsh操作函数声明 ********************/ u8 SPI_Flash_ReadSR(void); void SPI_FLASH_Write_SR(u8 sr); void SPI_Flash_Wait_Busy(void); void SPI_FLASH_Write_Enable(void); void SPI_FLASH_Write_Disable(void); u16 SPI_Flash_ReadID(void); void SPI_Flash_Erase_Sector(u32 Dst_Addr); void SPI_Flash_Read(u8 *pBuffer, u32 ReadAddr, u16 size); void SPI_Flash_Write_Page(u8 *pBuffer, u32 WriteAddr, u16 size); void SPI_Flash_Write_NoCheck(u8 *pBuffer, u32 WriteAddr, u16 size); void SPI_Flash_Write(u8 *pBuffer, u32 WriteAddr, u16 size); void SPI_Flash_Erase_Chip(void); void SPI_Flash_PowerDown(void); void SPI_Flash_WAKEUP(void);/******************** 以下为主函数 ********************/int main(void) {NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);SystemCoreClockUpdate();Delay_Init();USART_Printf_Init(115200);printf(SystemClk:%d\r\n, SystemCoreClock);printf(\r\n);SPI1_Init(); // 初始化SPI1u16 Flash_Model SPI_Flash_ReadID(); // 读取Flash IDswitch(Flash_Model) {case W25Q80: printf(W25Q80 OK!\r\n); break;case W25Q16: printf(W25Q16 OK!\r\n); break;case W25Q32: printf(W25Q32 OK!\r\n); break;case W25Q64: printf(W25Q64 OK!\r\n); break;case W25Q128: printf(W25Q128 OK!\r\n); break;default: printf(Fail!\r\n); break;}const u8 msg[] CH32F103 SPI FLASH W25Qxx;const int size sizeof(msg);u8 buffer[size];printf(Start Erase W25Qxx....\r\n);SPI_Flash_Erase_Sector(0); // 擦除扇区printf(W25Qxx Erase Finished!\r\n);Delay_Ms(500);printf(Start Read W25Qxx....\r\n);SPI_Flash_Read(buffer, 0x0, size); // 读取数据printf(%s\r\n, buffer);Delay_Ms(500);printf(Start Write W25Qxx....\r\n);SPI_Flash_Write((u8*)msg, 0, size); // 写入数据printf(W25Qxx Write Finished!\r\n);Delay_Ms(500);printf(Start Read W25Qxx....\r\n);SPI_Flash_Read(buffer, 0x0, size); // 再次读取数据printf(%s\r\n, buffer);while(1) {} }/******************** 以下为SPI1基本操作函数实现 ********************/// 初始化SPI1 void SPI1_Init(void) {// 初始化时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE);// 初始化GPIOGPIO_InitTypeDef GPIO_InitStructure { 0 };GPIO_InitStructure.GPIO_Pin GPIO_Pin_2;GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStructure);GPIO_SetBits(GPIOA, GPIO_Pin_2); // CS引脚输出高电平不选中Flash芯片GPIO_InitStructure.GPIO_Pin GPIO_Pin_5 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz;GPIO_Init(GPIOA, GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin GPIO_Pin_6;GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING;GPIO_Init(GPIOA, GPIO_InitStructure);// 初始化SPI1SPI_InitTypeDef SPI_InitStructure { 0 };SPI_InitStructure.SPI_Direction SPI_Direction_2Lines_FullDuplex; // 全双工模式SPI_InitStructure.SPI_Mode SPI_Mode_Master; // 作为主机SPI_InitStructure.SPI_DataSize SPI_DataSize_8b; // 8bit数据SPI_InitStructure.SPI_CPOL SPI_CPOL_High; // 时钟不通讯时高电平SPI_InitStructure.SPI_CPHA SPI_CPHA_2Edge; // 在第二个边缘进行采样结合上条这里相当于使用Mode3SPI_InitStructure.SPI_NSS SPI_NSS_Soft; // 片选引脚手动控制SPI_InitStructure.SPI_BaudRatePrescaler SPI_BaudRatePrescaler_4; // SPI外设时钟源4分频SPI_InitStructure.SPI_FirstBit SPI_FirstBit_MSB; // 传输时高比特在前SPI_InitStructure.SPI_CRCPolynomial 7;SPI_Init(SPI1, SPI_InitStructure); // 初始化SPI1设置SPI_Cmd(SPI1, ENABLE); // 启动SPI1 }// 很多库中SPI的读和写是封装在一起的根据需要选择写或读或读写 // 在SPI读数据时需要注意这时候虽然数据是从机发送的但时钟还是主机给出的 // 所以往往读数据时主机还需要通过写数据任意均可来给出时钟信号 // SPI1_Write_Read(0x00) 经常用来表示通过写一个字节来发送时钟从而接收从机一个字节数据 u8 SPI1_ReadWriteByte(u8 TxData) {u8 i 0;while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) RESET) { // 等待SPI1可写i; if(i 200) return 0;}SPI_I2S_SendData(SPI1, TxData); // 写数据i 0;while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) RESET) { // 等待SPI1可读i; if(i 200) return 0;}return SPI_I2S_ReceiveData(SPI1); // 读数据 }/******************** 以下为Falsh操作函数实现 ********************/// 读状态寄存器 // BIT7 6 5 4 3 2 1 0 // SPR RV TB BP2 BP1 BP0 WEL BUSY u8 SPI_Flash_ReadSR(void) {u8 byte 0;GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0); // 选中芯片SPI1_ReadWriteByte(W25X_ReadStatusReg); // 写命令byte SPI1_ReadWriteByte(0x00); // 读数据GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1); // 释放芯片return byte; }// 写状态寄存器 void SPI_FLASH_Write_SR(u8 sr) {GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0); // 选中芯片SPI1_ReadWriteByte(W25X_WriteStatusReg); // 写命令SPI1_ReadWriteByte(sr); // 写数据GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1); // 释放芯片 }// 等待Flash空闲 void SPI_Flash_Wait_Busy(void) {while((SPI_Flash_ReadSR() 0x01) 0x01) { } }// 使能写入 void SPI_FLASH_Write_Enable(void) {GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0); // 选中芯片SPI1_ReadWriteByte(W25X_WriteEnable); // 写命令GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1); // 释放芯片 }// 失能写入 void SPI_FLASH_Write_Disable(void) {GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0); // 选中芯片SPI1_ReadWriteByte(W25X_WriteDisable); // 写命令GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1); // 释放芯片 }// 读取芯片ID u16 SPI_Flash_ReadID(void) {GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0); // 选中芯片SPI1_ReadWriteByte(W25X_ManufactDeviceID); // 写命令SPI1_ReadWriteByte(0x00); // 通过发送数据产生时钟等待数据可读SPI1_ReadWriteByte(0x00); // 同上SPI1_ReadWriteByte(0x00); // 同上u16 Temp 0;Temp | SPI1_ReadWriteByte(0xFF) 8; // 读数据Temp | SPI1_ReadWriteByte(0xFF); // 同上GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1); // 释放芯片return Temp; }// 擦除扇区 void SPI_Flash_Erase_Sector(u32 Dst_Addr) {SPI_FLASH_Write_Enable(); // 使能写入SPI_Flash_Wait_Busy(); // 等待操作完成GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0); // 选中芯片SPI1_ReadWriteByte(W25X_SectorErase); // 发送命令Dst_Addr * 4096; // 每个扇区大小为4kSPI1_ReadWriteByte((u8)((Dst_Addr) 16)); // 写扇区地址SPI1_ReadWriteByte((u8)((Dst_Addr) 8)); // 同上SPI1_ReadWriteByte((u8)Dst_Addr); // 同上GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1); // 释放芯片SPI_Flash_Wait_Busy(); // 等待操作完成 }// 读取数据 void SPI_Flash_Read(u8 *pBuffer, u32 ReadAddr, u16 size) {GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0); // 选中芯片SPI1_ReadWriteByte(W25X_ReadData); // 写命令SPI1_ReadWriteByte((u8)((ReadAddr) 16)); // 写地址SPI1_ReadWriteByte((u8)((ReadAddr) 8)); // 同上SPI1_ReadWriteByte((u8)ReadAddr);for(u16 i 0; i size; i) {pBuffer[i] SPI1_ReadWriteByte(0x00); // 读数据}GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1); // 释放芯片 }// 按页方式写入 void SPI_Flash_Write_Page(u8 *pBuffer, u32 WriteAddr, u16 size) {SPI_FLASH_Write_Enable(); // 使能写入GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0); // 选中芯片SPI1_ReadWriteByte(W25X_PageProgram); // 写命令SPI1_ReadWriteByte((u8)((WriteAddr) 16)); // 写地址SPI1_ReadWriteByte((u8)((WriteAddr) 8)); // 同上SPI1_ReadWriteByte((u8)WriteAddr); // 同上for(u16 i 0; i size; i) {SPI1_ReadWriteByte(pBuffer[i]); // 写数据}GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1); // 释放芯片SPI_Flash_Wait_Busy(); // 等待操作完成 }// 写入数据写入前需要先擦除 void SPI_Flash_Write_NoCheck(u8 *pBuffer, u32 WriteAddr, u16 size) {// 一次最多只能写一页256字节u16 pageremain 256 - WriteAddr % 256;if(size pageremain) pageremain size;while(1) {SPI_Flash_Write_Page(pBuffer, WriteAddr, pageremain);if(size pageremain) { break; }else {pBuffer pageremain;WriteAddr pageremain;size - pageremain;if(size 256) pageremain 256;else pageremain size;}} }// 写入数据 void SPI_Flash_Write(u8 *pBuffer, u32 WriteAddr, u16 size) {u8 buffer[4096];u32 secpos;u16 secoff;u16 secremain;u16 i;secpos WriteAddr / 4096;secoff WriteAddr % 4096;secremain 4096 - secoff;if(size secremain) secremain size;while(1) {SPI_Flash_Read(buffer, secpos * 4096, 4096); // 读取数据for(i 0; i secremain; i) {if(buffer[secoff i] ! 0XFF) break; // 检查数据}if(i secremain) { // 需要先擦除SPI_Flash_Erase_Sector(secpos);for(i 0; i secremain; i) { // 擦除数据buffer[i secoff] pBuffer[i]; // 将要写入数据填充到缓存中}SPI_Flash_Write_NoCheck(buffer, secpos * 4096, 4096); // 写数据} else { // 不需要擦除SPI_Flash_Write_NoCheck(pBuffer, WriteAddr, secremain); // 直接写数据}if(size secremain) { break; }else {secpos;secoff 0;pBuffer secremain;WriteAddr secremain;size - secremain;if(size 4096) { secremain 4096; }else { secremain size; }}} }// 全片擦除 void SPI_Flash_Erase_Chip(void) {SPI_FLASH_Write_Enable(); // 使能写入SPI_Flash_Wait_Busy(); // 等待操作完成GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0); // 选中芯片SPI1_ReadWriteByte(W25X_ChipErase); // 写命令GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1); // 释放芯片SPI_Flash_Wait_Busy(); // 等待操作完成 }// 进入省电模式 void SPI_Flash_PowerDown(void) {GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0); // 选中芯片SPI1_ReadWriteByte(W25X_PowerDown); // 写命令GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1); // 释放芯片Delay_Us(3); // 等待操作完成 }// 从省电模式唤醒 void SPI_Flash_WAKEUP(void) {GPIO_WriteBit(GPIOA, GPIO_Pin_2, 0); // 选中芯片SPI1_ReadWriteByte(W25X_ReleasePowerDown); // 写命令GPIO_WriteBit(GPIOA, GPIO_Pin_2, 1); // 释放芯片Delay_Us(3); // 等待操作完成 }上面代码演示结果如下 总结 Winbond华邦的 W25Qxx 系列 SPI FLASH 芯片使用上是比较简单的。上面的代码只是测试使用的代码可能存在很多不严谨或不完善的地方。实际使用中可以自行调整并抽象出相关功能使之可以适用各类平台。
http://www.w-s-a.com/news/94167/

相关文章:

  • 网站制作哪家好商城网站建设预算要多少钱
  • 怎么做律所的官方网站微网站可以做商城吗
  • 通用网站后台管理系统(php版)网站备案ip查询网站查询
  • 制作网站代码吗江阴网站建设推广
  • 汕头建网站wordpress文章网址采集
  • 十大景观设计网站用vue框架做的网站
  • 福建省建设监理网官方网站做外贸网站卖什么东西好
  • 公司做网站排名东莞关键词优化推广
  • 连云港做企业网站公司全网营销与seo
  • 电子毕业设计代做网站wordpress 插件放在那
  • 黄石规划建设局网站怎么做存储网站
  • 网站安装wordpress滨江网站建设
  • 河南官网网站建设一般使用的分辨率显示密度是
  • dedecms新网站 上传到万网的空间宝洁公司网站做的怎么样
  • 网站建设语录优惠券的网站怎么做的
  • 白山市住房和建设局网站有实力高端网站设计地址
  • 沧州网站建设制作设计优化深圳网站自然优化
  • 企业做网站 乐云seowordpress中修改html
  • 网站细节门户wordpress主题下载
  • 全景网站模版wordpress套餐
  • 华为云建网站dw制作一个手机网站模板
  • 定陶菏泽网站建设河北新出现的传染病
  • 商业网站建设案例教程郑州服装网站建设公司
  • 网站内容怎么做专业的企业管理软件
  • 深圳网站制作公司排名微网站和微信公共平台的区别
  • 权威的唐山网站建设扁平网站欣赏
  • 网站外链建设工作计划应用公园app免费制作
  • 东莞营销型网站建设全自动建站系统
  • 网络在线培训网站建设方案虚拟主机配置WordPress
  • 建设工程信息查询哪个网站好台州做优化