国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

STM32 SPI+DMA 驅(qū)動(dòng) SRAM LY68L6400SLIT 應(yīng)用筆記

這篇具有很好參考價(jià)值的文章主要介紹了STM32 SPI+DMA 驅(qū)動(dòng) SRAM LY68L6400SLIT 應(yīng)用筆記。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

關(guān)鍵詞:庫(kù)函數(shù),STM32F407,SPI+DMA ,SPI-DMA,SRAM , LY68L6400SLIT,STM32CubeMX

編 輯:大黃蜂

說(shuō)明:本筆記記錄 基于 STM32F407 + RT RTOS 采用 SPI接口和 SPI+DMA接口 調(diào)試 SRAM LY68L6400SLIT (8M 字節(jié) SRAM)

重點(diǎn):STM32 HAL SPI 庫(kù)函數(shù);STM32CubeMX SPI 配置;STM32CubeMX SPI 配置+DMA配置;SPI+DMA 讀寫SRAM

項(xiàng)目測(cè)試平臺(tái):STM32F407核心板 + LY68L6400SLIT (8M 字節(jié) SRAM)+ rt-thread4.0.2

調(diào)試心得:

1:調(diào)試 SRAM 時(shí)最開(kāi)始用的是 STM32CubeMX 配置的 SPI 配置代碼和 SPI 庫(kù)函數(shù),先期調(diào)試還算順利,但測(cè)試時(shí)發(fā)現(xiàn)代碼在讀寫大數(shù)據(jù)量,例如寫滿8M 耗時(shí)不記得了,讀完8M耗時(shí)在14s左右。

2:希望優(yōu)化 SRAM的讀寫速度,所以使用 SPI + DMA 讀寫,這個(gè)調(diào)試過(guò)程從最開(kāi)始的讀寫錯(cuò)誤,到后面發(fā)現(xiàn)有部分?jǐn)?shù)據(jù)是準(zhǔn)確的,再到讀寫不穩(wěn)定,最后讀寫徹底穩(wěn)定,連續(xù)讀寫15小時(shí)無(wú)錯(cuò)誤。

3:發(fā)生SPI + DMA 調(diào)試不順的問(wèn)題主要是忽略了 DMA 發(fā)送數(shù)據(jù)的機(jī)制,DMA發(fā)送是需要時(shí)間的,一開(kāi)始的測(cè)試代碼都是執(zhí)行了 DMA發(fā)送代碼就立即 關(guān)掉了SRAM的使能。代碼從執(zhí)行了DMA讀寫后就立刻關(guān)掉了使能,這時(shí)DMA實(shí)際上正在執(zhí)行讀寫操作,從而導(dǎo)致了DMA讀寫錯(cuò)誤。

4:優(yōu)化,在發(fā)現(xiàn) DMA 收發(fā)都需要時(shí)間這一問(wèn)題后,對(duì)此做了判斷 DMA 狀態(tài)的優(yōu)化,讀寫DMA都先判斷DMA就緒后再進(jìn)行下一步操作,從而完成了SPI + DMA 對(duì) SARM的讀寫測(cè)試。

5:在配置了 SPI + DMA 配置情況下,SPI直接讀寫函數(shù)和SPI+DMA函數(shù)都可以直接讀寫。

6:SPI + DMA 測(cè)試結(jié)果,SPI 時(shí)鐘頻率 40 M, 連續(xù)寫8M數(shù)據(jù)耗時(shí):1784ms ;連續(xù)讀8M數(shù)據(jù)耗時(shí):2070ms ;連續(xù)讀8M數(shù)據(jù) 每次讀 1K + CRC校驗(yàn) 耗時(shí):14245ms。以上測(cè)試數(shù)據(jù)都是讀寫函數(shù)按每次 512字節(jié)讀寫情況下測(cè)試結(jié)果。

7:SRAM 讀寫在MCU上電前先復(fù)位一下 SRAM,避免因 MCU 重啟而 SRAM 沒(méi)有復(fù)位 導(dǎo)致出現(xiàn)讀寫異常的問(wèn)題。

/* 調(diào)試遇到讀寫問(wèn)題時(shí)的代碼 */
rt_pin_write(SPI_SRAM_CS  , 0);                    /*使能SRAM 用RT函數(shù)控制*/
HAL_SPI_Transmit_DMA(&hspi1, pData, 5);            /*發(fā)送數(shù)據(jù)*/
HAL_SPI_Receive_DMA(&hspi1, ReadData, read_size);  /*接收數(shù)據(jù)*/
rt_pin_write(SPI_SRAM_CS  , 1);                    /*去使能SRAM 用RT函數(shù)控制*/

/* 優(yōu)化后正常測(cè)試的代碼 */
while(hdma_spi1_rx.State != HAL_DMA_STATE_READY ); /*等待DMA就緒*/
while(hdma_spi1_tx.State != HAL_DMA_STATE_READY ); /*等待DMA就緒*/
rt_pin_write(SPI_SRAM_CS  , 0);                    /*使能SRAM 用RT函數(shù)控制*/
HAL_SPI_Transmit_DMA(&hspi1, pData, 5);            /*發(fā)送數(shù)據(jù)*/
while(hdma_spi1_tx.State != HAL_DMA_STATE_READY ); /*等待DMA發(fā)送完成*/
HAL_SPI_Receive_DMA(&hspi1, ReadData, read_size);  /*接收數(shù)據(jù)*/
while(hdma_spi1_rx.State != HAL_DMA_STATE_READY ); /*等待DMA接收完成*/
rt_pin_write(SPI_SRAM_CS  , 1);             /*去使能SRAM 用RT函數(shù)控制*/

1:硬件圖紙、連接

核心板資料:STM32F407VxT6 Board - LCD wiki

如圖:將SRAM直接焊接到箭頭指的FLASH封裝上, 例程測(cè)試時(shí)是把 SRAM直接背到FLASH,再把CS管腳單獨(dú)連接到LED0的驅(qū)動(dòng)腳。

spi sram,STM32,stm32,單片機(jī),嵌入式硬件

?

?spi sram,STM32,stm32,單片機(jī),嵌入式硬件

?2:STM32CubeMX SPI 配置流程、工程包

