文章概览

‍️说在最前面 + 实现功能 1 CubeMX - RCC & Clock Configuration时钟配置諒 1.1 【System Core】 – 【RCC】諒 1.2 【Clock Configuration】

 2 CubeMX -SYS Debug设置 3 CubeMX -UART通讯设置 4 CubeMX - TIM定时器设置 5 CubeMX - GPIO设置 6 CubeMX - GPIO设置:连接DRV8323S的一些端口⭐諒 6.1 (STM32 - out) PA9 – CAL (DRV8323S - in)諒6.2 (STM32 - out) PA10 – ENABLE (DRV8323S – in,EN_GATE)諒6.3 (STM32 - X) 无 – nFAULT (DRV8323S – open-drain output) – 单片机连D11发光二极管

 7 CubeMX - SPI通信设置:用来和DRV8323通讯,配置PWM+发送错误信息⭐諒7.1 Connectivity – SPI 3諒7.2 System Core – GPIO

 8 Keil - SPI通信相关代码摘录‍️说在最后

‍️说在最前面 + 实现功能

最近在埋头搞STM32 + 无刷直流电机控制,想实现用自己的STM32F407VGT6芯片板子,外加一块驱动板(目前选用到TI的DRV8302或者DRV8323驱动芯片),搞定电机驱动,最后实现比较好的控制效果。如果不是同一块芯片的同学也不用急着走,大体上都是可借鉴哒~

本文主要实现使用SPI通信,通过STM32F407控制芯片来对DRV8323S驱动芯片进行配置,为使用DRV8323做好准备。

目标操作: 不启动电机,仅使能DRV8323S芯片。使用SPI朝DRV8323S芯片写几个地址的配置,然后再读取这几个位置的状态,检查是否通信正常。调试过程借助Keil的Debug功能中 watch变量的值,或使用UASRT串口通信打印出信息,来检查。

如果文章中有什么错误和待改进的地方,欢迎在评论区指出交流,共同学习和进步!✊ 首先是一系列用CubeMX的配置操作。

 1 CubeMX - RCC & Clock Configuration时钟配置

諒 1.1 【System Core】 – 【RCC】

HSE – Crystal/Ceramic Resonator 高速时钟源 – 外部晶振 会自动分配好管脚RCC_OSC_IN & RCC_OSC_OUT: PH0 – RCC_OSC_IN PH1 – RCC_OSC_OUT.

諒 1.2 【Clock Configuration】

系统定时器配置Cortex System timer – 168MHz

 2 CubeMX -SYS Debug设置

>> SYS Mode and Configuration Debug – Serial Wire Timebase Source – SysTick(后续若使用到RTOS,则需改成如TIM7的没用到的定时器!)

 3 CubeMX -UART通讯设置

USART3 —— 暂定用它接收(来自上位机的)控制电机指令 PD8-USART3_TX PD9-USART3_RX >> USART3 – Mode

ItemSettingModeAsynchronous异步模式Hardware Flow Control (RS232)Disable

>> Parameter Settings – Basic Parameters

ItemSettingBaud Rate115200 Bits/sWord Length8 Bits (including Parity)ParityNoneStop Bits1

>> Parameter Settings – Advanced Parameters

ItemSettingData DirectionReceive and TransmitOver Sampling16 Samples

>> NVIC Settings 中断使能,优先级(0,0)。 >> GPIO Settings

ItemSettingGPIO modeAlternate Function Push PullGPIO Pull-up/Pull-downPull-up 注意⭐Maximum output speedVery high

 4 CubeMX - TIM定时器设置

TIM8-PWM+TIM4-HALL+TIM6简单定时 本文暂时略

 5 CubeMX - GPIO设置

KEY+LED+PWM低桥臂 本文暂时略

 6 CubeMX - GPIO设置:连接DRV8323S的一些端口⭐

諒 6.1 (STM32 - out) PA9 – CAL (DRV8323S - in)

