wordpress图片网站wordpress侧栏缩略图
wordpress图片网站,wordpress侧栏缩略图,公司网站做的好的公司,wordpress怎么生成app提示#xff1a;文章写完后#xff0c;目录可以自动生成#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、SPI外设介绍二#xff0c;SPI外设读取Flash用到寄存器详解三、HAL库实现SPI硬件外设读写flash1.stm32cubemx配置设置1.1. 选择芯片并配置单线调试模式…提示文章写完后目录可以自动生成如何生成可参考右边的帮助文档文章目录前言一、SPI外设介绍二SPI外设读取Flash用到寄存器详解三、HAL库实现SPI硬件外设读写flash1.stm32cubemx配置设置1.1. 选择芯片并配置单线调试模式 配置外部时钟源和时钟树1.2.打开usart1 配置输出打印1.3 设置spi1 为主输出模式同时片选是有pc13 通用推挽输出1.4 配置工程名称并导出工程等等1.5 分别新建w25q32.c 和.h 放入core/src 和core/inc里面 并使用keil 导入并引入c库支持2.编写代码2.1 usart 重定义2.2 编写spi.c 和.h2.3 w25q32.c前言提示这里可以添加本文要记录的大概内容介绍SPI外设说明硬件外设读取flash的需求和寄存器的介绍 以及用HAL库的方式实现提示以下是本篇文章正文内容下面案例可供参考一、SPI外设介绍STM32 的 SPI 外设可用作通讯的主机及从机支持最高的 SCK 时钟频率为 fpclk/2 STM32F103 型号的芯片默认fpclk1为36MHzfpclk2为72MHz。完全支持 SPI 协议的 4 种模式数据帧长度可设置为 8 位或 16 位可设置数据 MSB 先行或 LSB 先行。它还支持双线全双工、双线单向以及单线模式。STM32F103系列提供了3个SPISPI1挂在APB2总线SPI2/3挂在APB1总线。其中双线单向模式可以同时使用 MOSI 及 MISO 数据线向一个方向传输数据可以加快一倍的传输速度。而单线模式则可以减少硬件接线当然这样速率会受到影响。用的比较多还是双线全双工模式。什么是SPISPI 是英语Serial Peripheral interface的缩写顾名思义就是串行外围设备接口。是Motorola(摩托罗拉)首先在其MC68HCXX系列处理器上定义的。SPI是一种高速的全双工同步的通信总线并且在芯片的管脚上只占用四根线节约了芯片的管脚同时为PCB的布局上节省空间提供方便主要应用在 EEPROMFLASH实时时钟AD转换器还有数字信号处理器和数字信号解码器之间。SPI主从模式SPI分为主、从两种模式一个SPI通讯系统需要包含一个且只能是一个主设备一个或多个从设备。提供时钟的为主设备Master接收时钟的设备为从设备SlaveSPI接口的读写操作都是由主设备发起。当存在多个从设备时通过各自的片选信号进行管理。SPI是全双工且SPI没有定义速度限制一般的实现通常能达到甚至超过10 MbpsSPI信号线SPI接口一般使用四条信号线通信SDI数据输入SDO数据输出SCK时钟CS片选MISO 主设备输入/从设备输出引脚。该引脚在从模式下发送数据在主模式下接收数据。MOSI主设备输出/从设备输入引脚。该引脚在主模式下发送数据在从模式下接收数据。SCLK串行时钟信号由主设备产生。CS/SS从设备片选信号由主设备控制。它的功能是用来作为“片选引脚”也就是选择指定的从设备让主设备可以单独地与特定从设备通讯避免数据线上的冲突硬件上为4根线。SPI 一对一SPI 一对多SPI设备选择SPI是单主设备 single-master 通信协议这意味着总线中的只有一支中心设备能发起通信。当SPI主设备想读/写从设备时它首先拉低从设备对应的SS线SS是低电平有效接着开始发送工作脉冲到时钟线上在相应的脉冲时间上主设备把信号发到MOSI实现“写”同时可对MISO采样而实现“读”如下图SPI数据发送接收SPI主机和从机都有一个串行移位寄存器主机通过向它的SPI串行寄存器写入一个字节来发起一次传输。首先拉低对应SS信号线表示与该设备进行通信主机通过发送SCLK时钟信号来告诉从机写数据或者读数据这里要注意SCLK时钟信号可能是低电平有效也可能是高电平有效因为SPI有四种模式这个我们在下面会介绍主机(Master)将要发送的数据写到发送数据缓存区(Menory)缓存区经过移位寄存器(0~7)串行移位寄存器通过MOSI信号线将字节一位一位的移出去传送给从机同时MISO接口接收到的数据经过移位寄存器一位一位的移到接收缓存区。从机(Slave)也将自己的串行移位寄存器(0~7)中的内容通过MISO信号线返回给主机。同时通过MOSI信号线接收主机发送的数据这样两个移位寄存器中的内容就被交换。SPI通信的四种模式SPI的四种模式简单地讲就是设置SCLK时钟信号线的那种信号为有效信号SPI通信有4种不同的操作模式不同的从设备可能在出厂是就是配置为某种模式这是不能改变的但我们的通信双方必须是工作在同一模式下所以我们可以对我们的主设备的SPI模式进行配置通过CPOL时钟极性和CPHA时钟相位来控制我们主设备的通信模式具体如下、时钟极性(CPOL)定义了时钟空闲状态电平CPOL0表示当SCLK0时处于空闲态所以有效状态就是SCLK处于高电平时CPOL1表示当SCLK1时处于空闲态所以有效状态就是SCLK处于低电平时时钟相位(CPHA)定义数据的采集时间。CPHA0在时钟的第一个跳变沿上升沿或下降沿进行数据采样。在第2个边沿发送数据CPHA1在时钟的第二个跳变沿上升沿或下降沿进行数据采样。在第1个边沿发送数据例如Mode0CPOL0CPHA0此时空闲态时SCLK处于低电平数据采样是在第1个边沿也就是SCLK由低电平到高电平的跳变所以数据采样是在上升沿(准备数据发送数据数据发送是在下降沿。Mode1CPOL0CPHA1此时空闲态时SCLK处于低电平数据发送是在第1个边沿也就是SCLK由低电平到高电平的跳变所以数据采样是在下降沿数据发送是在上升沿。Mode2CPOL1CPHA0此时空闲态时SCLK处于高电平数据采集是在第1个边沿也就是SCLK由高电平到低电平的跳变所以数据采集是在下降沿数据发送是在上升沿。Mode3CPOL1CPHA1此时空闲态时SCLK处于高电平数据发送是在第1个边沿也就是SCLK由高电平到低电平的跳变所以数据采集是在上升沿数据发送是在下降沿。它们的区别是定义了在时钟脉冲的哪条边沿转换toggles输出信号哪条边沿采样输入信号还有时钟脉冲的稳定电平值就是时钟信号无效时是高还是低。每种模式由一对参数刻画它们称为时钟极clock polarityCPOL与时钟期clock phaseCPHA。、SPI的通信协议主从设备必须使用相同的工作模式——SCLK、CPOL 和 CPHA才能正常工作。如果有多个从设备并且它们使用了不同的工作模式那么主设备必须在读写不同从设备时需要重新修改对应从设备的模式。以上SPI总线协议的主要内容。是不是感觉这就完了 SPI就是如此他没有规定最大传输速率没有地址方案也没规定通信应答机制没有规定流控制规则。只要四根信号线连接正确SPI模式相同将CS/SS信号线拉低即可以直接通信一次一个字节的传输读写数据同时操作这就是SPI些通信控制都得通过SPI设备自行实现SPI并不关心物理接口的电气特性例如信号的标准电压。PS:这也是SPI接口的一个缺点没有指定的流控制没有应答机制确认是否接收到数据。SPI的三种模式SPI工作在3中模式下分别是运行、等待和停止。运行模式Run Mode这是基本的操作模式等待模式Wait ModeSPI工作在等待模式是一种可配置的低功耗模式可以通过SPICR2寄存器的SPISWAI位进行控制。在等待模式下如果SPISWAI位清0SPI操作类似于运行模式。如果SPISWAI位置1SPI进入低功耗状态并且SPI时钟将关闭。如果SPI配置为主机所有的传输将停止但是会在CPU进入运行模式后重新开始。如果SPI配置为从机会继续接收和传输一个字节这样就保证从机与主机同步。停止模式Stop Mode为了降低功耗SPI在停止模式是不活跃的。如果SPI配置为主机正在进行的传输会停止但是在CPU进入运行模式后会重新开始。如果SPI配置为从机会继续接受和发送一个字节这样就保证了从机与主机同步。SPI原理图连接二SPI外设读取Flash用到寄存器详解第 1 章配置SPI模式1.1代码/* 3.1 配置主模式 0从设备 1主设备*/SPI1-CR1 | SPI_CR1_MSTR;1.2寄存器第 2 章SPI波特率控制2.1代码/* 3.2 选择分频系数 000fpclk/2, 001fpclk/4 …,我们选择4分频 */SPI1-CR1 ~SPI_CR1_BR;SPI1-CR1 | SPI_CR1_BR_0;2.2寄存器第 3 章时钟的极性和相位3.1代码/* 3.3 时钟极性 0 空闲状态时SCK保持低电平1 空闲状态时SCK保持高电平。/SPI1-CR1 ~SPI_CR1_CPOL;/3.4 时钟相位 0 数据采样从第一个时钟边沿开始1 数据采样从第二个时钟边沿开始。*/SPI1-CR1 ~SPI_CR1_CPHA;3.2寄存器第 4 章数据帧格式和传输顺序4.1代码/* 3.5 数据帧格式 08位数据帧116位数据帧/SPI1-CR1 ~SPI_CR1_DFF;/3.6 数据传输顺序 0先发送MSB1先发送LSB。/SPI1-CR1 ~SPI_CR1_LSBFIRST; /高位先行 */4.2寄存器第 5 章配置片选方式5.1代码/* 3.7 使用软件实现片选我们自7己控制CS0禁止软件从设备管理1启用软件从设备管理。/SPI1-CR1 | SPI_CR1_SSM;/3.8 当SSM1时这个时候对SSI的操作无效必须设置为1 */SPI1-CR1 | SPI_CR1_SSI;5.2寄存器第 6 章启动SPI6.1代码/* 4 启动SPI1 0禁止SPI设备1开启SPI设备。*/SPI1-CR1 | SPI_CR1_SPE;6.2寄存器第 7 章SPI读写数据7.1代码uint8_t SPI_SwapByte(uint8_t byte_sended){/* 1. 等待发送缓冲区为空/while (!(SPI1-SR SPI_SR_TXE));/2. 把数据写入到数据寄存器/SPI1-DR byte_sended;/3. 等待接收缓冲区非空/while (!(SPI1-SR SPI_SR_RXNE));/4. 返回读到的字节数据 */return SPI1-DR;}7.2寄存器三、HAL库实现SPI硬件外设读写flash1.stm32cubemx配置设置1.1. 选择芯片并配置单线调试模式 配置外部时钟源和时钟树1.2.打开usart1 配置输出打印1.3 设置spi1 为主输出模式同时片选是有pc13 通用推挽输出片选引脚配置 默认输出拉高要用的时候拉低1.4 配置工程名称并导出工程等等1.5 分别新建w25q32.c 和.h 放入core/src 和core/inc里面 并使用keil 导入并引入c库支持根据目录放入文件2.编写代码2.1 usart 重定义#includestdio.hintfputc(intch,FILE*f){HAL_UART_Transmit(huart1,(uint8_t*)ch,1,1000);returnch;}2.2 编写spi.c 和.hintfputc(intch,FILE*f){HAL_UART_Transmit(huart1,(uint8_t*)ch,1,1000);returnch;}2.3 w25q32.c#includew25q32.h// // ³õʼ»¯// void W25Q32_Init(void)// {// MX_SPI1_Init();// }// ¶ÁÈ¡Éú²úÉ̺ÍÉ豸IDvoidW25Q32_ReadID(uint8_t*mid,uint16_t*did){// 0. ¿ªÆô SPI ͨµÀ£¬Æ¬Ñ¡ÉúЧSPI_Start();// 1. ·¢ËÍÖ¸ÁîSPI_SwapByte(0x9f);// 2. ÏÂÒ»¸öÖÜÆÚ»ñÈ¡·¢À´µÄµÚÒ»¸ö×Ö½Ú£¬ÖÆÔìÉÌID*midSPI_SwapByte(0xff);// 3. ÏÂÁ½¸öÖÜÆÚ£¬»ñÈ¡É豸ID*did0;*did|SPI_SwapByte(0xff)8;*did|SPI_SwapByte(0xff)0xff;SPI_Stop();}// дÈëʹÄÜvoidW25Q32_WriteEnalbe(void){SPI_Start();// ·¢ËÍÖ¸ÁîSPI_SwapByte(0x06);SPI_Stop();}// дÈëʧÄÜvoidW25Q32_WriteDisable(void){SPI_Start();// ·¢ËÍÖ¸ÁîSPI_SwapByte(0x04);SPI_Stop();}// µÈ´ýµ±Ç°×´Ì¬£¬²»ÎªbusyvoidW25Q32_WaitNotBusy(void){SPI_Start();// 1. ·¢ËÍÖ¸ÁîSPI_SwapByte(0x05);// 2. Ñ»·µÈ´ý£¬Ö±µ½½ÓÊÕÊý¾Ý×îºóһλΪ 0while(SPI_SwapByte(0xff)0x01){}SPI_Stop();}// ²Á³ýsectorvoidW25Q32_EraseSector(uint8_tblock,uint8_tsector){// 1. Ïȵȴý²»ÎªbusyW25Q32_WaitNotBusy();// 2. ¿ªÆôдʹÄÜW25Q32_WriteEnalbe();// 3. Æ´½ÓÍêÕûµØÖ·£¬sectorÊ×µØÖ·£¬ºó12λ¶¼Îª0uint32_tsectorHeadAddrblock*0x010000sector*0x001000;// 4. Æô¶¯SPI_Start();// 5. ·¢ËÍÖ¸ÁîSPI_SwapByte(0x20);// 6. ·¢ËÍ24λµØÖ·SPI_SwapByte(sectorHeadAddr160xff);// È¡Èý¸ö×Ö½ÚÖеÄ×î¸ß×Ö½ÚSPI_SwapByte(sectorHeadAddr80xff);// È¡µÚ¶þ¸ö×Ö½ÚSPI_SwapByte(sectorHeadAddr00xff);SPI_Stop();W25Q32_WriteDisable();}// ҳдvoidW25Q32_WritePage(uint8_tblock,uint8_tsector,uint8_tpage,uint8_t*data,uint8_tlen){// 1. Ïȵȴý²»ÎªbusyW25Q32_WaitNotBusy();// 2. ¿ªÆôдʹÄÜW25Q32_WriteEnalbe();// 3. Æ´½ÓÍêÕûµØÖ·£¬pageÊ×µØÖ·£¬ºó8λ¶¼Îª0uint32_tpageHeadAddrblock*0x010000sector*0x001000page*0x000100;// 4. Æô¶¯SPI_Start();// 5. ·¢ËÍÖ¸ÁîSPI_SwapByte(0x02);// 6. ·¢ËÍ24λµØÖ·SPI_SwapByte(pageHeadAddr160xff);// È¡Èý¸ö×Ö½ÚÖеÄ×î¸ß×Ö½ÚSPI_SwapByte(pageHeadAddr80xff);// È¡µÚ¶þ¸ö×Ö½ÚSPI_SwapByte(pageHeadAddr00xff);// 7. ¼ÌÐø·¢ËÍÊý¾Ýfor(uint8_ti0;ilen;i){SPI_SwapByte(data[i]);}SPI_Stop();W25Q32_WriteDisable();}// ¶ÁÈ¡voidW25Q32_Read(uint8_tblock,uint8_tsector,uint8_tpage,uint8_t*buffer,uint8_tlen){// 1. Ïȵȴý²»ÎªbusyW25Q32_WaitNotBusy();// 2. Æ´½ÓÍêÕûµØÖ·£¬pageÊ×µØÖ·£¬ºó8λ¶¼Îª0uint32_tpageHeadAddrblock*0x010000sector*0x001000page*0x000100;// 3. Æô¶¯SPI_Start();// 4. ·¢ËÍÖ¸ÁîSPI_SwapByte(0x03);// 5. ·¢ËÍ24λµØÖ·SPI_SwapByte(pageHeadAddr160xff);// È¡Èý¸ö×Ö½ÚÖеÄ×î¸ß×Ö½ÚSPI_SwapByte(pageHeadAddr80xff);// È¡µÚ¶þ¸ö×Ö½ÚSPI_SwapByte(pageHeadAddr00xff);// 6. ¶ÁÈ¡Êý¾Ýfor(uint8_ti0;ilen;i){buffer[i]SPI_SwapByte(0xff);}SPI_Stop();}// ҳдvoidW25Q32_WritePageRandom(uint32_taddr,uint8_t*data,uint8_tlen){// 1. Ïȵȴý²»ÎªbusyW25Q32_WaitNotBusy();// 2. ¿ªÆôдʹÄÜW25Q32_WriteEnalbe();// 4. Æô¶¯SPI_Start();// 5. ·¢ËÍÖ¸ÁîSPI_SwapByte(0x02);// 6. ·¢ËÍ24λµØÖ·SPI_SwapByte(addr160xff);// È¡Èý¸ö×Ö½ÚÖеÄ×î¸ß×Ö½ÚSPI_SwapByte(addr80xff);// È¡µÚ¶þ¸ö×Ö½ÚSPI_SwapByte(addr00xff);// 7. ¼ÌÐø·¢ËÍÊý¾Ýfor(uint8_ti0;ilen;i){SPI_SwapByte(data[i]);}SPI_Stop();W25Q32_WriteDisable();}main.c/* USER CODE BEGIN Header *//** ****************************************************************************** * file : main.c * brief : Main program body ****************************************************************************** * attention * * Copyright (c) 2024 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** *//* USER CODE END Header *//* Includes ------------------------------------------------------------------*/#includemain.h#includespi.h#includeusart.h#includegpio.h#includew25q32.h/* Private includes ----------------------------------------------------------*//* USER CODE BEGIN Includes *//* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*//* USER CODE BEGIN PTD *//* USER CODE END PTD *//* Private define ------------------------------------------------------------*//* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*//* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/voidSystemClock_Config(void);/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*//* USER CODE BEGIN 0 *//* USER CODE END 0 *//** * brief The application entry point. * retval int */intmain(void){/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_SPI1_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 *//* USER CODE END 2 *//* Infinite loop */printf(Hello world\n);// 2. ¶ÁÈ¡ID£¬²âÊÔFlashÊÇ·ñÕý³£uint8_tmid0;uint16_tdid0;W25Q32_ReadID(mid,did);printf(mid %#x, did%#x\n,mid,did);// 3. ¶Î²Á³ýW25Q32_EraseSector(0,0);// 4. ҳд£¨µÚÒ»¸ö¿éµÄµÚÒ»¸ö¶ÎµÄµÚÒ»Ò³£©W25Q32_WritePage(0,0,0,12345678,8);W25Q32_WritePage(0,0,1,abcdef,8);// 5. Ò³¶Áuint8_tbuffer[100]{0};W25Q32_Read(0,0,0,buffer,8);printf(read data %s\n,buffer);W25Q32_Read(0,0,1,buffer,8);printf(read data %s\n,buffer);// 6. ²âÊÔ£ºËæ»úÍêÕûµØÖ·Ð´ÈëW25Q32_WritePageRandom(0x00022f,12345678\0,9);W25Q32_Read(0,0,2,buffer,255);printf(read data %s\n,buffer);while(1){}/* USER CODE END 3 */}/** * brief System Clock Configuration * retval None */voidSystemClock_Config(void){RCC_OscInitTypeDef RCC_OscInitStruct{0};RCC_ClkInitTypeDef RCC_ClkInitStruct{0};/** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */RCC_OscInitStruct.OscillatorTypeRCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEStateRCC_HSE_ON;RCC_OscInitStruct.HSEPredivValueRCC_HSE_PREDIV_DIV1;RCC_OscInitStruct.HSIStateRCC_HSI_ON;RCC_OscInitStruct.PLL.PLLStateRCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSourceRCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLMULRCC_PLL_MUL9;if(HAL_RCC_OscConfig(RCC_OscInitStruct)!HAL_OK){Error_Handler();}/** Initializes the CPU, AHB and APB buses clocks */RCC_ClkInitStruct.ClockTypeRCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;RCC_ClkInitStruct.SYSCLKSourceRCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDividerRCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDividerRCC_HCLK_DIV2;RCC_ClkInitStruct.APB2CLKDividerRCC_HCLK_DIV1;if(HAL_RCC_ClockConfig(RCC_ClkInitStruct,FLASH_LATENCY_2)!HAL_OK){Error_Handler();}}/* USER CODE BEGIN 4 *//* USER CODE END 4 *//** * brief This function is executed in case of error occurrence. * retval None */voidError_Handler(void){/* USER CODE BEGIN Error_Handler_Debug *//* User can add his own implementation to report the HAL error return state */__disable_irq();while(1){}/* USER CODE END Error_Handler_Debug */}#ifdefUSE_FULL_ASSERT/** * brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * param file: pointer to the source file name * param line: assert_param error line source number * retval None */voidassert_failed(uint8_t*file,uint32_tline){/* USER CODE BEGIN 6 *//* User can add his own implementation to report the file name and line number, ex: printf(Wrong parameters value: file %s on line %d\r\n, file, line) *//* USER CODE END 6 */}#endif/* USE_FULL_ASSERT */烧录验证效果