2.1配置調(diào)試接口

spi sram,STM32,stm32,單片機(jī),嵌入式硬件

?2.2配置時(shí)鐘

spi sram,STM32,stm32,單片機(jī),嵌入式硬件

?spi sram,STM32,stm32,單片機(jī),嵌入式硬件

2.3配置SPI?

spi sram,STM32,stm32,單片機(jī),嵌入式硬件

?2.4配置SPI 的 DMA

spi sram,STM32,stm32,單片機(jī),嵌入式硬件

?2.5工程輸出設(shè)置

spi sram,STM32,stm32,單片機(jī),嵌入式硬件

?工程輸出設(shè)置

spi sram,STM32,stm32,單片機(jī),嵌入式硬件

?2.6生成代碼

spi sram,STM32,stm32,單片機(jī),嵌入式硬件

?生成后的文件路徑,截圖是壓縮包壓縮后的參考路徑,實(shí)際路徑根據(jù)工程保存路徑查找。

spi sram,STM32,stm32,單片機(jī),嵌入式硬件

?

3:STM32CubeMX SPI 代碼移植、代碼注釋

3.1 把STM32CubeMX生成的 SPI 和 DMA 代碼復(fù)制到 RT 工程的 board.c 文件后面

如:代碼有兩個(gè)模式 SPI 和 SPI + DMA 模式,根據(jù)宏定義選擇

/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-09-15     RealThread   first version
 */

//#include <rtthread.h>     /* 這里把頭文件轉(zhuǎn)移到 user_cfg.h 文件下面了 */
//#include <board.h>        /* 這里把頭文件轉(zhuǎn)移到 user_cfg.h 文件下面了 */
//#include <drv_common.h>   /* 這里把頭文件轉(zhuǎn)移到 user_cfg.h 文件下面了 */
#include "user_cfg.h"

RT_WEAK void rt_hw_board_init()
{
    extern void hw_board_init(char *clock_src, int32_t clock_src_freq, int32_t clock_target_freq);

    /* Heap initialization */
#if defined(RT_USING_HEAP)
    rt_system_heap_init((void *) HEAP_BEGIN, (void *) HEAP_END);
#endif

    hw_board_init(BSP_CLOCK_SOURCE, BSP_CLOCK_SOURCE_FREQ_MHZ, BSP_CLOCK_SYSTEM_FREQ_MHZ);

    /* Set the shell console output device */
#if defined(RT_USING_DEVICE) && defined(RT_USING_CONSOLE)
    rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif

    /* Board underlying hardware initialization */
#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif

}


/* SPI 模式 */

#if SRAM_LY64_MODE_SPI
SPI_HandleTypeDef hspi1;

/* SPI1 init function */
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 */
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_MASTER;            //主機(jī)模式
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;  //全雙工
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;      //數(shù)據(jù)位為8位
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;    //CPOL=0
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;        //CPHA為數(shù)據(jù)線的第一個(gè)變化沿
  hspi1.Init.NSS = SPI_NSS_SOFT;                //軟件控制NSS
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; //2分頻
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;                 //最高位先發(fā)送
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;                 //禁用TI模式
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; //禁用CRC校驗(yàn)
  hspi1.Init.CRCPolynomial = 10;                          //CRC值計(jì)算的多項(xiàng)式
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI1_Init 2 */

  /* USER CODE END SPI1_Init 2 */

}
INIT_COMPONENT_EXPORT(MX_SPI1_Init);

void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(spiHandle->Instance==SPI1)
  {
  /* USER CODE BEGIN SPI1_MspInit 0 */

  /* USER CODE END SPI1_MspInit 0 */
    /* SPI1 clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();

    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**SPI1 GPIO Configuration
    PB3     ------> SPI1_SCK
    PB4     ------> SPI1_MISO
    PB5     ------> SPI1_MOSI
    */
    GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* USER CODE BEGIN SPI1_MspInit 1 */

  /* USER CODE END SPI1_MspInit 1 */
  }
}

void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
{

  if(spiHandle->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
    PB3     ------> SPI1_SCK
    PB4     ------> SPI1_MISO
    PB5     ------> SPI1_MOSI
    */
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5);

  /* USER CODE BEGIN SPI1_MspDeInit 1 */

  /* USER CODE END SPI1_MspDeInit 1 */
  }
}

#endif



/* SPI + DMA 模式 */

#if SRAM_LY64_MODE_SPI_DMA
/* USER CODE END 0 */

 SPI_HandleTypeDef hspi1;
 DMA_HandleTypeDef hdma_spi1_rx;
 DMA_HandleTypeDef hdma_spi1_tx;

/* SPI1 init function */
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 */
  hspi1.Instance = SPI1;                                      //SP1
  hspi1.Init.Mode = SPI_MODE_MASTER;                          //設(shè)置SPI工作模式,設(shè)置為主模式
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;                //設(shè)置SPI單向或者雙向的數(shù)據(jù)模式:SPI設(shè)置為雙線模式
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;                    //設(shè)置SPI的數(shù)據(jù)大小:SPI發(fā)送接收8位幀結(jié)構(gòu)
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;                  //串行同步時(shí)鐘的空閑狀態(tài)為高/底電平
  hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;                      //串行同步時(shí)鐘的第1個(gè)跳變沿(上升或下降)數(shù)據(jù)被采樣
  hspi1.Init.NSS = SPI_NSS_SOFT;                              //NSS信號(hào)由硬件(NSS管腳)還是軟件(使用SSI位)管理:內(nèi)部NSS信號(hào)有SSI位控制
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;     //定義波特率預(yù)分頻的值
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;                     //指定數(shù)據(jù)傳輸從MSB位還是LSB位開(kāi)始:數(shù)據(jù)傳輸從MSB位開(kāi)始
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;                     //關(guān)閉TI模式
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;     //關(guān)閉硬件CRC校驗(yàn)
  hspi1.Init.CRCPolynomial = 10;                              //CRC值計(jì)算的多項(xiàng)式
  if (HAL_SPI_Init(&hspi1) != HAL_OK)                         //初始化
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI1_Init 2 */

  /* USER CODE END SPI1_Init 2 */

}