放大器校准输入。设置逻辑高时,内部短接放大器输入,并执行自动偏移校准。完成校准后引脚还要恢复低位,才能正常执行后续测量操作。 煮详见数据手册【8.3.4.3 Auto Offset Calibration – P44】 >> GPIO Settings

Item项目Setting设定GPIO Output LevelLow(引脚低电平)GPIO modeOutput Push Pull(输出推挽模式)GPIO Pull-up/Pull-downNo pull-up and no pull-downMaximum output speedHigh(引脚高速)

暂时不用自动校准功能!因此初始就让PA9输出低电平。

諒6.2 (STM32 - out) PA10 – ENABLE (DRV8323S – in,EN_GATE)

栅极驱动器启用。当该引脚为逻辑低时,设备进入低功率睡眠模式。8至40µs的低脉冲可用于重置故障条件。 煮详见数据手册【8.4.1.1 Sleep Mode – P50】

>> GPIO Settings

Item项目Setting设定GPIO Output LevelLow(引脚低电平)GPIO modeOutput Push Pull(输出推挽模式)GPIO Pull-up/Pull-downNo pull-up and no pull-downMaximum output speedHigh(引脚高速)

初始让PA10输出低电平,要使能DRV8323S芯片时,把引脚输出改为高电平。

諒6.3 (STM32 - X) 无 – nFAULT (DRV8323S – open-drain output) – 单片机连D11发光二极管

暂时不额外连STM32引脚来读状态(应该也可以连?目前我的板子版本未连),如果发光二极管D11亮了,则说明出故障了。 煮详见数据手册【8.3.6 Gate Driver Protective Circuits – P47】 外部硬件电路给他上拉了,出现故障时,nFAULT pin输出逻辑低,对应发光二极管D11亮。

 7 CubeMX - SPI通信设置:用来和DRV8323通讯,配置PWM+发送错误信息⭐

煮相关寄存器的配置备忘详见我的另一篇Blog:【DRV8323】电机驱动芯片寄存器配置指南,通过STM32F407的SPI通信配置。 SPI - Serial Peripheral Interface串行外围设备接口 SPI3是APB1上的设备,APB1 peripheral clocks = 42MHz,最高通信速率为 21Mbits/s。 SPI3_nSCS需要用GPIO单独配置,另外三个是SPI3自动配置的。

引脚名STM32自命名原理图中引脚命名PD1SPI3_nSCSNSCS(片选)【❗这个是GPIO_Output单独设!】PC10SPI3_SCKSPI_SCLK (时钟)PC11SPI3_MISOSPI_SDO (从机DRV8323输出数据,主机STM32输入。连DRV8323的SDO口)PC12SPI3_MOSISPI_SDI (主机STM32输出数据,发给从机DRV8323。连DRV8323的SDI口)

諒7.1 Connectivity – SPI 3

>> SPI3 – Mode

Item项目Setting设定ModeFull-Duplex Master (全双工主机模式)Hardware NSS SignalDisable(不是硬件控制)

>> Parameter Settings – Basic Parameters

Item项目Setting设定Frame FormatMotorolaData Size16 BitsFirst BitMSB First

>> Parameter Settings – Clock Parameters

Item项目Setting设定Prescaler (for Baud Rate)16 (❗一定要至少选16,稍微小一点都会因为太快了数据出错!)Baud Rate2.625 MBits/sClock Polarity (CPOL)Low (空闲态时,SCLK处于低电平)Clock Phase (CPHA)2 Edge(CPHA=1)

>> Parameter Settings – Advanced Parameters

Item项目Setting设定CRC CalculationDisabledNSS Signal TypeSoftware

諒7.2 System Core – GPIO

>> GPIO - PD1 Configuration

