目录

  • 高速 SPI 设备控制器
  • 库函数
    • 函数
    • 参数
    • 应用示例
      • 初始化
      • 引脚复用
      • 中断相关
      • 使用
  • 注意事项
    • DataAlignment
    • Direction
  • 测试
    • main.c
    • wm_hal_msp.c
    • wm_it.c
    • 其他改动
    • 实验现象

Windows 10 20H2
HLK-W806-V1.0-KIT
WM_SDK_W806_v0.6.0


摘自《W806 芯片设计指导书 V1.0》、《W806 MCU 芯片规格书 V2.0》、《WM_W800_寄存器手册 V2.1》

高速 SPI 设备控制器

兼容通用 SPI 物理层协议,通过约定与主机交互的数据格式,主机对设备的高速访问,最高支持工作频率为50Mbps。

兼容通用 SPI 协议
可选择的电平中断信号
最高支持 50Mbps 速率
简单的帧格式,全硬件解析与 DMA








库函数

函数

HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi);
//初始化SPI的工作模式和速率等HAL_StatusTypeDef HAL_SPI_DeInit(SPI_HandleTypeDef *hspi);
//将初始化之后的SPI接口恢复成默认的状态–各个寄存器复位时的值void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi);
//用于启用SPI时钟,引脚复用,配置DMA及中断优先级等void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi);
//用于禁用SPI时钟,将对应引脚恢复成默认的状态HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint32_t Size, uint32_t Timeout);
//SPI发送数据,使用超时管理机制
HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint32_t Size, uint32_t Timeout);
//SPI接收数据,使用超时管理机制
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint32_t Size,uint32_t Timeout);
//SPI收发数据,使用超时管理机制 HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint32_t Size);
//SPI中断模式发送
HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint32_t Size);
//SPI中断模式接收
HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData,uint32_t Size);
//SPI中断模式收发HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint32_t Size);
//SPI DMA模式发送
HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint32_t Size);
//SPI DMA模式接收
HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData,uint32_t Size);
//SPI DMA模式收发HAL_StatusTypeDef HAL_SPI_DMAPause(SPI_HandleTypeDef *hspi);
//SPI DMA传输暂停
HAL_StatusTypeDef HAL_SPI_DMAResume(SPI_HandleTypeDef *hspi);
//SPI DMA传输恢复
HAL_StatusTypeDef HAL_SPI_DMAStop(SPI_HandleTypeDef *hspi);
//SPI DMA传输停止void HAL_SPI_IRQHandler(SPI_HandleTypeDef *hspi);
//SPI 中断服务函数
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi);
//SPI 发送完毕回调函数
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi);
//SPI 接收完毕回调函数
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi);
//SPI 收发完毕回调函数
void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi);
void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi);
void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef *hspi);
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi);HAL_SPI_StateTypeDef HAL_SPI_GetState(SPI_HandleTypeDef *hspi);
//获取SPI传输状态
uint32_t             HAL_SPI_GetError(SPI_HandleTypeDef *hspi);

参数

结构体和枚举类型