void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(spiHandle->Instance==SPI1)
  {
  /* USER CODE BEGIN SPI1_MspInit 0 */

  /* USER CODE END SPI1_MspInit 0 */
    /* SPI1 clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();

    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**SPI1 GPIO Configuration
    PB3     ------> SPI1_SCK
    PB4     ------> SPI1_MISO
    PB5     ------> SPI1_MOSI
    */
    GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    /* SPI1 DMA Init */
    /* SPI1_RX Init */
    hdma_spi1_rx.Instance = DMA2_Stream0;                         //數(shù)據(jù)流選擇
    hdma_spi1_rx.Init.Channel = DMA_CHANNEL_3;                    //通道選擇
    hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;           //外設(shè)到存儲(chǔ)器
    hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;               //外設(shè)非增量模式
    hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;                   //存儲(chǔ)器增量模式
    hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;  //外設(shè)數(shù)據(jù)長(zhǎng)度:8位
    hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;     //存儲(chǔ)器數(shù)據(jù)長(zhǎng)度:8位
    hdma_spi1_rx.Init.Mode = DMA_NORMAL;                          //外設(shè)流控模式
    hdma_spi1_rx.Init.Priority = DMA_PRIORITY_LOW;                //低優(yōu)先級(jí)
    hdma_spi1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(spiHandle,hdmarx,hdma_spi1_rx);                 //將DMA與SPI1聯(lián)系起來(lái)(發(fā)送DMA)

    /* SPI1_TX Init */
    hdma_spi1_tx.Instance = DMA2_Stream3;
    hdma_spi1_tx.Init.Channel = DMA_CHANNEL_3;
    hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;

    hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi1_tx.Init.Mode = DMA_NORMAL;
    hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW;
    hdma_spi1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
    {
      Error_Handler();
    }

    __HAL_LINKDMA(spiHandle,hdmatx,hdma_spi1_tx);

  /* USER CODE BEGIN SPI1_MspInit 1 */

  /* USER CODE END SPI1_MspInit 1 */
  }
}

void HAL_SPI_MspDeInit(SPI_HandleTypeDef* spiHandle)
{

  if(spiHandle->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
    PB3     ------> SPI1_SCK
    PB4     ------> SPI1_MISO
    PB5     ------> SPI1_MOSI
    */
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5);

    /* SPI1 DMA DeInit */
    HAL_DMA_DeInit(spiHandle->hdmarx);
    HAL_DMA_DeInit(spiHandle->hdmatx);
  /* USER CODE BEGIN SPI1_MspDeInit 1 */

  /* USER CODE END SPI1_MspDeInit 1 */
  }
}

/* USER CODE BEGIN 1 */


void MX_DMA_Init(void)
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA2_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA2_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
  /* DMA2_Stream3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);

}

void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_RESET);

  /*Configure GPIO pin : PB14 */
  GPIO_InitStruct.Pin = GPIO_PIN_14;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

int SPI_Init_User()
{
    MX_GPIO_Init();
    MX_DMA_Init();
    MX_SPI1_Init();
    return 1;
}
INIT_COMPONENT_EXPORT(SPI_Init_User);


/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

/******************************************************************************/
/* STM32F4xx Peripheral Interrupt Handlers                                    */
/* Add here the Interrupt Handlers for the used peripherals.                  */
/* For the available peripheral interrupt handler names,                      */
/* please refer to the startup file (startup_stm32f4xx.s).                    */
/******************************************************************************/
extern DMA_HandleTypeDef hdma_spi1_rx;
extern DMA_HandleTypeDef hdma_spi1_tx;
/**
  * @brief This function handles DMA2 stream0 global interrupt.
  */
void DMA2_Stream0_IRQHandler(void)
{
  /* USER CODE BEGIN DMA2_Stream0_IRQn 0 */

  /* USER CODE END DMA2_Stream0_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_spi1_rx);
  /* USER CODE BEGIN DMA2_Stream0_IRQn 1 */

  /* USER CODE END DMA2_Stream0_IRQn 1 */
}

/**
  * @brief This function handles DMA2 stream3 global interrupt.
  */
void DMA2_Stream3_IRQHandler(void)
{
  /* USER CODE BEGIN DMA2_Stream3_IRQn 0 */

  /* USER CODE END DMA2_Stream3_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_spi1_tx);
  /* USER CODE BEGIN DMA2_Stream3_IRQn 1 */

  /* USER CODE END DMA2_Stream3_IRQn 1 */
}

#endif

4:HAL SPI 相關(guān)函數(shù)

參考1:以下內(nèi)容摘錄:https://www.cnblogs.com/xingboy/p/9555708.html

HAL庫(kù)里的硬件SPI主要有以下幾個(gè)庫(kù)函數(shù):

? /*  hspi1:spi1 硬件通道,temp_val:發(fā)送的數(shù)據(jù),re_val:接收的數(shù)據(jù),1:數(shù)據(jù)長(zhǎng)度,1000:超時(shí)時(shí)間  */
  HAL_SPI_TransmitReceive(&hspi1,? &temp_val, &re_val, 1, 1000);? ?// 一邊接受一邊發(fā)送數(shù)據(jù)
  HAL_SPI_Transmit(&hspi1,&temp,sizeof(temp),10);  //發(fā)送數(shù)據(jù)
  HAL_SPI_Receive(&hspi1,&sc1161y_sel_re,sizeof(sc1161y_sel_re),10); //接收數(shù)據(jù)
  HAL_SPI_TransmitReceive_DMA();  //以DMA方式發(fā)送數(shù)據(jù)
  HAL_SPI_Receive_DMA();  //以DMA方式接收數(shù)據(jù)
  HAL_SPI_TransmitReceive_IT();  // 以中斷方式同時(shí)接收發(fā)送數(shù)據(jù)
  HAL_SPI_Transmit_IT();  // 以中斷方式發(fā)送數(shù)據(jù)
  HAL_SPI_Receive_IT();  // 以中斷方式接收數(shù)據(jù)

具體使用哪個(gè)HAL庫(kù)函數(shù)看項(xiàng)目需求。