Item项目Setting设定GPIO Output LevelHigh(初始状态引脚高电平,低电平有效)GPIO modeOutput Push Pull(输出推挽模式)GPIO Pull-up/Pull-downNo pull-up and no pull-downMaximum output speedVery HighUser LabelSPI3_nSCS

>> GPIO - SPI - PC10&PC11&PC12 Configuration (?作者存疑点:PC11在CubeMX默认是输出状态?实现功能来说应该是输入)

Item项目Setting设定GPIO modeAlternate Function Push PullGPIO Pull-up/Pull-downNo Pull-up and no Pull-downMaximum output speedVery High

 8 Keil - SPI通信相关代码摘录

【motor_drv8323.c】代码(含寄存器和HAL库函数对比的详细版本)

/**

******************************************************************************

* @file motor_drv8323.c

* @date 2023-05-08

* @brief 驱动芯片DRV8323相关 - STM32 F407

******************************************************************************

*/

#include "motor_drv8323.h"

uint16_t TIMP01, TIMP02, TIMP03, TIMP04, TIMP05;

uint16_t TIMP1, TIMP2, TIMP3, TIMP4, TIMP5;

/**

* @brief 【MOTOR-DRV8323 SPI通信】

* 配置 DRV8323工作状态

* @function 0 - SPI读&写一体化函数 16位 - HAL库函数版本

* @function 1 - SPI 读 & 写16bit函数 - 寄存器版本

* @function 2 - DRV8323写入函数 16位 - 寄存器版本

* @function 3 - DRV8323读取函数 16位 - 寄存器版本

* @function 4 - SPI功能异常提示函数

* @function 5 - 用SPI配置DRV8323的函数 (操作封装)

*/

// 0 - SPI读&写一体化函数 16位 - HAL库函数版本 【要么用后三个,要么就用这个】

uint16_t SPI_ReadWrite_DRV8323(uint16_t ReadAddr)

{

uint16_t value;

SPI3_nSCS_LOW(); // SPI3-nSCS 拉低使能 //HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_RESET);

//HAL_Delay(500); // 如果 LOW & HIGH 操作是使用的BSRR寄存器操作版本,需要加上延时,否则速度太快可能会出错!

HAL_SPI_TransmitReceive(&hspi3, (uint8_t*)&ReadAddr, (uint8_t*)&value, 1, 1000); // 通过一个强制转换“骗过”库函数接口

//HAL_Delay(500); // 如果 LOW & HIGH 操作是使用的BSRR寄存器操作版本,需要加上延时,否则速度太快可能会出错!

SPI3_nSCS_HIGH(); // SPI3-nSCS 拉高关断 //HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_SET);

HAL_Delay(500);

return value;

}

// 1 - SPI读&写16bit函数 - 寄存器版本

uint16_t SPI_ReadWrite16bit(uint16_t ReadAddr)

{

int SPITimeout = SPIT_FLAG_TIMEOUT; // 等待超时时间 设为0x1000

// Loop while DR register in not emplty 等待发送缓冲区为空,TXE 事件

while (__HAL_SPI_GET_FLAG( &hspi3, SPI_FLAG_TXE ) == RESET)

{

if((SPITimeout--) == 0)

{ SPI_ERROR_UserCallback(); return 0; }

}

// Send Half Word through the SPIx peripheral 写入数据寄存器,把要写入的数据写入发送缓冲区

WRITE_REG(hspi3.Instance->DR, ReadAddr);

SPITimeout = SPIT_FLAG_TIMEOUT;

// Wait to receive a Half Word 等待接收缓冲区非空,RXNE 事件

while (__HAL_SPI_GET_FLAG( &hspi3, SPI_FLAG_RXNE ) == RESET)

{

if((SPITimeout--) == 0)

{ SPI_ERROR_UserCallback(); return 0; }

}

// Return the Half Word read from the SPI bus 读取数据寄存器,获取接收缓冲区数据

return READ_REG(hspi3.Instance->DR);

}

// 2 - DRV8323写入函数 16位 - 寄存器版本

