STM32 | 您所在的位置:网站首页 › 外置flash芯片加密 › STM32 |
一、工具
1、硬件:STM32F103VET6单片机(HAL库) 2、编译环境:Atollic TrueSTUDIO for STM32 9.3.0 3、辅助工具:STM32CubeMX 二、电路原理图1、时钟源选择: 2、时钟树: 1、选用的是SPI1,全双工主机模式(单片机是主机,外部FLASH做从机),片选引脚由软件控制。 2、再检查一下SPI1的引脚设置是否正确。 3、设置FLASH的片选引脚即PC0引脚为输出模式,因为SPI1上只有一个器件,默认输出低电平。 1、SPI1初始化代码如下所示: static void MX_SPI1_Init(void) { /* USER CODE BEGIN SPI1_Init 0 */ /* USER CODE END SPI1_Init 0 */ /* USER CODE BEGIN SPI1_Init 1 */ /* USER CODE END SPI1_Init 1 */ /* SPI1 parameter configuration*/ hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 10; if (HAL_SPI_Init(&hspi1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN SPI1_Init 2 */ /* USER CODE END SPI1_Init 2 */ }2、SPI1引脚及其相关的代码如下所示: /** * @brief SPI MSP Initialization * This function configures the hardware resources used in this example * @param hspi: SPI handle pointer * @retval None */ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(hspi->Instance==SPI1) { /* USER CODE BEGIN SPI1_MspInit 0 */ /* USER CODE END SPI1_MspInit 0 */ /* Peripheral clock enable */ __HAL_RCC_SPI1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO PA7 ------> SPI1_MOSI */ GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN SPI1_MspInit 1 */ /* USER CODE END SPI1_MspInit 1 */ } } /** * @brief SPI MSP De-Initialization * This function freeze the hardware resources used in this example * @param hspi: SPI handle pointer * @retval None */ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) { if(hspi->Instance==SPI1) { /* USER CODE BEGIN SPI1_MspDeInit 0 */ /* USER CODE END SPI1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_SPI1_CLK_DISABLE(); /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK PA6 ------> SPI1_MISO PA7 ------> SPI1_MOSI */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7); /* USER CODE BEGIN SPI1_MspDeInit 1 */ /* USER CODE END SPI1_MspDeInit 1 */ } }/** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET); /*Configure GPIO pin : PC0 */ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); } 六、编写与Flash的相关代码 1、读一个字节 /** * @brief SPI1 读一个字节 * @param None * @retval None */ static uint8_t spi1_flash_read_byte(void) { uint8_t t_data, r_data; if(HAL_SPI_TransmitReceive(&hspi1, &t_data, &r_data, 1, 0xFFFFFF) != HAL_OK) { r_data = 0xff; } return r_data; }2、写一个字节 /** * @brief SPI1 写一个字节 * @param byte 写入的字节 * @retval 写状态 0成功 1失败 */ static uint8_t spi1_flash_send_byte(uint8_t byte) { uint8_t r_data; if(HAL_SPI_TransmitReceive(&hspi1, &byte, &r_data, 1, 0xFFFFFF) != HAL_OK) { return 1; } return 0; }3、Flash写使能 /** * @brief FLASH 写使能 * @param None * @retval None */ static void spi1_flash_write_enable(void) { cs_low; spi1_flash_send_byte(0x06); cs_high; }4、Flash等待写结束 /** * @brief FLASH 等待写结束 * @param None * @retval None */ static void spi1_flash_wait_for_write_end(void) { uint8_t state = 0; cs_low; spi1_flash_send_byte(0x05); do { state = spi1_flash_read_byte(); } while((state & 0x01) == SET); cs_high; }5、读Flash的ID /** * @brief FLASH 读ID * @param None * @retval None */ uint32_t spi_flash_read_ID(void) { uint32_t temp, temp0, temp1, temp2; cs_low; spi1_flash_send_byte(0x9F); temp0 = spi1_flash_read_byte(); temp1 = spi1_flash_read_byte(); temp2 = spi1_flash_read_byte(); cs_high; temp = (temp0 16); spi1_flash_send_byte((addr & 0xFF00) >> 8); spi1_flash_send_byte(addr & 0xFF); while (size--) { *pdata = spi1_flash_read_byte(); pdata++; } cs_high; }7、按页写Flash /** * @brief 按页写FLASH * @param addr 写入flash的起始地址 * @param pdata 写入数据的起始地址 * pdata size 写数据大小 * @retval None */ void spi1_flash_page_write(uint32_t addr, uint8_t *pdata, uint16_t size) { uint16_t i; spi1_flash_write_enable(); cs_low; spi1_flash_send_byte(0x02); spi1_flash_send_byte((uint8_t)((addr)>>16)); spi1_flash_send_byte((uint8_t)((addr)>>8)); spi1_flash_send_byte((uint8_t)addr); for(i = 0; i < size; i++) { spi1_flash_send_byte(pdata[i]); } cs_high; spi1_flash_wait_for_write_end(); }8、写Flash /** * @brief 写FLASH * @param addr 写入flash的起始地址 * @param pdata 写入数据的起始地址 * pdata size 写数据大小 * @retval None */ void spi1_flash_write(uint32_t addr, uint8_t *pdata, uint32_t size) { uint32_t page_remain; page_remain = 256 - addr%256; if(size 256) page_remain = 256; else page_remain = size; } } }9、擦除Flash扇区 /** * @brief 擦除FLASH扇区 * @param sector_addr 扇区的起始地址 * @retval None */ void spi1_flash_sector_erase(uint32_t sector_addr) { spi1_flash_write_enable(); spi1_flash_wait_for_write_end(); cs_low; spi1_flash_send_byte(0x20); spi1_flash_send_byte((sector_addr & 0xFF0000) >> 16); spi1_flash_send_byte((sector_addr & 0xFF00) >> 8); spi1_flash_send_byte(sector_addr & 0xFF); cs_high; spi1_flash_wait_for_write_end(); }10、擦除Flash块 /** * @brief 擦除FLASH块 * @param None * @retval None */ void spi1_flash_block_erase(void) { spi1_flash_write_enable(); cs_low; spi1_flash_send_byte(0xC7); cs_high; spi1_flash_wait_for_write_end(); }
#endif
|
CopyRight 2018-2019 实验室设备网 版权所有 |