在使用硬件SPI過(guò)程中,會(huì)出現(xiàn)的問(wèn)題可以總結(jié)為以下幾點(diǎn):

  1.發(fā)送數(shù)據(jù)不成功;

  2.接收數(shù)據(jù)不成功;

  3.發(fā)送的數(shù)據(jù)有誤;

  4.接收的數(shù)據(jù)有誤;

  5.交互的數(shù)據(jù)一部分是對(duì)的,一部分有誤;

  6.SPI時(shí)鐘沒(méi)有啟動(dòng)。

對(duì)于以上解決方法,我總結(jié)了一個(gè)自己調(diào)試時(shí)的方法:

  1. 先確認(rèn)自己的SPI配置是否正確,是否滿足項(xiàng)目需求;

  2. 確認(rèn)電路與通信IC無(wú)誤,注意信號(hào)線不要接錯(cuò);

  3. 重點(diǎn):調(diào)節(jié)延時(shí),第一第二步確認(rèn)無(wú)誤后,很多時(shí)候不成功是由于延時(shí)原因造成的,

  ? ? 主要是一個(gè)數(shù)據(jù)交互之間的延時(shí),一幀數(shù)據(jù)發(fā)送后跟接收的延時(shí),IC片選的延時(shí),

   每個(gè)數(shù)據(jù)發(fā)送間的延時(shí),IC與MCU交互間的延時(shí)。

5:SPI SRAM讀寫測(cè)試代碼

/*
 * Copyright (c) 2006-2020, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-09-16     yl       the first version
 * .程序功能LY68L6400 讀寫
 *
 */

#include "user_cfg.h"
//#include <rtthread.h>
//#include <board.h>
//#include <rtdevice.h>
//#include "drv_spi.h"

#define SPI_SRAM_NEME                   "spi11"
#define SPI_SRAM_CS                     GET_PIN(A, 1)
#define LY64_CS(X)                      X? (GPIOA->ODR |= (0X0001<<1)):(GPIOA->ODR &=~ (0X0001<<1))   /* IO 直接控制控制模式 PA1 輸出1 或者 0 */
#define SPI_FLASH_CS                    GET_PIN(B, 14)
#define SRAM_LY64_CMD_READ              0x0B        /*LY68L6400 快速讀取命令 */
#define SRAM_LY64_CMD_WRITE             0x02        /*LY68L6400 寫命令 */
#define SRAM_LY64_CMD_READ_ID           0x9F        /*LY68L6400 讀ID命令*/
#define SRAM_LY64_CMD_Reset_Enable      0x66        /*LY68L6400 復(fù)位使能*/
#define SRAM_LY64_CMD_Reset             0x99        /*LY68L6400 復(fù)位*/

#define SRAM_LY64_SIZE                  1024*1024*8 /*LY68L6400 空間大小 字節(jié)*/

#define SRAM_LY64_ID_LEN                8           /*LY68L6400 ID長(zhǎng)度 字節(jié)*/
#define SRAM_LY64_READ_LEN              512         /*LY68L6400 讀取函數(shù)單次讀取的最大長(zhǎng)度,如果超過(guò)這個(gè)數(shù)量函數(shù)自動(dòng)分多次讀取*/
#define WR_SIZE                         1024        /*LY68L6400 寫入函數(shù)單次寫取的最大長(zhǎng)度,如果超過(guò)這個(gè)數(shù)量函數(shù)自動(dòng)分多次寫入*/

#define READ_DATA_CRC                   1           /*LY68L6400 讀取數(shù)據(jù)測(cè)試時(shí) CRC 校驗(yàn)開(kāi)關(guān),需要計(jì)算讀取時(shí)間時(shí)可以關(guān)閉CRC,1開(kāi)啟  0關(guān)閉*/
#define READ_DATA_PRINTF                0           /*LY68L6400 打印讀取的SRAM數(shù)據(jù) ,1開(kāi)啟  0關(guān)閉*/
/**
  * @brief   描  述:讀取SRAM的ID
  * @param   參數(shù)1:uint32_t Size 讀取數(shù)據(jù)量.
  * @param   參數(shù)2:uint8_t *ReadData 讀取的數(shù)據(jù)存儲(chǔ)地址.
  * @retval  回  復(fù):無(wú).
  * @author  作  者:YL
  * @date    日  期:2021.10.07
  * @version 版 本:V1.0
  * @warning 警 告:
  */
void Sram_LY64_Read_ID(uint32_t Size,uint8_t *ReadData)
{
        uint8_t pData[4];

        pData[0] = SRAM_LY64_CMD_READ_ID;
        pData[1] = 0;
        pData[2] = 0;
        pData[3] = 0;

        rt_enter_critical();/*調(diào)度器上鎖*/

        rt_pin_write(SPI_SRAM_CS  , 0);             /*使能SRAM*/
        rt_hw_us_delay(2);
        HAL_SPI_Transmit(&hspi1, pData, 4, 2);      /*發(fā)送數(shù)據(jù)*/
        HAL_SPI_Receive(&hspi1, ReadData, Size,  2);/*接收數(shù)據(jù)*/

        rt_pin_write(SPI_SRAM_CS  , 1);             /*去使能SRAM*/
        rt_exit_critical();/*調(diào)度器解鎖*/
}

/**
  * @brief   描  述:復(fù)位SRAM
  * @param   參數(shù)1:
  * @retval  回  復(fù):無(wú).
  * @author  作  者:YL
  * @date    日  期:2021.10.13
  * @version 版 本:V1.0
  * @warning 警 告:
  */
void Sram_LY64_Reset(void)
{
        uint8_t pData[2];

        pData[0] = SRAM_LY64_CMD_Reset_Enable;
        pData[1] = SRAM_LY64_CMD_Reset;

        rt_enter_critical();/*調(diào)度器上鎖*/

        rt_pin_write(SPI_SRAM_CS  , 0);             /*使能SRAM*/
        rt_hw_us_delay(2);
        HAL_SPI_Transmit(&hspi1, pData, 2, 2);      /*發(fā)送數(shù)據(jù)*/

        rt_pin_write(SPI_SRAM_CS  , 1);             /*去使能SRAM*/
        rt_exit_critical();/*調(diào)度器解鎖*/
}