typedef struct
{uint32_t Mode;                /*!< Specifies the SPI operating mode.This parameter can be a value of @ref SPI_Mode */uint32_t CLKPolarity;         /*!< Specifies the serial clock steady state.This parameter can be a value of @ref SPI_Clock_Polarity */uint32_t CLKPhase;            /*!< Specifies the clock active edge for the bit capture.This parameter can be a value of @ref SPI_Clock_Phase */uint32_t NSS;                 /*!< Specifies whether the NSS signal is managed byhardware (NSS pin) or by software using the SSI bit.This parameter can be a value of @ref SPI_Slave_Select_management */uint32_t BaudRatePrescaler;   /*!< Specifies the Baud Rate prescaler value which will beused to configure the transmit and receive SCK clock.This parameter can be a value of @ref SPI_BaudRate_Prescaler@note The communication clock is derived from the masterclock. The slave clock does not need to be set. */uint32_t FirstByte;           /* Specifies whether data transfers start from high byte or low byte.This parameter can be a value of @ref SPI_HBYTE_LBYTE_transmission */} SPI_InitTypeDef;typedef enum
{HAL_SPI_STATE_RESET      = 0x00U,    /*!< Peripheral not Initialized                         */HAL_SPI_STATE_READY      = 0x01U,    /*!< Peripheral Initialized and ready for use           */HAL_SPI_STATE_BUSY       = 0x02U,    /*!< an internal process is ongoing                     */HAL_SPI_STATE_BUSY_TX    = 0x03U,    /*!< Data Transmission process is ongoing               */HAL_SPI_STATE_BUSY_RX    = 0x04U,    /*!< Data Reception process is ongoing                  */HAL_SPI_STATE_BUSY_TX_RX = 0x05U,    /*!< Data Transmission and Reception process is ongoing */HAL_SPI_STATE_ERROR      = 0x06U,    /*!< SPI error state                                    */HAL_SPI_STATE_ABORT      = 0x07U     /*!< SPI abort is ongoing                               */
} HAL_SPI_StateTypeDef;typedef struct __SPI_HandleTypeDef
{SPI_TypeDef                *Instance;      /*!< SPI registers base address               */SPI_InitTypeDef            Init;           /*!< SPI communication parameters             */uint8_t                    *pTxBuffPtr;    /*!< Pointer to SPI Tx transfer Buffer        */uint32_t                   TxXferSize;     /*!< SPI Tx Transfer size                     */__IO uint32_t              TxXferCount;    /*!< SPI Tx Transfer Counter                  */uint8_t                    *pRxBuffPtr;    /*!< Pointer to SPI Rx transfer Buffer        */uint32_t                   RxXferSize;     /*!< SPI Rx Transfer size                     */__IO uint32_t              RxXferCount;    /*!< SPI Rx Transfer Counter                  */DMA_HandleTypeDef         *hdmatx;        /*!< SPI Tx DMA Handle parameters          */DMA_HandleTypeDef           *hdmarx;        /*!< SPI Rx DMA Handle parameters          */HAL_LockTypeDef            Lock;           /*!< Locking object                           */__IO HAL_SPI_StateTypeDef  State;          /*!< SPI communication state                  */__IO uint32_t              ErrorCode;      /*!< SPI Error code                           */} SPI_HandleTypeDef;

宏参数

#define SPI                ((SPI_TypeDef *)SPI_BASE)#define HAL_SPI_ERROR_NONE              (0x00000000U)   /*!< No error                               */
#define HAL_SPI_ERROR_TXERR             (0x00000001U)   /*!< Tx error                               */
#define HAL_SPI_ERROR_RXERR             (0x00000002U)   /*!< Rx error                               */
#define HAL_SPI_ERROR_DMA               (0x00000010U)   /*!< DMA transfer error                     */// SPI_Mode
#define SPI_MODE_SLAVE                  (0x00000000U)
#define SPI_MODE_MASTER                 (SPI_SPI_CFG_MASTER)// SPI_Clock_Polarity
#define SPI_POLARITY_LOW                (0x00000000U)
#define SPI_POLARITY_HIGH               SPI_SPI_CFG_CPOL// SPI_Clock_Phase
#define SPI_PHASE_1EDGE                 (0x00000000U)
#define SPI_PHASE_2EDGE                 SPI_SPI_CFG_CPHA// SPI_Slave_Select_management
#define SPI_NSS_HARD                    (0x00000000U)
#define SPI_NSS_SOFT                    SPI_CH_CFG_CSSEL// SPI_HBYTE_LBYTE_transmission
#define SPI_LITTLEENDIAN                (0x00000000U)
#define SPI_BIGENDIAN                   SPI_SPI_CFG_BIGENDIAN// fclk = 40MHz / (2 * (div + 1))
#define SPI_BAUDRATEPRESCALER_2         (0x00000000U)   // 40M / 2 = 20M
#define SPI_BAUDRATEPRESCALER_4         (0x00000001U)   // 40M / 4 = 10M
#define SPI_BAUDRATEPRESCALER_8         (0x00000003U)   // 40M / 8 = 5M
#define SPI_BAUDRATEPRESCALER_10        (0x00000004U)   // 40M / 10 = 4M
#define SPI_BAUDRATEPRESCALER_20        (0x00000009U)   // 40M / 20 = 2M
#define SPI_BAUDRATEPRESCALER_40        (0x00000013U)   // 40M / 40 = 1M#define BLOCK_SIZE (8 * 1024 - 8)