uint16_t SPI_WRITE_DRV8323(uint16_t WriteData)

{

uint16_t RxData;

SPI3_nSCS_LOW(); // SPI3-nSCS 拉低使能

HAL_Delay(100); // 如果 LOW & HIGH 操作是使用的BSRR寄存器操作版本,需要加上延时,否则速度太快可能会出错!

SPI_ReadWrite16bit(WriteData);

HAL_Delay(100); // 如果 LOW & HIGH 操作是使用的BSRR寄存器操作版本,需要加上延时,否则速度太快可能会出错!

SPI3_nSCS_HIGH(); // SPI3-nSCS 拉高关断

HAL_Delay(100); // 如果 LOW & HIGH 操作是使用的BSRR寄存器操作版本,需要加上延时,否则速度太快可能会出错!

return RxData; // 对于Write操作不用有返回值,这里有只是更方便调试观察,看看是否正确写入

}

// 3 - DRV8323读取函数 16位 - 寄存器版本

uint16_t SPI_Read_DRV8323(uint16_t ReadAddr)

{

uint16_t RxData;

SPI3_nSCS_LOW(); // SPI3-nSCS 拉低使能

HAL_Delay(100); // 如果 LOW & HIGH 操作是使用的BSRR寄存器操作版本,需要加上延时,否则速度太快可能会出错!

RxData = SPI_ReadWrite16bit(ReadAddr);

HAL_Delay(100); // 如果 LOW & HIGH 操作是使用的BSRR寄存器操作版本,需要加上延时,否则速度太快可能会出错!

SPI3_nSCS_HIGH(); // SPI3-nSCS引脚拉高,因为不用它了

HAL_Delay(100); // 如果 LOW & HIGH 操作是使用的BSRR寄存器操作版本,需要加上延时,否则速度太快可能会出错!

return RxData;

}

// 4 - SPI功能异常提示函数

void SPI_ERROR_UserCallback(void)

{

/* 等待超时后的处理,输出错误信息 */

printf("SPI 通信异常! \r\n");

}

// 5 - 用SPI设置DRV8323的函数 (操作封装)

void Set_DRV8323(void)