/**
  * @brief   描  述:讀取指定地址開(kāi)始指定數(shù)量的 SRAM數(shù)據(jù).
  * @param   參數(shù)1:uint32_t addr 開(kāi)始地址.
  * @param   參數(shù)2:uint32_t Size 讀取數(shù)據(jù)量.
  * @param   參數(shù)3:uint8_t *ReadData 讀取的數(shù)據(jù)存儲(chǔ)地址.
  * @retval  回  復(fù):無(wú).
  * @author  作  者:YL
  * @date    日  期:2021.10.07
  * @version 版 本:V1.0
  * @warning 警 告:如果讀取數(shù)量超過(guò) SRAM_LY64_READ_LEN 程序會(huì)自動(dòng)按設(shè)置好的單次讀取最大數(shù)量分多次讀取。
  */
void Sram_LY64_Read(uint32_t addr,uint32_t Size,uint8_t *ReadData)
{
    uint8_t pData[5];
    uint16_t read_size;

    do
    {
        pData[0] = SRAM_LY64_CMD_READ;
        pData[1] = addr>>16;
        pData[2] = addr>>8;
        pData[3] = addr;
        pData[4] = 0x00; /* SPI Fast Read ‘h0B 命令的時(shí)序要求要等待8個(gè)時(shí)鐘周期。 */

        if (Size > SRAM_LY64_READ_LEN)
        {
            read_size = SRAM_LY64_READ_LEN;
            Size = Size - SRAM_LY64_READ_LEN;
        }
        else
        {
            read_size = Size;
            Size = 0;
        }

#if SRAM_LY64_MODE_SPI
        //rt_enter_critical();/*調(diào)度器上鎖*/
        rt_pin_write(SPI_SRAM_CS  , 0);                   /*使能SRAM 用RT函數(shù)控制*/
        //LY64_CS(0);                                     /*使能SRAM 寄存器直接控制*/
        rt_hw_us_delay(2);

        HAL_SPI_Transmit(&hspi1, pData, 5, 2);            /*發(fā)送數(shù)據(jù)*/
        HAL_SPI_Receive(&hspi1, ReadData, read_size, 2);  /*接收數(shù)據(jù)*/
#endif

#if SRAM_LY64_MODE_SPI_DMA
        while(hdma_spi1_rx.State != HAL_DMA_STATE_READY ); /*等待DMA就緒*/
        while(hdma_spi1_tx.State != HAL_DMA_STATE_READY ); /*等待DMA就緒*/
        rt_pin_write(SPI_SRAM_CS  , 0);                    /*使能SRAM 用RT函數(shù)控制*/
        HAL_SPI_Transmit_DMA(&hspi1, pData, 5);            /*發(fā)送數(shù)據(jù)*/
        while(hdma_spi1_tx.State != HAL_DMA_STATE_READY ); /*等待DMA發(fā)送完成*/
        HAL_SPI_Receive_DMA(&hspi1, ReadData, read_size);  /*接收數(shù)據(jù)*/
        while(hdma_spi1_rx.State != HAL_DMA_STATE_READY ); /*等待DMA接收完成*/
#endif

        rt_pin_write(SPI_SRAM_CS  , 1);             /*去使能SRAM 用RT函數(shù)控制*/
        //LY64_CS(1);                                   /*去使能SRAM 寄存器直接控制*/
        //rt_exit_critical();/*調(diào)度器解鎖*/
        addr = addr + read_size;
        ReadData = ReadData + read_size;
    }while(Size);

}


/**
  * @brief   描  述:寫指定數(shù)量數(shù)據(jù)到 SRAM數(shù)據(jù).
  * @param   參數(shù)1:uint32_t addr 開(kāi)始地址.
  * @param   參數(shù)2:uint32_t Size 數(shù)據(jù)量.
  * @param   參數(shù)3:uint8_t *WriteData 待寫入數(shù)據(jù)存儲(chǔ)地址.
  * @retval  回  復(fù):無(wú).
  * @author  作  者:YL
  * @date    日  期:2021.10.07
  * @version 版 本:V1.0
  * @warning 警 告:
  */

void Sram_LY64_Write(uint32_t addr,uint32_t Size,uint8_t *WriteData)
{
    uint8_t *test = WriteData-4;
    /* 連續(xù)寫入 */

#if SRAM_LY64_MODE_SPI
    uint8_t pData[5];
    rt_pin_write(SPI_SRAM_CS  , 0);
    rt_hw_us_delay(2);
    pData[0] = SRAM_LY64_CMD_WRITE;
    pData[1] = addr>>16;
    pData[2] = addr>>8;
    pData[3] = addr;
    pData[4] = *WriteData;

    HAL_SPI_Transmit(&hspi1, pData, 4, 2);        /* 發(fā)送寫命令 */
    HAL_SPI_Transmit(&hspi1, WriteData, Size, 2); /* 發(fā)送待寫入數(shù)據(jù) */
#endif

#if SRAM_LY64_MODE_SPI_DMA                                /* 把寫命令放入待發(fā)送數(shù)據(jù)中 */
    *(WriteData - 4) = SRAM_LY64_CMD_WRITE;               /* 這里是待寫入數(shù)據(jù)的首地址,在線程中定義了結(jié)構(gòu)體,這個(gè)地址前4個(gè)地址是預(yù)留存放寫命令用的 */
    *(WriteData - 3) = addr>>16;
    *(WriteData - 2) = addr>>8;
    *(WriteData - 1) = addr;

    while(hdma_spi1_rx.State != HAL_DMA_STATE_READY );    /* 等待DMA就緒 */
    while(hdma_spi1_tx.State != HAL_DMA_STATE_READY );    /* 等待DMA就緒 */
    rt_pin_write(SPI_SRAM_CS  , 0);
    HAL_SPI_Transmit_DMA(&hspi1, test, Size + 4);         /* 發(fā)送待寫入數(shù)據(jù) */
    while(hdma_spi1_tx.State != HAL_DMA_STATE_READY );    /* 等待DMA發(fā)送完成 */

#endif

    //rt_kprintf("SIZE = %d,addr = %08x, %02x , %02x , %02x , %02x , %02x \r\n",Size,addr,pData[0],pData[1],pData[2],pData[3],pData[4]);
    rt_pin_write(SPI_SRAM_CS  , 1);

}