#define IS_SPI_ALL_INSTANCE(INSTANCE) ((INSTANCE) == SPI1)#define IS_SPI_MODE(__MODE__)      ((__MODE__) == SPI_MODE_MASTER)#define IS_SPI_NSS(__NSS__)        (((__NSS__) == SPI_NSS_SOFT)       || \((__NSS__) == SPI_NSS_HARD_INPUT) || \((__NSS__) == SPI_NSS_HARD_OUTPUT))#define IS_SPI_BIG_OR_LITTLE(__ENDIAN__)       (((__ENDIAN__) == SPI_LITTLEENDIAN) || \((__ENDIAN__) == SPI_BIGENDIAN))#define IS_SPI_DMA_HANDLE(__HANDLE__)    ((__HANDLE__) != NULL)#define __HAL_SPI_ENABLE_TX(__HANDLE__)  SET_BIT((__HANDLE__)->Instance->CH_CFG, SPI_CH_CFG_TXON)#define __HAL_SPI_DISABLE_TX(__HANDLE__)  CLEAR_BIT((__HANDLE__)->Instance->CH_CFG, SPI_CH_CFG_TXON)#define __HAL_SPI_ENABLE_RX(__HANDLE__)  SET_BIT((__HANDLE__)->Instance->CH_CFG, SPI_CH_CFG_RXON)#define __HAL_SPI_DISABLE_RX(__HANDLE__)  CLEAR_BIT((__HANDLE__)->Instance->CH_CFG, SPI_CH_CFG_RXON)#define __HAL_SPI_ENABLE_TXRX(__HANDLE__)  SET_BIT((__HANDLE__)->Instance->CH_CFG, (SPI_CH_CFG_RXON | SPI_CH_CFG_TXON))#define __HAL_SPI_DISABLE_TXRX(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->CH_CFG, (SPI_CH_CFG_RXON | SPI_CH_CFG_TXON))#define __HAL_SPI_CLEAR_FIFO(__HANDLE__) do{SET_BIT((__HANDLE__)->Instance->CH_CFG, SPI_CH_CFG_CLEARFIFOS);\while(READ_BIT((__HANDLE__)->Instance->CH_CFG, SPI_CH_CFG_CLEARFIFOS));}while(0U);#define __HAL_SPI_GET_TXFIFO(__HANDLE__) (((__HANDLE__)->Instance->STATUS) & SPI_STATUS_TXFIFO)#define __HAL_SPI_GET_RXFIFO(__HANDLE__) ((((__HANDLE__)->Instance->STATUS) & SPI_STATUS_RXFIFO) >> SPI_STATUS_RXFIFO_Pos)#define __HAL_SPI_SET_CLK_NUM(__HANDLE__, NUM)    (MODIFY_REG((__HANDLE__)->Instance->CH_CFG, SPI_CH_CFG_LEN, NUM << SPI_CH_CFG_LEN_Pos))#define __HAL_SPI_SET_START(__HANDLE__) SET_BIT((__HANDLE__)->Instance->CH_CFG, SPI_CH_CFG_START)#define __HAL_SPI_GET_BUSY_STATUS(__HANDLE__) (READ_BIT((__HANDLE__)->Instance->STATUS, SPI_STATUS_BUSY))#define __HAL_SPI_SET_CS_LOW(__HANDLE__)   CLEAR_BIT((__HANDLE__)->Instance->CH_CFG, SPI_CH_CFG_CSLEVEL)#define __HAL_SPI_SET_CS_HIGH(__HANDLE__)    SET_BIT((__HANDLE__)->Instance->CH_CFG, SPI_CH_CFG_CSLEVEL)#define __HAL_SPI_GET_FLAG(__HANDLE__, FLAG)   READ_BIT((__HANDLE__)->Instance->INT_SRC, FLAG)#define __HAL_SPI_CLEAR_FLAG(__HANDLE__, FLAG) SET_BIT((__HANDLE__)->Instance->INT_SRC, FLAG)#define __HAL_SPI_ENABLE_IT(__HANDLE__, IT)     CLEAR_BIT((__HANDLE__)->Instance->INT_MASK, IT)#define __HAL_SPI_DISABLE_IT(__HANDLE__, IT)   SET_BIT((__HANDLE__)->Instance->INT_MASK, IT)

