单片机
返回首页

STM32G4电机外设系列(四):DAC输出电流波形分析与CAN通讯实战

2025-09-26 来源:cnblogs

1 DAC输出电流波形

  • 电机控制环路主要涉及的外设功能包含高级定时器TIM1的发波,OPAMP 及 ADC 准确的采样三相电流,并在三相电流过流时及时封波,避免损坏硬件

  • 本文将会使用STM32G4内部 TIM1ADCCOMP DAC级联使用

  • 1.1 STM32CubeMX配置和Keil代码
  • 配置 DAC1_CH1 为输出模式,只连接外部 Pin,配置外部 Pin为 PA4,使能
    buffer 模式
    * 点击生成代码

  • 在Keil修改代码如下

  • /* USER CODE BEGIN PV */ 中增加

    uint32_t DAC_wave[100] = { 

        0x0800, 0x0881, 0x0901, 0x0980, 0x09FD, 0x0A79, 0x0AF2, 0x0B68, 0x0BDA, 0x0C49,

        0x0CB3, 0x0D19, 0x0D79, 0x0DD4, 0x0E29, 0x0E78, 0x0EC0, 0x0F02, 0x0F3C, 0x0F6F,

        0x0F9B, 0x0FBF, 0x0FDB, 0x0FEF, 0x0FFB, 0x0FFF, 0x0FFB, 0x0FEF, 0x0FDB, 0x0FBF,

        0x0F9B, 0x0F6F, 0x0F3C, 0x0F02, 0x0EC0, 0x0E78, 0x0E29, 0x0DD4, 0x0D79, 0x0D19,

        0x0CB3, 0x0C49, 0x0BDA, 0x0B68, 0x0AF2, 0x0A79, 0x09FD, 0x0980, 0x0901, 0x0881,

        0x0800, 0x077F, 0x06FF, 0x0680, 0x0603, 0x0587, 0x050E, 0x0498, 0x0426, 0x03B7,

        0x034D, 0x02E7, 0x0287, 0x022C, 0x01D7, 0x0188, 0x0140, 0x00FE, 0x00C4, 0x0091,

        0x0065, 0x0041, 0x0025, 0x0011, 0x0005, 0x0001, 0x0005, 0x0011, 0x0025, 0x0041,

        0x0065, 0x0091, 0x00C4, 0x00FE, 0x0140, 0x0188, 0x01D7, 0x022C, 0x0287, 0x02E7,

        0x034D, 0x03B7, 0x0426, 0x0498, 0x050E, 0x0587, 0x0603, 0x0680, 0x06FF, 0x077F

    };


    /* Initialize all configured peripherals */ 中增加,来启动DAC1通道1

    HAL_DAC_Start(&hdac1, DAC_CHANNEL_1);


    //中断处理函数中增加,来输出DAC的波形

    i++;

    if(i>=100)

    {

    i = 0;

    }

    HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, DAC_wave[i]);




  • 编译并下载程序

  • 1.2 实验现象

    使用逻辑分析仪或者示波器链接逻辑分析仪,查看上传波形

    2 CAN/CANFD通讯

  • 本章介绍使用STM32CUBEMX建立CAN通讯,由于CAN通讯自身的特点,在电机控制的场景中使用非常常见,了解CAN通讯非常有必要

  • 2.1 STM32CubeMX配置和Keil代码
  • 首先配置cubeMx程序,在上一章的基础上使能CAN外设

  • 配置仲裁段和数据段的分频系数跳转位宽,使能FIFO模式

  • 波特率:500k = 160M/20/(1+10+5)

  • 使能中断,生成代码

  • 打开Keil,main函数中的部分代码的修改如下

  • 1. 定义RX和TX数据以及中间变量

    /* USER CODE BEGIN PV */ 

    //CAN收发

    FDCAN_RxHeaderTypeDef RxHeader;

    FDCAN_TxHeaderTypeDef TxHeader;

    uint8_t RxData[8] = {NULL};

    uint8_t TxData[8] = {NULL};

    float CANtemp[1];


    2. 声明函数

    /* USER CODE BEGIN PFP */ 

    void FDCAN2_Config(void);

    /* USER CODE END PFP */


    3. 配置RX和TX数据帧类型,RX接受的ID范围,TX的ID和和数据长度等参数

    /* USER CODE BEGIN 4 */ 

    void FDCAN2_Config(void)

    {

    FDCAN_FilterTypeDef sFilterConfig;

    HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);

    sFilterConfig.IdType = FDCAN_EXTENDED_ID;

    sFilterConfig.FilterIndex = 0;

    sFilterConfig.FilterType = FDCAN_FILTER_RANGE;

    sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;

    sFilterConfig.FilterID1 = 0x00000000;

    sFilterConfig.FilterID2 = 0x01ffffff;

    HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig);

    TxHeader.Identifier = 0x1B;

    TxHeader.IdType = FDCAN_EXTENDED_ID;

    TxHeader.TxFrameType = FDCAN_DATA_FRAME;

    TxHeader.DataLength = FDCAN_DLC_BYTES_8;

    TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;

    TxHeader.BitRateSwitch = FDCAN_BRS_OFF;

    TxHeader.FDFormat = FDCAN_CLASSIC_CAN;

    TxHeader.TxEventFifoControl= FDCAN_NO_TX_EVENTS;

    TxHeader.MessageMarker = 0x52;

    HAL_FDCAN_Start(&hfdcan1);

    }


    4. 在while循环中将VDC电压上传至上位机

    /* USER CODE BEGIN WHILE */

    while(1)

    {

    HAL_ADC_Start(&hadc1);

    HAL_ADC_Start(&hadc2);

    temp[3] = HAL_ADC_GetValue(&hadc1);

    temp[3] = temp[3] * 3.3f/4096*26;

    temp[4] = HAL_ADC_GetValue(&hadc2);

    temp[4] = temp[4] * 3.3f/4096*26;

    CANtemp[0] = temp[4];

    memcpy(TxData,(uint8_t*)&CANtemp, sizeof(CANtemp));

    HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData);

    HAL_Delay(10);

    }

    /* USER CODE END WHILE */


    5. 在it.c文件中,在FDCAN中断里面,接收上位机发送的数据

    /* USER CODE BEGIN EV */

    extern FDCAN_HandleTypeDef hfdcanl;

    extern FDCAN_RxHeaderTypeDef RxHeader;

    extern uint8_t RxData[8];

    /* USER CODE END EV */



    void FDCAN1_IT0_IRQHandler(void)

    {

      /* USER CODE BEGIN FDCAN1_IT0_IRQn 0 */


      /* USER CODE END FDCAN1_IT0_IRQn 0 */

      HAL_FDCAN_IRQHandler(&hfdcan1);

      /* USER CODE BEGIN FDCAN1_IT0_IRQn 1 */

      HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO0, &RxHeader, RxData);

      /* USER CODE END FDCAN1_IT0_IRQn 1 */

    }




  • 编译并下载代码

  • 2.2 实验现象
  • 接线图

  • 打开PCAN上位机,选择500k波特率,点击OK

  • 可以看到接受的数据帧ID与MCU中设置一样,上传的VDC电压实时刷新

  • 点击下发数据,可以在Keil的Debug中查看接受的数据


进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 1瓦线性调频增强器

  • 12V 转 28V DC-DC 变换器(基于 LM2585)

  • 红外遥控音量控制

  • LM317过压保护

  • 12V转110V/220V 500W逆变器

  • DS1669数字电位器

    相关电子头条文章