/* LY68L6400 讀寫測(cè)試線程,可以測(cè)試讀取指定大小數(shù)據(jù)花費(fèi)時(shí)間、測(cè)試讀寫可靠性 */
void SARM_LY64_Test_entry(void *param)
{
    rt_pin_mode(SPI_SRAM_CS  , PIN_MODE_OUTPUT);
    rt_pin_mode(SPI_FLASH_CS  , PIN_MODE_OUTPUT); /* 測(cè)試板FLASH 與 SARM 共用SPI接口 */
    rt_pin_write(SPI_FLASH_CS  , 1);              /* 測(cè)試板FLASH 與 SARM 共用SPI接口,這里先把FLASH CS 拉高 */

    rt_thread_mdelay(3000);

    rt_uint8_t id[SRAM_LY64_ID_LEN] = {0};       /* SRAM id 存儲(chǔ) */
    uint32_t data_addr = 0;                      /* 待讀寫 SRAM 首地址 */

    struct spi_wdata                             /* 待寫入數(shù)據(jù)結(jié)構(gòu)體 */
    {
        uint8_t  cmd[4];         /* 寫數(shù)據(jù)命令 */
        uint8_t  data[WR_SIZE];  /* 待寫入SRAM的數(shù)據(jù) */
    } spi_wdata_1;

    uint8_t   *wdata = &spi_wdata_1.data[0]; /* 待寫入數(shù)據(jù)指針 */
    uint8_t   rdata[WR_SIZE] = {0};
    uint32_t  stime;                    /* 開(kāi)始時(shí)間 */
    uint32_t  etime;                    /* 結(jié)束時(shí)間 */
    uint16_t  crc_data_w;               /* 寫入數(shù)據(jù)CRC*/
    uint16_t  crc_data_r;               /* 讀出數(shù)據(jù)CRC*/
    uint32_t  read_crc_ok = 0;          /* 單次讀出數(shù)據(jù)CRC 成功次數(shù)*/
    uint32_t  read_crc_err = 0;         /* 單次讀出數(shù)據(jù)CRC 失敗次數(shù)*/
    uint32_t  read_crc_err_sum = 0;     /* 總讀出數(shù)據(jù)CRC 失敗次數(shù)*/

    uint16_t test_num = 1;              /* 測(cè)試次數(shù) */
    uint8_t i = 1;

    /* 待寫入數(shù)據(jù)初始化 */
    for (uint16_t var = 0; var < WR_SIZE; ++var)
    {
        if (i>100)
        {
           i = 1;
        }
        wdata[var] = i;
        ++i;
    }

    Sram_LY64_Reset(); /* 復(fù)位 SRAM */

    while(1)
    {
        rt_thread_mdelay(100);

        /* 讀取SRAM ID */
        Sram_LY64_Read_ID(SRAM_LY64_ID_LEN,id);
        rt_kprintf("Read ID is:%02x %02x %02x %02x %02x %02x %02x %02x \n", id[0],id[1],id[2],id[3], id[4], id[5],id[6],id[7]);

        /* SRAM寫入數(shù)據(jù) */
        data_addr = 0;
        crc_data_w = yl_crc16(wdata,WR_SIZE);  /* 校驗(yàn)待寫入數(shù)據(jù),以便與讀出數(shù)據(jù)做對(duì)比 */
        rt_kprintf("寫入數(shù)據(jù) CRC = %04x \r\n",crc_data_w);

        /* 往SRAM中寫滿數(shù)據(jù) */
        stime = rt_tick_get();  /* 獲取系統(tǒng)時(shí)間 */
        do
        {
            Sram_LY64_Write(data_addr,WR_SIZE,wdata);
            data_addr = data_addr +  WR_SIZE;

        } while (data_addr < SRAM_LY64_SIZE);
        etime = rt_tick_get();  /* 獲取系統(tǒng)時(shí)間 */
        rt_kprintf("寫  開(kāi)始 = %d 結(jié)束 = %d 耗時(shí) = %d\r\n",stime,etime,etime-stime); /* 計(jì)算寫入過(guò)程耗時(shí) */

        rt_thread_mdelay(10);

        /* 讀取SRAM全部數(shù)據(jù) */
        i = 5;  /* 循環(huán)讀取測(cè)試次數(shù) */
        while(i)
        {
            data_addr = 0;
            rt_kprintf("倒數(shù)第 %d 次讀取測(cè)試...\r\n",i);
            stime = rt_tick_get();
            do
            {
                Sram_LY64_Read(data_addr,WR_SIZE,rdata);
                data_addr = data_addr +  WR_SIZE;

#if READ_DATA_CRC
                /* CRC 校驗(yàn)讀取的數(shù)據(jù) */
                crc_data_r = yl_crc16(rdata,WR_SIZE);
                if (crc_data_r == crc_data_w)
                {
                    //rt_kprintf("讀第 %d 次, 校驗(yàn)成功:地址: adr = %08x , CRC寫 = %04x , CRC讀 = %04x\r\n",i,data_addr-WR_SIZE,crc_data_w,crc_data_r);
                    ++read_crc_ok;
                }
                else
                {
                    rt_kprintf("\r\n\r\n\r\n 起始地址: %08x , %d 校驗(yàn)失?。?CRC寫 = %04x , CRC讀 = %04x \r\n\r\n\r\n",data_addr-WR_SIZE,i,crc_data_w,crc_data_r);
                    ++read_crc_err;
                    ++read_crc_err_sum;
                }
#endif
                /* 打印讀取的SRAM數(shù)據(jù) */
#if READ_DATA_PRINTF
                rt_kprintf(" 讀開(kāi)始地址: adr = %08x \r\n",data_addr-WR_SIZE);
                if (crc_data_r != crc_data_w)
                {
                    for (uint16_t var = 0; var < WR_SIZE; ++var)
                    {
                        rt_kprintf("讀SRAM var= %d Data:%d %d %d %d %d %d %d %d %d %d\n",var, rdata[var+0],rdata[var+1],rdata[var+2],rdata[var+3], rdata[var+4], rdata[var+5],rdata[var+6],rdata[var+7],rdata[var+8], rdata[var+9]);
                        var = var + 9;
                    }
                }

#endif

            } while (data_addr < SRAM_LY64_SIZE);
            etime = rt_tick_get();

            rt_kprintf("讀取大小 = %d 字節(jié), 時(shí)間統(tǒng)計(jì):開(kāi)始 = %d 結(jié)束 = %d 耗時(shí) = %d\r\n",SRAM_LY64_SIZE,stime,etime,etime-stime);

            rt_memset(rdata, 0, WR_SIZE);  /* 把讀數(shù)據(jù)緩存清零 */
            --i;
        }
        rt_kprintf("第 %d 次測(cè)試:寫1次,連讀 5 次 ;單次全部讀取,每次讀1K字節(jié):校驗(yàn)成功次數(shù) = %d ,校驗(yàn)失敗次數(shù) = %d ;累計(jì)校驗(yàn)失敗次數(shù) = %d\r\n",test_num,read_crc_ok,read_crc_err,read_crc_err_sum);
        ++test_num;
        read_crc_err = 0;
        read_crc_ok = 0;
        rt_thread_mdelay(1000);
    }

}