应用示例

摘自spi例程

初始化

在main.c中

SPI_HandleTypeDef hspi;
DMA_HandleTypeDef hdma_spi_tx;
DMA_HandleTypeDef hdma_spi_rx;static void SPI_Init(void);
static void DMA_Init(void);static void SPI_Init(void)
{hspi.Instance = SPI;hspi.Init.Mode = SPI_MODE_MASTER;                        //工作模式hspi.Init.CLKPolarity = SPI_POLARITY_LOW;                //控制空闲时的时钟电平hspi.Init.CLKPhase = SPI_PHASE_1EDGE;                  //控制采样相位hspi.Init.NSS = SPI_NSS_SOFT;                          //片选引脚的控制方式hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_20; //分频系数 其中SPI时钟为40MHzhspi.Init.FirstByte = SPI_LITTLEENDIAN;                    //控制数据 MSB或LSBif (HAL_SPI_Init(&hspi) != HAL_OK){Error_Handler();}
}static void DMA_Init(void)
{__HAL_RCC_DMA_CLK_ENABLE();HAL_NVIC_SetPriority(DMA_Channel0_IRQn, 0);HAL_NVIC_EnableIRQ(DMA_Channel0_IRQn);HAL_NVIC_SetPriority(DMA_Channel1_IRQn, 0);HAL_NVIC_EnableIRQ(DMA_Channel1_IRQn);
}

引脚复用

在wm_hal_msp.c中

extern DMA_HandleTypeDef hdma_spi_tx;
extern DMA_HandleTypeDef hdma_spi_rx;void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{__HAL_RCC_SPI_CLK_ENABLE();                        //启用SPI时钟__HAL_AFIO_REMAP_SPI_CS(GPIOB, GPIO_PIN_4);        //SPI引脚复用__HAL_AFIO_REMAP_SPI_CLK(GPIOB, GPIO_PIN_2);__HAL_AFIO_REMAP_SPI_MISO(GPIOB, GPIO_PIN_3);__HAL_AFIO_REMAP_SPI_MOSI(GPIOB, GPIO_PIN_5); hdma_spi_tx.Instance = DMA_Channel0;                           //使用的DMA通道hdma_spi_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;               //DMA传输方向 这里疑似有问题,见后文hdma_spi_tx.Init.DestInc = DMA_DINC_DISABLE;                   //目标地址是否自增hdma_spi_tx.Init.SrcInc = DMA_SINC_ENABLE;                       //数据地址是否自增hdma_spi_tx.Init.DataAlignment = DMA_DATAALIGN_WORD;         //数据对齐方式 这里疑似有问题,见后文hdma_spi_tx.Init.Mode = DMA_MODE_NORMAL_SINGLE;                 //DMA工作模式hdma_spi_tx.Init.RequestSourceSel = DMA_REQUEST_SOURCE_SPI_TX;    //DMA请求源__HAL_LINKDMA(hspi, hdmatx, hdma_spi_tx);if (HAL_DMA_Init(&hdma_spi_tx) != HAL_OK){Error_Handler();}hdma_spi_rx.Instance = DMA_Channel1;hdma_spi_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;hdma_spi_rx.Init.DestInc = DMA_DINC_ENABLE;hdma_spi_rx.Init.SrcInc = DMA_SINC_DISABLE;hdma_spi_rx.Init.DataAlignment = DMA_DATAALIGN_WORD;hdma_spi_rx.Init.Mode = DMA_MODE_NORMAL_SINGLE;hdma_spi_rx.Init.RequestSourceSel = DMA_REQUEST_SOURCE_SPI_RX;__HAL_LINKDMA(hspi, hdmarx, hdma_spi_rx);if (HAL_DMA_Init(&hdma_spi_rx) != HAL_OK){Error_Handler();}HAL_NVIC_SetPriority(SPI_LS_IRQn, 1);HAL_NVIC_EnableIRQ(SPI_LS_IRQn);
}void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi)
{__HAL_RCC_SPI_CLK_DISABLE();HAL_GPIO_DeInit(GPIOB, GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5);
}