{

//库函数版本测试代码

Drv8323_ENABLE();//使能Drv-Enable输入高电平,驱动芯片开始工作

HAL_Delay(1000);

//SPI_ReadWrite_DRV8323(Dummy_Byte);HAL_Delay(500);

// TIMP1 = SPI_ReadWrite_DRV8323(0x9000);//取地址0x02

// TIMP2 = SPI_ReadWrite_DRV8323(0x9800);//取地址0x03

// TIMP3 = SPI_ReadWrite_DRV8323(0xA000);//取地址0x04

// TIMP4 = SPI_ReadWrite_DRV8323(0xA800);//取地址0x05

// TIMP5 = SPI_ReadWrite_DRV8323(0xB000);//取地址0x06

TIMP01 = SPI_ReadWrite_DRV8323(0x1000); //address 02

TIMP02 = SPI_ReadWrite_DRV8323(0x1bff); //address 03

TIMP03 = SPI_ReadWrite_DRV8323(0x27ff); //address 04

TIMP04 = SPI_ReadWrite_DRV8323(0x2a59); //address 05

TIMP05 = SPI_ReadWrite_DRV8323(0x3283); //address 06

// SPI_ReadWrite_DRV8323(0x1000); //address 02

// SPI_ReadWrite_DRV8323(0x1B22); //address 03

// SPI_ReadWrite_DRV8323(0x2722); //address 04

// SPI_ReadWrite_DRV8323(0x2B66); //address 05

// SPI_ReadWrite_DRV8323(0x3280); //address 06

HAL_Delay(500);

TIMP1 = SPI_ReadWrite_DRV8323(0x9000);//取地址0x02

TIMP2 = SPI_ReadWrite_DRV8323(0x9800);//取地址0x03

TIMP3 = SPI_ReadWrite_DRV8323(0xA000);//取地址0x04

TIMP4 = SPI_ReadWrite_DRV8323(0xA800);//取地址0x05

TIMP5 = SPI_ReadWrite_DRV8323(0xB000);//取地址0x06

printf("add0x02 = %d \r\n", TIMP1);

printf("add0x03 = %d \r\n", TIMP2);

printf("add0x04 = %d \r\n", TIMP3);

printf("add0x05 = %d \r\n", TIMP4);

printf("add0x06 = %d \r\n", TIMP5);

Drv8323_DISABLE();//使能Drv-Enable输入低电平,驱动芯片停止工作

/* //寄存器版本测试代码

Drv8323_ENABLE();//使能Drv-Enable输入高电平,驱动芯片开始工作

HAL_Delay(1000);

// TIMP01 = SPI_WRITE_DRV8323(0x1000); //address 02

// TIMP02 = SPI_WRITE_DRV8323(0x1bff); //address 03

// TIMP03 = SPI_WRITE_DRV8323(0x27ff); //address 04

// TIMP04 = SPI_WRITE_DRV8323(0x2a59); //address 05

// TIMP05 = SPI_WRITE_DRV8323(0x3283); //address 06

// HAL_Delay(500);

TIMP1 = SPI_Read_DRV8323(0x9000);//取地址0x02

TIMP2 = SPI_Read_DRV8323(0x9800);//取地址0x03

TIMP3 = SPI_Read_DRV8323(0xA000);//取地址0x04

TIMP4 = SPI_Read_DRV8323(0xA800);//取地址0x05

TIMP5 = SPI_Read_DRV8323(0xB000);//取地址0x06

printf("add0x02 = %d \r\n", TIMP1);

printf("add0x03 = %d \r\n", TIMP2);

printf("add0x04 = %d \r\n", TIMP3);

printf("add0x05 = %d \r\n", TIMP4);

printf("add0x06 = %d \r\n", TIMP5);

Drv8323_DISABLE();//使能Drv-Enable输入低电平,驱动芯片停止工作

*/

}

/**

* @brief 【MOTOR-DRV8323 芯片使能】

* @function 1 - DRV8323的芯片使能

* @function 2 - DRV8323的芯片关闭

*/

// 1 - DRV8323的芯片使能

void Drv8323_ENABLE(void) //DRV8323 Enable

{

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET);

//printf("DRV8323S 芯片启用。\r\n");

}

// 2 - DRV8323的芯片关闭

void Drv8323_DISABLE(void) //DRV8323 Disable

{

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_RESET);

//printf("DRV8323S 芯片关闭。\r\n");

}

【motor_drv8323.c】代码(HAL库函数的简洁版本,可直接用)

/**

******************************************************************************

* @file motor_drv8323.c

* @date 2023-05-08

* @brief 驱动芯片DRV8323相关 - STM32 F407

******************************************************************************

*/

#include "motor_drv8323.h"

uint16_t TIMP01, TIMP02, TIMP03, TIMP04, TIMP05;

uint16_t TIMP1, TIMP2, TIMP3, TIMP4, TIMP5;

/**

* @brief 【MOTOR-DRV8323 SPI通信】

* 配置 DRV8323工作状态

* @function 1 - SPI读&写一体化函数 16位 - HAL库函数版本

* @function 2 - SPI功能异常提示函数

* @function 3 - 用SPI配置DRV8323的函数 (操作封装)

*/

// 1 - SPI读&写一体化函数 16位 - HAL库函数版本

uint16_t SPI_ReadWrite_DRV8323(uint16_t ReadAddr)