/*線程創(chuàng)建函數(shù)*/
int SARM_LY64_Test(void)
{
    rt_thread_t tid1;                                          /*創(chuàng)建線程控制塊指針來(lái)接收線程創(chuàng)建函數(shù)的返回值,目的是通過(guò)返回值判斷線程是否創(chuàng)建ok*/

    /* 創(chuàng)建線程 1,名稱是 SARM_LY64_Test,入口是 SARM_LY64_Test_entry*/

    tid1 = rt_thread_create("SARM_LY64_Test",         /*線程名稱,系統(tǒng)打印線程時(shí)會(huì)顯示這個(gè)線程的名字*/
                            SARM_LY64_Test_entry,     /*線程入口函數(shù),入口函數(shù)函數(shù)名*/
                            RT_NULL,                  /*入口參數(shù)*/
                            2000 + WR_SIZE*2,         /*設(shè)置內(nèi)存堆棧大小*/
                            9,                        /*設(shè)置優(yōu)先級(jí)*/
                            200);                     /*時(shí)間片參數(shù),時(shí)間片是在有多個(gè)相同優(yōu)先級(jí)線程時(shí),這個(gè)線程每次被執(zhí)行多少個(gè)時(shí)間片*/


    /* 如果獲得線程控制塊,啟動(dòng)這個(gè)線程 */
    if (tid1 != RT_NULL)
        rt_thread_startup(tid1);

    return RT_EOK;
}
INIT_APP_EXPORT(SARM_LY64_Test);

6.測(cè)試信息輸出

spi sram,STM32,stm32,單片機(jī),嵌入式硬件

?

7:參考資源鏈接

優(yōu)質(zhì)參考資料:STM32 SPI通信協(xié)議詳細(xì)講解—小白入門_阿喬不想編程的博客-CSDN博客

其他參考:

https://blog.csdn.net/weixin_41294615/article/details/103233374?depth_1-

https://yngzmiao.blog.csdn.net/article/details/80318821

https://www.freesion.com/article/65571428542/

https://my.oschina.net/u/4386235/blog/3937830

https://blog.csdn.net/qq_54747686/article/details/119221405?spm=1001.2014.3001.5501

https://www.cnblogs.com/xuhaojieixbwer/p/14270116.html

https://www.cnblogs.com/xingboy/p/9555708.html

https://xfxuezhang.blog.csdn.net/article/details/108716706

https://blog.csdn.net/as480133937/article/details/104827639/?spm=1001.2101.3001.4242

https://blog.csdn.net/as480133937/article/details/105849607

https://blog.csdn.net/as480133937/article/details/104827639文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-651001.html

到了這里,關(guān)于STM32 SPI+DMA 驅(qū)動(dòng) SRAM LY68L6400SLIT 應(yīng)用筆記的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • STM32 硬件SPI+DMA實(shí)現(xiàn)快速刷TFT屏

    STM32 硬件SPI+DMA實(shí)現(xiàn)快速刷TFT屏

    首先在TB上找一塊SPI驅(qū)動(dòng)的彩屏,下載商家提供的示例 例如我買的一款2.8寸SPI的TFT彩屏,商家提供的資料很齊全,模擬SPI和硬件SPI驅(qū)動(dòng)的程序都有 打開(kāi)硬件SPI驅(qū)動(dòng)的工程,商家提供的代碼是SPI2驅(qū)動(dòng),想換成其他的SPI可以到SPI.c文件中更改 打開(kāi)main.c,測(cè)試一下簡(jiǎn)單顏色填充刷

    2024年04月15日
    瀏覽(114)
  • U8g2庫(kù)的STM32硬件SPI(DMA)移植教程(HAL、OLED顯示、四線SPI、DMA)

    U8g2庫(kù)的STM32硬件SPI(DMA)移植教程(HAL、OLED顯示、四線SPI、DMA)

    本文教你把U8g2圖形庫(kù)移植到STM32上,基于STM32的硬件SPI、CubeMX U8g2庫(kù)Github網(wǎng)址:https://github.com/olikraus/u8g2 U8g2庫(kù)CSDN鏡像網(wǎng)址:https://gitcode.net/mirrors/olikraus/u8g2?utm_source=csdn_github_accelerator 硬件準(zhǔn)備:STM32C8T6(STM32系列芯片)、0.96寸OLED(128×64)、J-Link(或其他) 引腳連接: 出自此

    2024年02月09日
    瀏覽(35)
  • STM32CubeMX教程23 FSMC - IS62WV51216(SRAM)驅(qū)動(dòng)

    開(kāi)發(fā)板(正點(diǎn)原子stm32f407探索者開(kāi)發(fā)板V2.4) STM32CubeMX軟件(Version 6.10.0) 野火DAP仿真器 keil μVision5 IDE(MDK-Arm) ST-LINK/V2驅(qū)動(dòng) XCOM V2.6串口助手 使用STM32CubeMX軟件配置STM32F407開(kāi)發(fā)板的 FSMC實(shí)現(xiàn)以輪詢或DMA的方式讀寫IS62WV51216(SRAM)芯片 關(guān)于FSMC的內(nèi)容讀者可閱讀“STM32CubeMX教程

    2024年01月24日
    瀏覽(18)
  • stm32HAL庫(kù) G4 SPI 從機(jī)DMA可變長(zhǎng)度接受數(shù)據(jù)亂碼問(wèn)題

    stm32HAL庫(kù) G4 SPI 從機(jī)DMA可變長(zhǎng)度接受數(shù)據(jù)亂碼問(wèn)題

    使用一個(gè)引腳當(dāng)作SPI CS, 邊沿觸發(fā); 在電平位0時(shí)候接受SPI數(shù)據(jù)20個(gè)字節(jié) 如果實(shí)際主機(jī)只發(fā)了小于20字節(jié)時(shí)候, 下一個(gè)幀就會(huì)錯(cuò)亂; 去老外找了之后,需要復(fù)位SPi RCC時(shí)鐘才能復(fù)位掉SPI 下面的不行 正確的做法

    2024年02月10日
    瀏覽(16)
  • STM32CubeMX配置HAL庫(kù)實(shí)現(xiàn)SPI-DMA的遞歸調(diào)用

    STM32CubeMX配置HAL庫(kù)實(shí)現(xiàn)SPI-DMA的遞歸調(diào)用

    核心: STM32F407ZET6?? 外設(shè)ADC: ADS1258? ?數(shù)量:3個(gè)? ?※ 核心與3個(gè)ADC使用SPI總線 “一主多從” 方式連接,PCB布線的方式與下圖一致。 ※ 在電路板上STM32與三個(gè)ADS1258在同一直線上分布,STM32在一端,三個(gè)ADC依次排布。 ※ 離STM32最遠(yuǎn)ADC的DRDY硬件管腳與STM32的EXTI line4 interrupt連接

    2024年02月15日
    瀏覽(39)
  • 【STM32】HAL庫(kù)中的SPI傳輸(可利用中斷或DMA進(jìn)行連續(xù)傳輸)

    【STM32】HAL庫(kù)中的SPI傳輸(可利用中斷或DMA進(jìn)行連續(xù)傳輸)

    【STM32】HAL庫(kù)中的SPI傳輸(可利用中斷或DMA進(jìn)行連續(xù)傳輸) SPI 是英語(yǔ)Serial Peripheral interface的縮寫,顧名思義就是串行外圍設(shè)備接口。是Motorola(摩托羅拉)首先在其MC68HCXX系列處理器上定義的。 SPI,是一種高速的,全雙工,同步的通信總線,并且在芯片的管腳上只占用四根線,

    2024年02月08日
    瀏覽(23)
  • DMA技術(shù)在STM32中優(yōu)化UART、SPI和I2C通信性能的研究與實(shí)現(xiàn)

    DMA技術(shù)在STM32中優(yōu)化UART、SPI和I2C通信性能的研究與實(shí)現(xiàn)

    DMA(Direct Memory Access,直接存儲(chǔ)器訪問(wèn))技術(shù)可以在STM32微控制器上優(yōu)化UART、SPI和I2C等通信性能。 DMA可以實(shí)現(xiàn)數(shù)據(jù)的高速傳輸,減輕CPU的負(fù)擔(dān),提高系統(tǒng)性能。在本篇文章中,我將探討DMA技術(shù)在STM32中優(yōu)化這些通信協(xié)議的研究和實(shí)現(xiàn)。 一、DMA工作原理 DMA可以實(shí)現(xiàn)外設(shè)與存儲(chǔ)器

    2024年01月20日
    瀏覽(27)
  • 【STM32】BLDC驅(qū)動(dòng)&控制開(kāi)發(fā)筆記 | 07_SPI通信測(cè)試 - STM32F407用SPI配置DRV8323驅(qū)動(dòng)芯片

    【STM32】BLDC驅(qū)動(dòng)&控制開(kāi)發(fā)筆記 | 07_SPI通信測(cè)試 - STM32F407用SPI配置DRV8323驅(qū)動(dòng)芯片

    最近在埋頭搞STM32 + 無(wú)刷直流電機(jī)控制,想實(shí)現(xiàn)用自己的STM32F407VGT6芯片板子,外加一塊驅(qū)動(dòng)板(目前選用到TI的DRV8302或者DRV8323驅(qū)動(dòng)芯片),搞定電機(jī)驅(qū)動(dòng),最后實(shí)現(xiàn)比較好的控制效果。如果不是同一塊芯片的同學(xué)也不用急著走,大體上都是可借鑒噠~ 本文主要實(shí)現(xiàn)使用SPI通信

    2024年02月08日
    瀏覽(35)
  • STM32+PWM+DMA驅(qū)動(dòng)WS2812彩燈模塊(附源碼)

    STM32+PWM+DMA驅(qū)動(dòng)WS2812彩燈模塊(附源碼)

    WS2812是一顆數(shù)字LED燈珠,采用單總線通訊,每顆燈珠支持24bit的顏色控制,也即RGB888,信號(hào)線通過(guò)DIN輸入,經(jīng)過(guò)一顆燈珠之后,信號(hào)線上前24bit數(shù)據(jù)會(huì)被該燈珠鎖存,之后將剩下的數(shù)據(jù)信號(hào)整形之后通過(guò)DOUT輸出 C1為VDD的濾波電容,一般大小為100NF。 WS2812.c pwm.c DMA.c main.c 需要源

    2024年02月15日
    瀏覽(23)
  • 0.96OLED STM32 SPI驅(qū)動(dòng)(一)

    0.96OLED STM32 SPI驅(qū)動(dòng)(一)

    閑來(lái)無(wú)聊,翻出了一個(gè)OLED,本來(lái)想串流做個(gè)小顯示器用,感覺(jué)難度太大。將就變成了下面這 個(gè)樣子,姑且叫火柴人大亂斗之OLED。 火柴人之OLED 分兩步走,先驅(qū)動(dòng)OLED能顯示一副圖片,本篇講述此內(nèi)容。 第二步顯示動(dòng)畫,放在下一篇中講。 查資料得到此OLED為SPI通信,SCL對(duì)應(yīng)連

    2024年02月06日
    瀏覽(26)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包