STM32CubeMx開發之路—13使用SPI讀寫W25Q64
運行環境
Windows10
STM32CubeMX
Version 5.2.0
Keil5(MDK5)
Version 5.28.0.0
簡介
本例程主要講解如何使用硬件IIC讀寫24C02
STM32CubeMx基本配置
基礎配置過程請參考 STM32CubeMx開發之路—配置第一個項目
使用printf
功能
重定向printf
的過程請參考 STM32CubeMx開發之路—3發送USART數據和printf重定向
CubeMX配置
代碼修改
- 查看W25Q64的手冊(後面配置時需要用的命令都在裏面)
- 封裝功能函數的代碼(講解寫在代碼裏面)
/* W25Q64的指令 */
uint8_t w25x_read_id = 0x90; // 讀ID
uint8_t m_addr[3] = {0,0,0}; // 測試地址0x000000
uint8_t check_addr = 0x05; // 檢查線路是否繁忙
uint8_t enable_write = 0x06; // 使能了才能改變芯片數據
uint8_t erase_addr = 0x20; // 擦除命令
uint8_t write_addr = 0x02; // 寫數據命令
uint8_t read_addr = 0x03; // 讀數據命令
/* 讀ID */
void ReadID(void)
{
uint8_t temp_ID[5] = {0,0,0,0,0}; // 接收緩存
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_RESET); // 使能CS
HAL_SPI_Transmit(&hspi2, &w25x_read_id, 1, 100); // 讀ID發送指令
HAL_SPI_Receive(&hspi2, temp_ID, 5, 100); // 讀取ID
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_SET); // 失能CS
/* 測試打印 */
printf("readID is %x%x\n",temp_ID[3],temp_ID[4]);
}
/* 檢查是否繁忙 */
void CheckBusy(void)
{
uint8_t status=1;
uint32_t timeCount=0;
do
{
timeCount++;
if(timeCount > 0xEFFFFFFF) //等待超時
{
return ;
}
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_RESET); // 使能CS
HAL_SPI_Transmit(&hspi2, &check_addr, 1, 100); // 發送指令
HAL_SPI_Receive(&hspi2, &status, 1, 100); // 讀取
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_SET); // 失能CS
}while((status&0x01)==0x01);
}
/* 寫入數據 */
void ReadData(void)
{
uint8_t temp_wdata[5] = {0x99,0x88,0x77,0x66,0x55}; // 需要寫入的數據
/* 檢查是否繁忙 */
CheckBusy();
/* 寫使能 */
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_RESET); // 使能CS
HAL_SPI_Transmit(&hspi2, &enable_write, 1, 100); // 發送指令
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_SET); // 失能CS
/* 擦除 */
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_RESET); // 使能CS
HAL_SPI_Transmit(&hspi2, &erase_addr, 1, 100); // 發送指令
HAL_SPI_Transmit(&hspi2, m_addr, 3, 100); // 發送地址
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_SET); // 失能CS
/* 再次檢查是否繁忙 */
CheckBusy();
/* 寫使能 */
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_RESET); // 使能CS
HAL_SPI_Transmit(&hspi2, &enable_write, 1, 100); // 發送指令
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_SET); // 失能CS
/* 寫數據 */
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_RESET); // 使能CS
HAL_SPI_Transmit(&hspi2, &write_addr, 1, 100); // 發送指令
HAL_SPI_Transmit(&hspi2, m_addr, 3, 100); // 地址
HAL_SPI_Transmit(&hspi2, temp_wdata, 5, 100); // 寫入數據
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_SET); // 失能CS
}
/* 讀取數據 */
void WriteData(void)
{
uint8_t temp_rdata[5] = {0,0,0,0,0}; // 讀出數據保存的buff
/* 檢查是否繁忙 */
CheckBusy();
/* 開始讀數據 */
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_RESET); // 使能CS
HAL_SPI_Transmit(&hspi2, &read_addr, 1, 100); // 讀發送指令
HAL_SPI_Transmit(&hspi2, m_addr, 3, 100); // 地址
HAL_SPI_Receive(&hspi2, temp_rdata, 5, 100); // 拿到數據
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_13, GPIO_PIN_SET); // 失能CS
/* 測試打印 */
printf("Read flash data is:%x %x %x %x %x\n",temp_rdata[0],temp_rdata[1],temp_rdata[2],temp_rdata[3],temp_rdata[4]);
}
- main函數
int main(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_SPI2_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
ReadID();
WriteData();
ReadData();
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
運行結果
- 燒錄進去,用串口調試助手
- 發現輸出的就是我們存進的數據,說明測試成功
源碼
小結
SPI在實際應用過程非常廣泛,而且速度也是比較快的,也是嵌入式需瞭解的協議之一,所以一定要好好理解!
備註:提供一下個人微信號 Hleafleafleaf,歡迎加好友,共同學習!共同進步!