{

uint16_t value;

SPI3_nSCS_LOW(); // SPI3-nSCS 拉低使能 //HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_RESET);

HAL_Delay(100); // 如果 LOW & HIGH 操作是使用的BSRR寄存器操作版本,需要加上延时(大概500),否则速度太快可能会出错!

HAL_SPI_TransmitReceive(&hspi3, (uint8_t*)&ReadAddr, (uint8_t*)&value, 1, 1000); // 通过一个强制转换“骗过”库函数接口

HAL_Delay(100); // 如果 LOW & HIGH 操作是使用的BSRR寄存器操作版本,需要加上延时(大概500),否则速度太快可能会出错!

SPI3_nSCS_HIGH(); // SPI3-nSCS 拉高关断 //HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_SET);

HAL_Delay(500);

return value;

}

// 2 - SPI功能异常提示函数

void SPI_ERROR_UserCallback(void)

{

/* 等待超时后的处理,输出错误信息 */

printf("SPI 通信异常! \r\n");

}

// 3 - 用SPI设置DRV8323的函数 (操作封装)

void Set_DRV8323(void)

{

Drv8323_ENABLE();//使能Drv-Enable输入高电平,驱动芯片开始工作

HAL_Delay(1000);

TIMP01 = SPI_ReadWrite_DRV8323(0x1000); //address 02

TIMP02 = SPI_ReadWrite_DRV8323(0x1bff); //address 03

TIMP03 = SPI_ReadWrite_DRV8323(0x27ff); //address 04

TIMP04 = SPI_ReadWrite_DRV8323(0x2a59); //address 05

TIMP05 = SPI_ReadWrite_DRV8323(0x3283); //address 06

HAL_Delay(200);

TIMP1 = SPI_ReadWrite_DRV8323(0x9000);//取地址0x02

TIMP2 = SPI_ReadWrite_DRV8323(0x9800);//取地址0x03

TIMP3 = SPI_ReadWrite_DRV8323(0xA000);//取地址0x04

TIMP4 = SPI_ReadWrite_DRV8323(0xA800);//取地址0x05

TIMP5 = SPI_ReadWrite_DRV8323(0xB000);//取地址0x06

printf("======DRV8323寄存器配置情况======\r\n");

printf("add0x02 = %x \r\n", TIMP1); // %d - 十进制

printf("add0x03 = %x \r\n", TIMP2); // %x - 十六进制

printf("add0x04 = %x \r\n", TIMP3);

printf("add0x05 = %x \r\n", TIMP4);

printf("add0x06 = %x \r\n", TIMP5);

printf("=================================\r\n");

//Drv8323_DISABLE();//使能Drv-Enable输入低电平,驱动芯片停止工作

//在这里就关的话就用不了啦!

}

/**

* @brief 【MOTOR-DRV8323 芯片使能】

* @function 1 - DRV8323的芯片使能

* @function 2 - DRV8323的芯片关闭

*/

// 1 - DRV8323的芯片使能

void Drv8323_ENABLE(void) //DRV8323 Enable

{

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_SET);

printf("DRV8323S 芯片启用。\r\n");

}

// 2 - DRV8323的芯片关闭

void Drv8323_DISABLE(void) //DRV8323 Disable

{

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_10, GPIO_PIN_RESET);

printf("DRV8323S 芯片关闭。\r\n");

}

【motor_drv8323.h】代码

#ifndef __MOTOR_DRV8323_H

#define __MOTOR_DRV8323_H

#include "stm32f4xx.h"

#include "spi.h"

#include

#include

#include

/********** MOTOR_CONTROL 宏定义 **********/

#define Dummy_Byte 0xFFFF

#define SPIT_FLAG_TIMEOUT ((uint32_t)0x1000) // 等待超时时间

#define SPI3_CLK_ENABLE() __HAL_RCC_SPI3_CLK_ENABLE()

//SCK 引脚

#define SPI3_SCK_PIN GPIO_PIN_10

#define SPI3_SCK_ GPIO_PORT GPIOC

//MISO 引脚

#define SPI3_MISO_PIN GPIO_PIN_11