中断相关

在wm_it.c中

extern SPI_HandleTypeDef hspi;
extern DMA_HandleTypeDef hdma_spi_tx;
extern DMA_HandleTypeDef hdma_spi_rx;__attribute__((isr)) void SPI_LS_IRQHandler(void)
{HAL_SPI_IRQHandler(&hspi);
}__attribute__((isr)) void DMA_Channel0_IRQHandler(void)
{HAL_DMA_IRQHandler(&hdma_spi_tx);
}__attribute__((isr)) void DMA_Channel1_IRQHandler(void)
{HAL_DMA_IRQHandler(&hdma_spi_rx);
}

使用

 DMA_Init();SPI_Init();__HAL_SPI_SET_CS_LOW(&hspi);HAL_SPI_Transmit_DMA(&hspi, 数据首地址, 数据长度);__HAL_SPI_SET_CS_LOW(&hspi);HAL_SPI_Receive_DMA(&hspi, 缓冲区首地址, 数据长度);

注意事项

DataAlignment

在WM_SDK_W806_v0.6.0中,DMA的数据对齐方式DataAlignment和STM32的效果完全相反,不知道是否是有意为之:
       所传数据为

当hdma_spi_tx.Init.DataAlignment = DMA_DATAALIGN_WORD时

波形正确

使用硬件I2C+DMA驱动相同的屏幕,在STM32中则为

若改为hdma_spi_tx.Init.DataAlignment = DMA_DATAALIGN_BYTE;

则波形错误

Direction

在WM_SDK_W806_v0.6.0中,外设到内存的宏和内存到外设的宏是一样的,有点奇怪

在STM32中则是不一样的:

测试

这里的测试程序见【0.96寸 OLED屏实现1500Fps的帧率】STM32 软件、硬件SPI、I2C驱动总结

main.c

#include <stdio.h>
#include "wm_hal.h"
#include "oled.h"SPI_HandleTypeDef hspi;
DMA_HandleTypeDef hdma_spi_tx;void Error_Handler(void);
static void SPI_Init(void);
static void GPIO_Init(void);
static void DMA_Init(void);uint16_t FPS = 0, FPS_Count = 0;int main(void)
{SystemClock_Config(CPU_CLK_240M);GPIO_Init();DMA_Init();SPI_Init();printf("enter main\r\n");uint8_t i;OLED_Init();OLED_Clear();OLED_Display_On();         OLED_ShowString(0, 0, "   W806  OLED", 16, 0);OLED_ShowString(0, 2, "   2022-01-25", 6, 0);for(i = 0; i < 7; ++i)OLED_ShowChinese(8 + 16 * i, 6, i, 1);OLED_Refresh_Gram();while (1){++FPS_Count;OLED_ShowString(0, 4, "FPS: ", 16, 0); OLED_ShowNum(32, 4, FPS, 7, 16, 0);OLED_Refresh_Gram();}
}static void SPI_Init(void)
{hspi.Instance = SPI;hspi.Init.Mode = SPI_MODE_MASTER;hspi.Init.CLKPolarity = SPI_POLARITY_HIGH;hspi.Init.CLKPhase = SPI_PHASE_2EDGE;hspi.Init.NSS = SPI_NSS_SOFT;hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;hspi.Init.FirstByte = SPI_LITTLEENDIAN;if (HAL_SPI_Init(&hspi) != HAL_OK){Error_Handler();}
}static void GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};__HAL_RCC_GPIO_CLK_ENABLE();GPIO_InitStruct.Pin = SSD1306_RES_PIN;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(SSD1306_RES_PORT, &GPIO_InitStruct);GPIO_InitStruct.Pin = SSD1306_DC_PIN;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT;GPIO_InitStruct.Pull = GPIO_NOPULL;HAL_GPIO_Init(SSD1306_DC_PORT, &GPIO_InitStruct);
}static void DMA_Init(void)
{__HAL_RCC_DMA_CLK_ENABLE();HAL_NVIC_SetPriority(DMA_Channel0_IRQn, 0);HAL_NVIC_EnableIRQ(DMA_Channel0_IRQn);
}void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{}void Error_Handler(void)
{while (1){}
}void assert_failed(uint8_t *file, uint32_t line)
{printf("Wrong parameters value: file %s on line %d\r\n", file, line);
}

wm_hal_msp.c

#include "wm_hal.h"
#include "oled.h"extern DMA_HandleTypeDef hdma_spi_tx;void Error_Handler(void);void HAL_MspInit(void)
{}void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{__HAL_RCC_SPI_CLK_ENABLE();__HAL_AFIO_REMAP_SPI_CS(SSD1306_CS_PORT, SSD1306_CS_PIN);__HAL_AFIO_REMAP_SPI_CLK(SSD1306_SCK_PORT, SSD1306_SCK_PIN);__HAL_AFIO_REMAP_SPI_MOSI(SSD1306_MOSI_PORT, SSD1306_MOSI_PIN);hdma_spi_tx.Instance = DMA_Channel0;hdma_spi_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;hdma_spi_tx.Init.DestInc = DMA_DINC_DISABLE;hdma_spi_tx.Init.SrcInc = DMA_SINC_ENABLE;//  hdma_spi_tx.Init.DataAlignment = DMA_DATAALIGN_BYTE;hdma_spi_tx.Init.DataAlignment = DMA_DATAALIGN_WORD;hdma_spi_tx.Init.Mode = DMA_MODE_NORMAL_SINGLE;hdma_spi_tx.Init.RequestSourceSel = DMA_REQUEST_SOURCE_SPI_TX;__HAL_LINKDMA(hspi, hdmatx, hdma_spi_tx);if (HAL_DMA_Init(&hdma_spi_tx) != HAL_OK){Error_Handler();}HAL_NVIC_SetPriority(SPI_LS_IRQn, 1);HAL_NVIC_EnableIRQ(SPI_LS_IRQn);
}void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi)
{__HAL_RCC_SPI_CLK_DISABLE();HAL_GPIO_DeInit(SSD1306_CS_PORT, SSD1306_CS_PIN);HAL_GPIO_DeInit(SSD1306_SCK_PORT, SSD1306_SCK_PIN);HAL_GPIO_DeInit(SSD1306_MOSI_PORT, SSD1306_MOSI_PIN);
}

wm_it.c


#include "wm_hal.h"extern uint16_t FPS, FPS_Count;extern SPI_HandleTypeDef hspi;
extern DMA_HandleTypeDef hdma_spi_tx;#define readl(addr) ({unsigned int __v = (*(volatile unsigned int *) (addr)); __v;})
__attribute__((isr)) void CORET_IRQHandler(void)
{static uint16_t ms_Count = 0;readl(0xE000E010);HAL_IncTick();if(++ms_Count >= 1000){ms_Count = 0;FPS = FPS_Count;FPS_Count = 0;}
}__attribute__((isr)) void SPI_LS_IRQHandler(void)
{HAL_SPI_IRQHandler(&hspi);
}__attribute__((isr)) void DMA_Channel0_IRQHandler(void)
{HAL_DMA_IRQHandler(&hdma_spi_tx);
}

其他改动

实验现象


【联盛德W806上手笔记】八、SPI及其DMA相关推荐

  1. 【联盛德W806上手笔记】七、I2C

    目录 WM_SDK_W806_v0.6.0的库函数 函数 参数 宏 应用示例 初始化 使用 测试 I2C 控制器 功能概述 主要特性 功能描述 传输速率选择 中断及启动停止可控 快速输出及检测信号 寄 ...

  2. 【联盛德W806上手笔记】一、开发环境和烧录程序

    目录 简介 芯片外观 MCU 特性 安全特性 低功耗模式 芯片结构 管脚定义 极限参数 开发环境 SDK的获取 从官网获取 从Q群获取 iosetting大佬 维护的wm-sdk-w806 打开工程 ...

  3. 【联盛德W806上手笔记】三、MCU系统与时钟结构

    目录 总线结构 AHB-1 总线 AHB-2 总线 时钟与复位 主要特性 时钟结构 功能描述 时钟门控 时钟自适应关断 功能复位 时钟分频 寄存器描述 寄存器列表 软件时钟门控使能寄存器 软件时钟掩码 ...

  4. 【联盛德W806上手笔记】五、TIM定时器

    目录 定时器 库函数 函数 参数 宏 Demo中的测试程序 main.c wm_hal_msp.c wm_it.c 实验现象 Windows 10 20H2 HLK-W806-V1.0-KIT WM_ ...

  5. 【联盛德W806上手笔记】二、GPIO

    目录 GPIO 控制器 库函数 函数 参数 宏 极限翻转速度 寄存器操作 库函数操作 测试 main.c wm_it.c Windows 10 20H2 HLK-W806-V1.0-KIT WM_SD ...

  6. 联盛德W806最小系统开发板第一次上手准备工作

    W806 芯片 是一款安全 IoT MCU 芯片.芯片集成 32 位 CPU 处理器,内置 UART.GPIO.SPI.SDIO.I2C.I2S.PSRAM.7816.ADC.LCD.TouchSen ...

  7. 联盛德W806,W801刷固件步骤

    本文针对无基础玩家参考,如有不对的欢迎指正 1)需要准备物料 1.开发板801或806 2.CH340驱动 (USB转串口驱动) 3.烧入工具(官方首页-芯片-W800-开发工具- 4.PC端固件烧录 ...

  8. 联盛德W806入门教程-CDK安装教程及代码下烧录

    笔者使用的系统板如下图所示: 首先安装代码编译软件CDK: 硬件:⚫ W805/W806 开发板 ⚫ USB 转串口线 软件: Windows 端编译工具:CDK 安装包 链接:[https://pa ...

  9. 联盛德 HLK-W806 (八): 4线SPI驱动SSD1306/SSD1315 128x64 OLED液晶屏

    目录 联盛德 HLK-W806 (一): Ubuntu20.04下的开发环境配置, 编译和烧录说明 联盛德 HLK-W806 (二): Win10下的开发环境配置, 编译和烧录说明 联盛德 HLK-W ...

最新文章

  1. 两种写法的效果一样,那么到底哪一种更好呢?
  2. 移动端300ms延迟解决的几种方法;
  3. mysql-安装报错计算机中丢失MSVCR100.dll文件丢失
  4. 【转】D365 FO第三方访问https证书问题
  5. Confluence 6 访问你的宏正文(body)
  6. MD5 + salt 的加密算法
  7. TCP/IP学习笔记12-- IP协议基础
  8. em算法 实例 正态分布_4-EM算法原理及利用EM求解GMM参数过程
  9. html 确定取消dialog,弹出一个带确认和取消的dialog实例
  10. 大写金额转换成阿拉伯数字金额
  11. 代码随想录第六天 LeetCode 242、349、202、1 (哈希表)
  12. 新建web.xml文件头报错报红xmlns=http://xmlns.jcp.org/xml/ns/javaee,http://xmlns.jcp.org/xml/ns/javaee/web-ap
  13. java 自动点击网页_JS脚本实现网页自动秒杀点击
  14. Photoshop脚本 压缩并输出GIF图片
  15. 【转】统一μITRON,日本成立开放源码ITRON团体
  16. 微信小程序轮播中的current_手把手教你美化微信小程序中的轮播效果
  17. 利用Echarts制作地图(一)
  18. 2020年日历电子版(打印版)_2020年日历打印版超清版
  19. 【AI数学原理】概率机器学习(四):半朴素贝叶斯之TAN算法实例
  20. ArcGIS流域提取教程

热门文章

  1. 白天 996, 我还能晚上669!
  2. jdbc 批量执行sql
  3. Windows Mobil中解决日期显示不正常的方法
  4. word学习-清除格式+清除链接
  5. Spring in Action 3 -The four kinds of autowiring
  6. 怎么去除烦人的WPS广告
  7. python 0基础容易学吗_Python0基础好学吗?
  8. 有关如何用html制作电影影评网,初阶展示
  9. (六)Python查询12306余票:升级版-----图形化界面代码
  10. 笔记本屏幕 亮度 背光调节 工具 c++ 用来解决亮度调节功能键失效问题