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

目录

  • 高速 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);
}

其他改动

在这里插入图片描述

在这里插入图片描述

实验现象

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/400091.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安装配置 radicale

为什么80%的码农都做不了架构师&#xff1f;>>> 可以直接pip安装,也可以下载源码安装,如果要存储到sql里面,则需要下载源码包,用里面的schema.sql 建表 默认安装后没有相应的配置文件,源码包里面也包含了 logging 和config,放到/etc/radicale 下 安装没什么说的,下…

【联盛德W806上手笔记】九、DMA

目录DMA 控制器功能概述功能描述DMA 通道DMA 数据流DMA 循环模式DMA 传输模式DMA 外设选择DMA 链表模式DMA 中断中断请求库函数函数参数宏应用Windows 10 20H2 HLK-W806-V1.0-KIT WM_SDK_W806_v0.6.0 摘自《W806 MCU 芯片规格书 V2.0》、《WM_W800_寄存器手册 V2.1》 DMA 控制…

SNF快速开发平台MVC-自由排序组件

1. 自由排序功能使用 在一些需要排序优先级的数据进行调整处理&#xff0c;如民族数据&#xff0c;在北方实施的时候汉族比较多&#xff0c;希望把汉族放在第一位。在蒙古实施项目时&#xff0c;蒙古族人最多把蒙古族放在第一选择位。 1.1. 效果展示 图 1.1 1.2. …

【联盛德W806上手笔记】十、ADC

目录ADCADC 电路设计库函数函数参数宏Demo中的例程main.cwm_hal_msp.cwm_it.cWindows 10 20H2 HLK-W806-V1.0-KIT WM_SDK_W806_v0.6.0 摘自《W806 芯片设计指导书 V1.0》、《W806 MCU 芯片规格书 V2.0》 ADC 基于 Sigma-Delta ADC 的采集模块&#xff0c;集成 4 路 16 比特 AD…

【电路补习笔记】8、稳压电路 —— 线性电源及LDO

目录有名的电源芯片品牌DCDC电源分类开关电源vs线性稳压器线性电源参数线性电源工作原理集成稳压器78/79系列&#xff08;固定输出电压&#xff09;正、负对称输出两组电源的稳压电路扩展输出电压扩大输出电流LM317/LM337&#xff08;可调输出电压&#xff09;正、负对称输出两…

ajax代码整理

$.ajax({ type: "post", 【以POST或GET的方式请求。默认GET。PUT和DELETE也可以用&#xff0c;有的浏览器不支持】 url: url, 【请求的目的地址&#xff0c;须是一个字符串。】 contentType: "application/json", 【以哪种数据类型发送请求】 data: data, …

创建一个简单的WCF程序

为了使读者对基于WCF的编程模型有一个直观的映像&#xff0c;我将带领读者一步一步地创建一个完整的WCF应用。本应用功能虽然简单&#xff0c;但它涵盖了一个完整WCF应用的基本结构。对那些对WCF不是很了解的读者来说&#xff0c;这个例子将带领你正式进入WCF的世界。 在这个例…

深圳IO —— 一个汇编编程小游戏

目录简介数据手册接口简单 I/OXBus简单 I/O 对比 XBus语言参考程序结构注释标签寄存器accdatp0、p1、x0、x1、x2、x3null 伪寄存器指令操作数确保进行足够的睡眠 (slp)&#xff01;基本指令算法指令条件指令隐藏指令游戏界面DIY版本&#xff1a; 简介 以下介绍摘自未来软件园 …

unity shader 编辑器扩展类 ShaderGUI

这应该unity5才出的新功能了&#xff0c;今天看文档时刚巧看到了&#xff0c;就来尝试了一下。 效果如图&#xff1a; shader 的编辑器扩展分为2种方法&#xff1a; 是通过UnityEditor下的ShaderGUI类来实现的&#xff0c;形式比较近似于我们一般对unity编辑器的扩展方式。是通…

【电路补习笔记】9、电容式开关电源(电荷泵)

目录分类原理电荷泵基础开关电容稳压器的细调功能电荷泵的电压增益调节输出电容&#xff08;Co&#xff09;优点电容式开关稳压器减小纹波相关应用老师的主页&#xff1a;唐老师讲电赛 视频地址&#xff1a; 电源大师3——电容式开关电源&#xff08;电荷泵&#xff09;工作原理…

CPU 硬盘性能到底相差多少

本文以一个现代的、实际的个人电脑为对象&#xff0c;分析其中CPU&#xff08;Intel Core 2 Duo 3.0GHz&#xff09;以及各类子系统的运行速度——延迟和数据吞吐量。通过粗略的估算PC各个组件的相对运行速度&#xff0c;希望能给大家留下一个比较直观的印象。本文中的数据来自…

【电路补习笔记】10、电感式开关电源(BUCK 降压电路)

目录分类封装焊线式覆晶式开关电源三种基本的非隔离开关电源纹波&#xff08;ripple&#xff09;开关电源的元件构成有源开关肖特基二极管或快恢复二极管不使用普通硅二极管的原因电感电容分压电阻&#xff08;输出电压设置&#xff09;工作原理工作模式连续模式&#xff08;co…

php中Session的生成机制、回收机制和存储机制探究

转载:http://www.jb51.net/article/53938.htm这篇文章主要介绍了php中Session的生成机制、回收机制和存储机制探究,可以帮助大家对Session有一个全面的了解,需要的朋友可以参考下1、php中session的生成机制我们先来分析一下PHP中是怎么生成一个session的。设计出session的目的是…

wsl2 Ubuntu 18.04 安装 ROS

目录前期准备安装ROS初始化rosdep测试前期准备 WSL的安装见旧版 WSL 的手动安装步骤从步骤4开始弄。 图形界面安装见在WSL中使用GPU&#xff1a;WSL2 Ubuntu 18.04 CUDA Gnome图形界面环境配置 界面汉化见WSL-Ubuntu安装中文语言 这里使用鱼香ROS大佬的一键安装脚本&…

GPU CUDA 经典入门指南

转自&#xff1a;http://luofl1992.is-programmer.com/posts/38830.html CUDA编程中&#xff0c;习惯称CPU为Host&#xff0c;GPU为Device。编程中最开始接触的东西恐怕是并行架构&#xff0c;诸如Grid、Block的区别会让人一头雾水&#xff0c;我所看的书上所讲述的内容比较抽象…

用PyQt实现透明桌面时钟小部件

2019独角兽企业重金招聘Python工程师标准>>> #!/usr/bin/env python # -*- coding: utf-8 -*-Created on 2012-4-6author: wangxiaoimport sys from PyQt4 import QtGui, QtCore from PyQt4.QtCore import Qt from PyQt4.QtCore import QPoint from PyQt4.QtCore…

实现织梦dedecms百度主动推送(实时)网页抓取

做百度推广的时候&#xff0c;如何让百度快速收录呢&#xff0c;下面提供了三种方式&#xff0c;今天我们主要讲的是第一种。 如何选择链接提交方式 1、主动推送&#xff1a;最为快速的提交方式&#xff0c;推荐您将站点当天新产出链接立即通过此方式推送给百度&#xff0c;以保…

【RK3399Pro学习笔记】十八、点亮LED灯(python、C语言、bash)

目录GPIOpython3python-peripherypython2RPiC语言SysFs方式编写gpiolib.cgpiolib.hmain.c编译测试wiringPibash平台&#xff1a;华硕 Thinker Edge R 瑞芯微 RK3399Pro 固件版本&#xff1a;Tinker_Edge_R-Debian-Stretch-V1.0.4-20200615 GPIO (机翻)下表显示了座子的引脚&am…

Linux中python、C++和C语言的多线程用法整理(_thread、threading、thread和pthread)

目录python3开始学习Python线程_thread常量和函数&#xff1a;锁对象试用基本功能试用线程同步threading函数常量类线程本地数据线程对象锁对象递归锁对象条件对象信号量对象Semaphore 例子事件对象定时器对象栅栏对象在 with 语句中使用锁、条件和信号量测试Cstd::threadstd::…

Swing-BoxLayout用法-入门

注&#xff1a;本文内容源于http://www.java3z.com/cwbwebhome/article/article20/200016.html?id4797&#xff1b;细节内容根据笔者理解有修改。 BoxLayout 可以把控件依次进行水平或者垂直排列布局&#xff0c;这是通过参数 X_AXIS、Y_AXIS 来决定的。X_AXIS 表示水平排列&a…