#define SPI3_MISO_GPIO_PORT GPIOC

//MOSI 引脚

#define SPI3_MOSI_PIN GPIO_PIN_12

#define SPI3_MOSI_GPIO_PORT GPIOC

//CS(nSCS) 引脚

#define SPI3_nSCS_PIN GPIO_PIN_1

#define SPI3_nSCS_GPIO_PORT GPIOD

// 以下是两种方法给SPI3_nSCS 高、低电平 ??据说操作寄存器比调用HAL库函数快

// 寄存器版本 给SPI3_nSCS 高、低电平,用寄存器版本可能需要多一点点延时,以免软件速度太快硬件跟不上。

BSRR寄存器:控制管脚的高、低电平。32位有效,低16位写1 高电平,高16位写1 低电平。

//#define digitalLow(p,i) {p->BSRR=(uint32_t)i << 16;} //输出低电平

//#define digitalHigh(p,i) {p->BSRR=i;} //设置为高电平

//#define SPI3_nSCS_LOW() digitalLow( SPI3_nSCS_GPIO_PORT, SPI3_nSCS_PIN )

//#define SPI3_nSCS_HIGH() digitalHigh(SPI3_nSCS_GPIO_PORT, SPI3_nSCS_PIN )

// 库函数版本 给SPI3_nSCS 高、低电平

#define SPI3_nSCS_LOW() HAL_GPIO_WritePin(SPI3_nSCS_GPIO_PORT, SPI3_nSCS_PIN, GPIO_PIN_RESET)

#define SPI3_nSCS_HIGH() HAL_GPIO_WritePin(SPI3_nSCS_GPIO_PORT, SPI3_nSCS_PIN, GPIO_PIN_SET)

/********************************************/

/********** MOTOR_CONTROL 相关变量 **********/

extern SPI_HandleTypeDef hspi3;

/********************************************/

/********** MOTOR_CONTROL 函数声明 **********/

// 【MOTOR-DRV8323 SPI通信】

uint16_t SPI_ReadWrite_DRV8323(uint16_t ReadAddr);// 0 - SPI读&写一体化函数 16位 - HAL库函数版本

uint16_t SPI_ReadWrite16bit(uint16_t ReadAddr);// 1 - SPI 读 & 写16bit函数 - 寄存器版本

uint16_t SPI_WRITE_DRV8323(uint16_t WriteData);// 2 - DRV8323写入函数 16位 - 寄存器版本

uint16_t SPI_Read_DRV8323(uint16_t ReadAddr); // 3 - DRV8323读取函数 16位 - 寄存器版本

void SPI_ERROR_UserCallback(void); // 4 - SPI功能异常提示函数

void Set_DRV8323(void); // 5 - 用SPI配置DRV8323的函数 (操作封装)

// 【MOTOR-DRV8323 芯片使能】

void Drv8323_ENABLE(void);

void Drv8323_DISABLE(void);

/********************************************/

/* USER CODE BEGIN Private defines */

#endif /* __MOTOR_DRV8323_H */

【main.c】代码

/* USER CODE BEGIN Header */

/**

******************************************************************************

* @file : main.c

* @brief : Main program body

******************************************************************************

* @attention

*

* Copyright (c) 2023 STMicroelectronics.

* All rights reserved.

*

* This software is licensed under terms that can be found in the LICENSE file

* in the root directory of this software component.

* If no LICENSE file comes with this software, it is provided AS-IS.

*

******************************************************************************

*/

/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/

#include "main.h"

#include "spi.h"

#include "tim.h"

#include "usart.h"

#include "gpio.h"

/* Private includes ----------------------------------------------------------*/

/* USER CODE BEGIN Includes */

#include "LED/led.h"

#include "KEY/key.h"

#include "MOTOR/motor_tim.h"

#include "MOTOR/motor_control.h"

#include "MOTOR/motor_drv8323.h"

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/

/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/

/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/

/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/

void SystemClock_Config(void);

/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/

/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**

* @brief The application entry point.

* @retval int

*/

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_TIM4_Init();

MX_SPI3_Init();

MX_UART4_Init();

MX_USART2_UART_Init();

MX_USART3_UART_Init();

MX_TIM6_Init();

MX_TIM8_Init();

/* USER CODE BEGIN 2 */

Init_Motor(); // MX_TIMx_Init();也在里面

Init_LED();

Set_Motor_StartStop(0); //关闭电机 - stop PWM & Hall

Set_DRV8323(); // 通过SPI配置DRV8323寄存器,来配置驱动芯片工作模式

Set_Motor_StartStop(1); //开启电机 - enable PWM & Hall

/* USER CODE END 2 */

/* Infinite loop */

/* USER CODE BEGIN WHILE */

while (1)

{

/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */

}

/* USER CODE END 3 */

}

/**

* @brief System Clock Configuration

* @retval None

*/

void SystemClock_Config(void)

{

RCC_OscInitTypeDef RCC_OscInitStruct = {0};

RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

/** Configure the main internal regulator output voltage

*/

__HAL_RCC_PWR_CLK_ENABLE();

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

/** Initializes the RCC Oscillators according to the specified parameters

* in the RCC_OscInitTypeDef structure.

*/

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;

RCC_OscInitStruct.HSEState = RCC_HSE_ON;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

RCC_OscInitStruct.PLL.PLLM = 4;

RCC_OscInitStruct.PLL.PLLN = 168;

RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;

RCC_OscInitStruct.PLL.PLLQ = 4;

if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

{

Error_Handler();

}

/** Initializes the CPU, AHB and APB buses clocks

*/

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK

|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)

{

Error_Handler();

}

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**

* @brief This function is executed in case of error occurrence.

* @retval None

*/

void Error_Handler(void)

{

/* USER CODE BEGIN Error_Handler_Debug */

/* User can add his own implementation to report the HAL error return state */

__disable_irq();

while (1)

{

}

/* USER CODE END Error_Handler_Debug */

}

#ifdef USE_FULL_ASSERT

/**

* @brief Reports the name of the source file and the source line number

* where the assert_param error has occurred.

* @param file: pointer to the source file name

* @param line: assert_param error line source number

* @retval None

*/

void assert_failed(uint8_t *file, uint32_t line)

{

/* USER CODE BEGIN 6 */

/* User can add his own implementation to report the file name and line number,

ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

/* USER CODE END 6 */

}

#endif /* USE_FULL_ASSERT */

‍️说在最后

本文关于SPI通信的介绍到这里就结束啦,预祝大家调试顺利! 附上笔者学习过程中觉得对自己有帮助的博文: STM32G4系列通过SPI配置DRV8353S驱动芯片_超级馒头神的博客-CSDN博客(驱动芯片区别应该仅在于芯片的驱动电压范围不同); DRV8301的使用_【ql君】qlexcel的博客-CSDN博客; STM32F334 SPI编程里的坑_hy_wujun-CSDN博客; 【STM32】HAL库开发教程(七)—SPI使用_怪怪王-CSDN博客 关于STM32使用SPI接口实现自通信的一个详细示例(程序实现)_曾小庆-知乎 stm32 GPIO模拟SPI接口实现双机通信_惆怅客~-CSDN博客 DRV8301 SPI调试问题(接收一直为0x0000)_映月寒-CSDN博客 DRV8323S关于SPI通信以及PWM输出不正常-TI官网论坛; DRV8323 PWM OUTPUT-TI官网论坛; [FAQ] SPI Configuration and Use-TI官网论坛; 【正点原子-STM32F1开发指南(精英板-HAL库版)-CH28】 【野火-STM32 HAL库开发实战指南——基于野火F4系列开发板-CH23】 比ZDYZ的这个部分讲解得更清晰,更推荐一点点。

推荐链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: