BLDC的列子2

1.三相采样电流的采集以u相为举例。

采集下桥臂I-V的电压。在除以采样电阻。就可以得到采样电流。但由于I-V的电压比较小。

需要一个放大电路把电压放大ADC才采集的到。

放大后的电压是AMP_IU.用ADC去采集这个电压。从而算出I_V的电压。 

在电机停止的时候也会有微小的电压。并且包括1.25V的抬升电压。所以实际的电压如下计算:

 先求电机停止时的偏置电压,在求运行时的电压。

I = (运行时的电压 - 偏置电压)/0.12 

 2.电源电压

 

运放是一个射极跟随器所以VBUS等于A点的电压 。当用ADC采集VBUS的电压就知道A点的电压。从而可以计算出POWER的电压(分压公式)。因为POWER是电机的供电电压。当比较相差很大时就可以判断有故障发生。

3.板子温度的采集

板子上有一个热敏电阻随温度的变化而变化。

跟电源电压一样运放是射极跟随器。VTEMP点的电压等于A点的电压。VCC等于3. 3v。可以求出R106的阻值。

上面实际温度的公式是根据热敏电阻的手册可以查出的。

 上面的有些参数需要查手册如下:Rt就是通过上面分压计算得到。

 4.速度环

当只有一对极时。旋转一圈有180度的高电平与180度的低电平(如图:霍尔1,2,3)。

当我们求出高电平的时间(t)=高电平的计数值*PWM的频率(不是定时器的频率)。

总的时间:2t(因为高电平与低电平相等) T=2(Cnt/fpwm) 单位s/圈。

倒数就是:圈每秒 T=fpwm/2*Cnt   如果转为RPM乘上60即可。

如果是两对极 T=fpwm/4*Cnt   霍尔1,2,3会经历两次的N-S。多对极依次

 速度环的框图:

 

 dome:速度-电流PID

高级定时器T1(开启更新中断55us进入一次),定时器6(计时作用防止堵转)。ADC采集温度,电源电源电压,三相采样电流(力矩)。开启DMA。各采集50次求平均值。减小误差。

高级定时器.h 与定时器6.h 一起

#ifndef __BLDC_TIM_H
#define __BLDC_TIM_H

#include "./SYSTEM/sys/sys.h"

/******************************************************************************************/
/* 高级定时器 定义 */
extern TIM_HandleTypeDef g_atimx_handle;      /* 定时器x句柄 */
 /* TIMX PWM 定义 
 * 注意: 通过修改这几个宏定义, 可以支持TIM1/TIM8定时器
 */
#define ATIM_TIMX_PWM_CH1_GPIO_PORT            GPIOA
#define ATIM_TIMX_PWM_CH1_GPIO_PIN             GPIO_PIN_8
#define ATIM_TIMX_PWM_CH1_GPIO_CLK_ENABLE()    do{  __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)    /* PA口时钟使能 */

#define ATIM_TIMX_PWM_CH2_GPIO_PORT            GPIOA
#define ATIM_TIMX_PWM_CH2_GPIO_PIN             GPIO_PIN_9
#define ATIM_TIMX_PWM_CH2_GPIO_CLK_ENABLE()    do{  __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)    /* PA口时钟使能 */

#define ATIM_TIMX_PWM_CH3_GPIO_PORT            GPIOA
#define ATIM_TIMX_PWM_CH3_GPIO_PIN             GPIO_PIN_10
#define ATIM_TIMX_PWM_CH3_GPIO_CLK_ENABLE()    do{  __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)    /* PA口时钟使能 */

/* 互补通道IO */
#define M1_LOW_SIDE_U_PORT                      GPIOB
#define M1_LOW_SIDE_U_PIN                       GPIO_PIN_13
#define M1_LOW_SIDE_U_GPIO_CLK_ENABLE()         do{  __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)    /* PB口时钟使能 */

#define M1_LOW_SIDE_V_PORT                      GPIOB
#define M1_LOW_SIDE_V_PIN                       GPIO_PIN_14
#define M1_LOW_SIDE_V_GPIO_CLK_ENABLE()         do{  __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)    /* PB口时钟使能 */

#define M1_LOW_SIDE_W_PORT                      GPIOB
#define M1_LOW_SIDE_W_PIN                       GPIO_PIN_15
#define M1_LOW_SIDE_W_GPIO_CLK_ENABLE()         do{  __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)    /* PB口时钟使能 */

#define ATIM_TIMX_PWM_CHY_GPIO_AF               GPIO_AF1_TIM1

#define ATIM_TIMX_PWM                           TIM1
#define ATIM_TIMX_PWM_IRQn                      TIM1_UP_TIM10_IRQn
#define ATIM_TIMX_PWM_IRQHandler                TIM1_UP_TIM10_IRQHandler
#define ATIM_TIMX_PWM_CH1                       TIM_CHANNEL_1                                   /* 通道1 */
#define ATIM_TIMX_PWM_CH2                       TIM_CHANNEL_2                                   /* 通道2 */
#define ATIM_TIMX_PWM_CH3                       TIM_CHANNEL_3                                   /* 通道3 */
#define ATIM_TIMX_PWM_CHY_CLK_ENABLE()          do{ __HAL_RCC_TIM1_CLK_ENABLE(); }while(0)      /* TIM1 时钟使能 */


/******************************************************************************************/
/* 基本定时器 定义 */

/* TIMX 中断定义 
 * 默认是针对TIM6
 */
 
#define BTIM_TIMX_INT                           TIM6
#define BTIM_TIMX_INT_IRQn                      TIM6_DAC_IRQn
#define BTIM_TIMX_INT_IRQHandler                TIM6_DAC_IRQHandler
#define BTIM_TIMX_INT_CLK_ENABLE()              do{ __HAL_RCC_TIM6_CLK_ENABLE(); }while(0)      /* TIM6 时钟使能 */

extern TIM_HandleTypeDef g_atimx_handle;                                                        /* 定时器x句柄 */
/******************************************************************************************/

void atim_timx_oc_chy_init(uint16_t arr, uint16_t psc);                                         /* 高级定时器 PWM初始化函数 */
void btim_timx_int_init(uint16_t arr, uint16_t psc);                                            /* 基本定时器中断初始化 */

#endif

高级定时器.c与定时器6.c 一起 

#include "./BSP/TIMER/bldc_tim.h"
#include "./BSP/LED/led.h"
#include "./BSP/BLDC/bldc.h"
#include "./BSP/PID/pid.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/ADC/adc.h"
#include "./DEBUG/debug.h"

/******************************** 定时器配置句柄 定义 ***********************************/

TIM_HandleTypeDef g_atimx_handle;           /* 定时器x句柄 */
TIM_OC_InitTypeDef g_atimx_oc_chy_handle;   /* 定时器输出句柄 */

/******************************** 定义全局变量 ************************************/

extern _bldc_obj g_bldc_motor1;
extern PID_TypeDef  g_speed_pid;            /* 位置PID参数结构体 */

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

/**
 * @brief       高级定时器TIMX PWM 初始化函数
 * @note
 *              高级定时器的时钟来自APB2, 而PCLK2 = 168Mhz, 我们设置PPRE2不分频, 因此
 *              高级定时器时钟 = 168Mhz
 *              定时器溢出时间计算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us.
 *              Ft=定时器工作频率,单位:Mhz
 *
 * @param       arr: 自动重装值
 * @param       psc: 时钟预分频数
 * @retval      无
 */
void atim_timx_oc_chy_init(uint16_t arr, uint16_t psc)
{
    ATIM_TIMX_PWM_CHY_CLK_ENABLE();                             /* TIMX 时钟使能 */


    g_atimx_handle.Instance = ATIM_TIMX_PWM;                    /* 定时器x */
    g_atimx_handle.Init.Prescaler = psc;                        /* 定时器分频 */
    g_atimx_handle.Init.CounterMode = TIM_COUNTERMODE_UP;       /* 向上计数模式 */
    g_atimx_handle.Init.Period = arr;                           /* 自动重装载值 */
    g_atimx_handle.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;   /* 分频因子 */
    g_atimx_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; /*使能TIMx_ARR进行缓冲*/
    g_atimx_handle.Init.RepetitionCounter = 0;                  /* 开始时不计数*/
    HAL_TIM_PWM_Init(&g_atimx_handle);                          /* 初始化PWM */

    g_atimx_oc_chy_handle.OCMode = TIM_OCMODE_PWM1;             /* 模式选择PWM1 */
    g_atimx_oc_chy_handle.Pulse = 0;
    g_atimx_oc_chy_handle.OCPolarity = TIM_OCPOLARITY_HIGH;     /* 输出比较极性为高 */
    g_atimx_oc_chy_handle.OCNPolarity = TIM_OCNPOLARITY_HIGH;
    g_atimx_oc_chy_handle.OCFastMode = TIM_OCFAST_DISABLE;
    g_atimx_oc_chy_handle.OCIdleState = TIM_OCIDLESTATE_RESET;
    g_atimx_oc_chy_handle.OCNIdleState = TIM_OCNIDLESTATE_RESET;
    HAL_TIM_PWM_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH1); /* 配置TIMx通道y */
    HAL_TIM_PWM_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH2); /* 配置TIMx通道y */
    HAL_TIM_PWM_ConfigChannel(&g_atimx_handle, &g_atimx_oc_chy_handle, ATIM_TIMX_PWM_CH3); /* 配置TIMx通道y */
    
    /* 开启定时器通道1输出PWM */
    HAL_TIM_PWM_Start(&g_atimx_handle,TIM_CHANNEL_1);

    /* 开启定时器通道2输出PWM */
    HAL_TIM_PWM_Start(&g_atimx_handle,TIM_CHANNEL_2);

    /* 开启定时器通道3输出PWM */
    HAL_TIM_PWM_Start(&g_atimx_handle,TIM_CHANNEL_3);

    HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 2, 2);
    HAL_NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);

    HAL_TIM_Base_Start_IT(&g_atimx_handle);                         /* 启动高级定时器1 */
}


/**
 * @brief       定时器底层驱动,时钟使能,引脚配置
                此函数会被HAL_TIM_PWM_Init()调用
 * @param       htim:定时器句柄
 * @retval      无
 */
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == ATIM_TIMX_PWM)
    {
        GPIO_InitTypeDef gpio_init_struct;
        ATIM_TIMX_PWM_CHY_CLK_ENABLE();                             /* 开启通道y的IO时钟 */
        /* 三个上桥臂对应IO时钟使能 */
        ATIM_TIMX_PWM_CH1_GPIO_CLK_ENABLE();                        /* IO时钟使能 */
        ATIM_TIMX_PWM_CH2_GPIO_CLK_ENABLE();                        /* IO时钟使能 */
        ATIM_TIMX_PWM_CH3_GPIO_CLK_ENABLE();                        /* IO时钟使能 */
        /* 三个下桥臂对应IO时钟使能 */
        M1_LOW_SIDE_U_GPIO_CLK_ENABLE();                            /* IO时钟使能 */
        M1_LOW_SIDE_V_GPIO_CLK_ENABLE();                            /* IO时钟使能 */
        M1_LOW_SIDE_W_GPIO_CLK_ENABLE();                            /* IO时钟使能 */

        /* UVW_LOW的IO初始化 */
        gpio_init_struct.Pin = M1_LOW_SIDE_U_PIN;
        gpio_init_struct.Pull = GPIO_NOPULL;
        gpio_init_struct.Speed = GPIO_SPEED_HIGH;
        gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;                /* 推挽输出模式 */
        HAL_GPIO_Init(M1_LOW_SIDE_U_PORT, &gpio_init_struct);

        gpio_init_struct.Pin = M1_LOW_SIDE_V_PIN;
        HAL_GPIO_Init(M1_LOW_SIDE_V_PORT, &gpio_init_struct);

        gpio_init_struct.Pin = M1_LOW_SIDE_W_PIN;
        HAL_GPIO_Init(M1_LOW_SIDE_W_PORT, &gpio_init_struct);


        /*定时器IO初始化*/
        gpio_init_struct.Pin = ATIM_TIMX_PWM_CH1_GPIO_PIN;          /* 通道y的IO口 */
        gpio_init_struct.Mode = GPIO_MODE_AF_PP;                    /* 复用推挽输出 */
        gpio_init_struct.Pull = GPIO_NOPULL;                        /* 上拉 */
        gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;              /* 高速 */
        gpio_init_struct.Alternate = ATIM_TIMX_PWM_CHY_GPIO_AF;     /* 端口复用 */
        HAL_GPIO_Init(ATIM_TIMX_PWM_CH1_GPIO_PORT, &gpio_init_struct);

        gpio_init_struct.Pin = ATIM_TIMX_PWM_CH2_GPIO_PIN;    
        HAL_GPIO_Init(ATIM_TIMX_PWM_CH2_GPIO_PORT, &gpio_init_struct);

        gpio_init_struct.Pin = ATIM_TIMX_PWM_CH3_GPIO_PIN;       
        HAL_GPIO_Init(ATIM_TIMX_PWM_CH3_GPIO_PORT, &gpio_init_struct);
    }
}
/**
 * @brief       高级定时器TIMX中断服务函数
 * @param       无
 * @retval      无
 */
void ATIM_TIMX_PWM_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&g_atimx_handle);
}

/******************************************基本定时器初始化**********************************************************/
TIM_HandleTypeDef timx_handler;         /* 定时器参数句柄 */


/**
 * @brief       基本定时器TIMX定时中断初始化函数
 * @note
 *              基本定时器的时钟来自APB1,当PPRE1 ≥ 2分频的时候
 *              基本定时器的时钟为APB1时钟的2倍, 而APB1为42 所以定时器时钟 = 84MHZ
 *              定时器溢出时间计算方法: Tout = ((arr + 1) * (psc + 1)) / Ft us.
 *              Ft=定时器工作频率,单位:Mhz
 *
 * @param       arr: 自动重装值。
 * @param       psc: 时钟预分频数
 * @retval      无
 */
void btim_timx_int_init(uint16_t arr, uint16_t psc)
{
    timx_handler.Instance = BTIM_TIMX_INT;                      /* 基本定时器X */
    timx_handler.Init.Prescaler = psc;                          /* 设置预分频器  */
    timx_handler.Init.CounterMode = TIM_COUNTERMODE_UP;         /* 向上计数器 */
    timx_handler.Init.Period = arr;                             /* 自动装载值 */
    timx_handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;   /* 时钟分频因子 */
    HAL_TIM_Base_Init(&timx_handler);

    HAL_TIM_Base_Start_IT(&timx_handler);                       /* 使能通用定时器x和及其更新中断:TIM_IT_UPDATE */
    __HAL_TIM_CLEAR_IT(&timx_handler,TIM_IT_UPDATE);            /* 清除更新中断标志位 */
}

/**
 * @brief       定时器底册驱动,开启时钟,设置中断优先级
                此函数会被HAL_TIM_Base_Init()函数调用
 * @param       无
 * @retval      无
 */
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == BTIM_TIMX_INT)
    {
        BTIM_TIMX_INT_CLK_ENABLE();                     /* 使能TIM时钟*/
        HAL_NVIC_SetPriority(BTIM_TIMX_INT_IRQn, 1, 3); /* 抢占1,子优先级3,组2 */
        HAL_NVIC_EnableIRQ(BTIM_TIMX_INT_IRQn);         /* 开启ITM3中断 */
    }
}

/**
 * @brief       基本定时器TIMX中断服务函数
 * @param       无
 * @retval      无
 */
void BTIM_TIMX_INT_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&timx_handler);  /*定时器回调函数*/
}


/***********************************************定时器中断回调函数***********************************************/
static uint8_t pid_s_count = 0;         /* 速度环运行标志 */
static uint8_t pid_c_count = 0;         /* 电流环运行标志 */
static uint8_t cf_count = 0;            /* 定时器时间记录 */
int32_t temp_pwm1 = 0;                  /* 存放速度环的PID计算结果 */
int32_t temp_pwm2 = 0;                  /* 存放电流环的PID计算结果 */

/* 将PID期望值进行一阶滤波后存放至以下变量 */
int32_t motor_pwm_s = 0;
int32_t motor_pwm_c = 0;
int32_t motor_pwm_sl= 0;

/* 停机状态下电流采集使用 */
#define ADC_AMP_OFFSET_TIMES 50    
uint16_t adc_amp_offset[3][ADC_AMP_OFFSET_TIMES+1];
uint8_t adc_amp_offset_p = 0;
int16_t adc_amp[3];
volatile uint16_t adc_val_m1[ADC_CH_NUM];
int16_t adc_amp_un[3];
float adc_amp_bus = 0.0f;

float debug_data_temp = 0.0f;
float *user_setpoint = (float*)(&g_speed_pid.SetPoint); /* 目标值赋值 */
uint8_t clc = 0;                                        /* 等待时间进入堵塞控制时间 */
/**
 * @brief       定时器中断回调
 * @param       无
 * @retval      无
 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    uint8_t i;
    uint8_t bldc_dir=0;
    static uint8_t times_count=0;                       /* 定时器时间记录 */
    int16_t temp_speed=0;                               /* 临时速度存储 */
    if(htim->Instance == ATIM_TIMX_PWM)                 /* 55us */
    {
        if(g_bldc_motor1.run_flag == RUN)
        {
            /******************************* 三相电流计算 *******************************/
            for(i=0; i<3; i++)
            {
                adc_val_m1[i] = g_adc_val[i+2];         /* UVW三相ADC通道 */
                adc_amp[i] = adc_val_m1[i] - adc_amp_offset[i][ADC_AMP_OFFSET_TIMES];

               if(adc_amp[i] >= 0)                      /* 去除反电动势引起的负电流数据 */
               adc_amp_un[i] = adc_amp[i];
            }
            /* 运算母线电流(母线电流为任意两个有开关动作的相电流之和)*/
            if(g_bldc_motor1.step_sta == 0x05)
            {
                adc_amp_bus = (adc_amp_un[0] + adc_amp_un[1])*ADC2CURT; /* UV */
            }
            else if(g_bldc_motor1.step_sta == 0x01)
            {
                adc_amp_bus = (adc_amp_un[0] + adc_amp_un[2])*ADC2CURT; /* UW */
            }
            else if(g_bldc_motor1.step_sta == 0x03)
            {
                adc_amp_bus = (adc_amp_un[1]+ adc_amp_un[2])*ADC2CURT;  /* VW */
            }
            else if(g_bldc_motor1.step_sta == 0x02)
            {
                adc_amp_bus = (adc_amp_un[0]+ adc_amp_un[1])*ADC2CURT;  /* UV */
            }
            else if(g_bldc_motor1.step_sta == 0x06)
            {
                adc_amp_bus= (adc_amp_un[0]+ adc_amp_un[2])*ADC2CURT;   /* WU */
            }
            else if(g_bldc_motor1.step_sta == 0x04)
            {
                adc_amp_bus= (adc_amp_un[2]+ adc_amp_un[1])*ADC2CURT;   /* WV */
            }
            
            /******************************* 六步换向 *******************************/
            if(g_bldc_motor1.dir == CW)
            {
                g_bldc_motor1.step_sta = hallsensor_get_state(MOTOR_1);
            }
            else
            {
                g_bldc_motor1.step_sta = 7 - hallsensor_get_state(MOTOR_1);
            }
            if((g_bldc_motor1.step_sta <= 6)&&(g_bldc_motor1.step_sta >= 1))     
            {
                pfunclist_m1[g_bldc_motor1.step_sta-1]();
            }
            else    /* 编码器错误、接触不良、断开等情况 */
            {
                stop_motor1();
                g_bldc_motor1.run_flag = STOP;
            }
            /******************************* 速度计算 *******************************/
            g_bldc_motor1.count_j++;                /* 计算速度专用计数值 */
            g_bldc_motor1.hall_sta_edge = uemf_edge(g_bldc_motor1.hall_single_sta);
            if(g_bldc_motor1.hall_sta_edge == 0)    /* 统计单个霍尔信号的高电平时间 */
            {
                /* 计算速度 */
                if(g_bldc_motor1.dir == CW)
                    temp_speed = (SPEED_COEFF/g_bldc_motor1.count_j);
                else
                    temp_speed = -(SPEED_COEFF/g_bldc_motor1.count_j);
                FirstOrderRC_LPF(g_bldc_motor1.speed,temp_speed,0.2379);
                g_bldc_motor1.no_single = 0;
                g_bldc_motor1.count_j = 0;
            }
            if(g_bldc_motor1.hall_sta_edge == 1)
            {
                g_bldc_motor1.no_single = 0;
                g_bldc_motor1.count_j = 0;
            }
            if(g_bldc_motor1.hall_sta_edge == 2)            /* 霍尔值一直不变代表未换向 */
            {
                g_bldc_motor1.no_single++;                  /* 不换相时间累计 超时则判定速度为0 */
                if(g_bldc_motor1.no_single > 15000)
                {
                    g_bldc_motor1.no_single = 0;
                    g_bldc_motor1.speed = 0;                /* 超时换向 判定为停止 速度为0 */
                }
            }
            /******************************* 位置记录以及堵转标记 *******************************/
            if(g_bldc_motor1.step_last != g_bldc_motor1.step_sta)
            {
                g_bldc_motor1.hall_keep_t = 0;
                bldc_dir = check_hall_dir(&g_bldc_motor1);
                if(bldc_dir == CCW)
                {
                    g_bldc_motor1.pos -= 1;
                }
                else if(bldc_dir == CW)
                {
                    g_bldc_motor1.pos += 1;
                }
                g_bldc_motor1.step_last = g_bldc_motor1.step_sta;
            }
            else if(g_bldc_motor1.run_flag == RUN)          /* 运行且霍尔保持时 */
            {
                g_bldc_motor1.hall_keep_t++;                /* 换向一次所需计数值(时间) 单位1/18k */
                if(g_bldc_motor1.hall_keep_t > 15000)       /* 堵转 */
                {
                    g_bldc_motor1.hall_keep_t = 0;
#if LOCK_TAC
                    stop_motor1();
                    g_bldc_motor1.run_flag = STOP;;         /* 标记停机 */
                    g_bldc_motor1.pwm_duty = 0;
#endif
                    g_bldc_motor1.locked_rotor = 1;         /* 标记堵转 */
                }
            }
        /******************************* PID控制 *******************************/
        if(g_bldc_motor1.run_flag == RUN)                   /* 进入PID闭环控制 */
        {
            pid_c_count++;
            pid_s_count++;

            if(pid_s_count > 2)
            {
         /******************************* PID计算 *******************************/
                temp_pwm1 = increment_pid_ctrl(&g_speed_pid,g_bldc_motor1.speed); /* 速度环PID的控制 */
                FirstOrderRC_LPF(motor_pwm_s,temp_pwm1,0.085); /* 一阶 */
                if(motor_pwm_s < 0)
                {
                    motor_pwm_sl = -motor_pwm_s;
                }
                else
                {
                    motor_pwm_sl = motor_pwm_s;
                }

                *user_setpoint = debug_data_temp;   /* 重新保持上位机指令要求 */
                pid_s_count = 0;
            }

            if(pid_c_count > 1)                     /* 电流环 */
            {
                /* 换向尖峰电流大于设定的电流值将导致PID调节转至电流环调节 速度环无法起作用,转速无法调节 */
                if(adc_amp_bus > (g_current_pid.SetPoint - 20))
                {
                    cf_count++;                     /* 滤除换向尖峰电流的影响 */
                    if(cf_count > 4)
                    {
                        cf_count = 0;
                        temp_pwm2 = increment_pid_ctrl(&g_current_pid,adc_amp_bus); /* 电流环PID计算 */
                        FirstOrderRC_LPF(motor_pwm_c,temp_pwm2,0.085);/* 一阶数字滤波 滤波系数0.08 */
                    }
                }
                else
                {
                    cf_count = 0;
                    temp_pwm2 = increment_pid_ctrl(&g_current_pid,adc_amp_bus);
                    FirstOrderRC_LPF(motor_pwm_c,temp_pwm2,0.085);
                }
                pid_c_count = 0;
            }
            
            /* 电流环输出值大于速度环输出则使用速度环调节 */
            if(motor_pwm_c > motor_pwm_sl)
            {
                g_bldc_motor1.pwm_duty = motor_pwm_sl;
              
                if(motor_pwm_s < 0)                     /* 正反转积分控制 */
                    g_current_pid.Ui = -g_speed_pid.Ui; /* 速度环积分给电流环 */
                else
                    g_current_pid.Ui = g_speed_pid.Ui;
            }
            else  /* 速度环输出值大于电流环输出则使用电流环调节 */
            {
                g_bldc_motor1.pwm_duty = motor_pwm_c;
                if(motor_pwm_s < 0)
                    g_speed_pid.Ui = -g_current_pid.Ui;/* 电流环积分给速度环 */
                else
                    g_speed_pid.Ui = g_current_pid.Ui;
            }
        }
        }
    }
    if(htim->Instance == TIM6)
    {
        /******************************* 采集电机停机状态下的偏置电压 *******************************/
        times_count++;
        if(g_bldc_motor1.run_flag == STOP)
        {
            uint8_t i;
            uint32_t avg[3] = {0,0,0};
            adc_amp_offset[0][adc_amp_offset_p] = g_adc_val[2];     /* 得到还未开始运动时三相的基准电压 */
            adc_amp_offset[1][adc_amp_offset_p] = g_adc_val[3];
            adc_amp_offset[2][adc_amp_offset_p] = g_adc_val[4];

            adc_amp_offset_p++;
            NUM_CLEAR(adc_amp_offset_p,ADC_AMP_OFFSET_TIMES);       /* 最大采集ADC_AMP_OFFSET_TIMES次,超过即从0开始继续采集 */
            for(i = 0; i < ADC_AMP_OFFSET_TIMES; i++)               /* 将采集的每个通道值累加 */
            {
                avg[0] += adc_amp_offset[0][i];
                avg[1] += adc_amp_offset[1][i];
                avg[2] += adc_amp_offset[2][i];
            }
            for(i = 0; i < 3; i++)                                  /* 取平均即软件滤波 */
            {
                avg[i] /= ADC_AMP_OFFSET_TIMES;
                adc_amp_offset[i][ADC_AMP_OFFSET_TIMES] = avg[i];   /* 得到还未开始运动时的基准电压 */
            }
        }
        /******************************* 定时判断电机是否发生堵塞 *******************************/
        if(times_count == SMAPLSE_PID_SPEED)
        {
#if (LOCK_TAC == 2)
            if(g_bldc_motor1.locked_rotor == 1)         /* 堵转处理,当到达一定速度后可进入闭环控制 */
            {
                clc++;
                if(clc > 50)                            /* 延迟2s后重新启动 */
                {
#if DEBUG_ENABLE /*开启调试*/
                    debug_send_motorstate(RUN_STATE);   /* 电机运行*/
#endif
                    clc = 0;
                    pid_init();
                    stop_motor1();
                    g_speed_pid.SetPoint = 400.0;       /* 400PRM */
                    g_bldc_motor1.pwm_duty = 500;       /* 加速启动速度 */
                    g_bldc_motor1.run_flag = RUN;       /* 开启运行 */
                    start_motor1();                     /* 运行电机 */
                    g_bldc_motor1.locked_rotor = 0;
                }
            }
#endif
            times_count = 0;
        }

    }
}

 霍尔传感器.h

#ifndef __BLDC_H
#define __BLDC_H

#include "./SYSTEM/sys/sys.h"

/******************************************************************************************/
typedef struct 
{
    __IO uint8_t    run_flag;       /* 运行标志 */
    __IO uint8_t    locked_rotor;   /* 堵转标记 */     
    __IO uint8_t    step_sta;       /* 本次霍尔状态 */
    __IO uint8_t    hall_single_sta;/* 单个霍尔状态 */
    __IO uint8_t    hall_sta_edge;  /* 单个霍尔状态跳变 */
    __IO uint8_t    step_last;      /* 上次霍尔状态 */
    __IO uint8_t    dir;            /* 电机旋转方向 */
    __IO int32_t    pos;            /* 电机位置 */
    __IO int32_t    speed;          /* 电机速度 */
    __IO int16_t    current;        /* 电机速度 */
    __IO uint16_t   pwm_duty;       /* 电机占空比 */
    __IO uint32_t   hall_keep_t;    /* 霍尔保持时间 */
    __IO uint32_t   hall_pul_num;   /* 霍尔传感器脉冲数 */
    __IO uint32_t   lock_time;      /* 电机堵转时间 */
    __IO uint32_t   no_single;
    __IO uint32_t   count_j;
    __IO uint64_t   sum_pos;
} _bldc_obj;

/******************************************************************************************/
#define MOTOR_1                     1
#define MOTOR_2                     2


extern _bldc_obj g_bldc_motor1;
/********************************************************************************************/
/*刹车引脚*/
#define SHUTDOWN_PIN                      GPIO_PIN_10    
#define SHUTDOWN_PIN_GPIO                 GPIOF
#define SHUTDOWN_PIN_GPIO_CLK_ENABLE()    do{  __HAL_RCC_GPIOF_CLK_ENABLE(); }while(0)    /* PF口时钟使能 */

#define SHUTDOWN2_PIN                     GPIO_PIN_2    
#define SHUTDOWN2_PIN_GPIO                GPIOF
#define SHUTDOWN2_PIN_GPIO_CLK_ENABLE()   do{  __HAL_RCC_GPIOF_CLK_ENABLE(); }while(0)    /* PF口时钟使能 */

#define SHUTDOWN_EN                       HAL_GPIO_WritePin(SHUTDOWN_PIN_GPIO,SHUTDOWN_PIN,GPIO_PIN_SET);
#define SHUTDOWN_OFF                      HAL_GPIO_WritePin(SHUTDOWN_PIN_GPIO,SHUTDOWN_PIN,GPIO_PIN_RESET);


#define SHUTDOWN2_EN                      HAL_GPIO_WritePin(SHUTDOWN2_PIN_GPIO,SHUTDOWN2_PIN,GPIO_PIN_SET);
#define SHUTDOWN2_OFF                     HAL_GPIO_WritePin(SHUTDOWN2_PIN_GPIO,SHUTDOWN2_PIN,GPIO_PIN_RESET);

/******************************************************************************************/
/*霍尔传感器接口一*/

#define HALL1_TIM_CH1_PIN           GPIO_PIN_10     /* U */
#define HALL1_TIM_CH1_GPIO          GPIOH
#define HALL1_U_GPIO_CLK_ENABLE()   do{  __HAL_RCC_GPIOH_CLK_ENABLE(); }while(0)    /* PH口时钟使能 */

#define HALL1_TIM_CH2_PIN           GPIO_PIN_11     /* V */
#define HALL1_TIM_CH2_GPIO          GPIOH
#define HALL1_V_GPIO_CLK_ENABLE()   do{  __HAL_RCC_GPIOH_CLK_ENABLE(); }while(0)    /* PH口时钟使能 */

#define HALL1_TIM_CH3_PIN           GPIO_PIN_12     /* W */
#define HALL1_TIM_CH3_GPIO          GPIOH
#define HALL1_W_GPIO_CLK_ENABLE()   do{  __HAL_RCC_GPIOH_CLK_ENABLE(); }while(0)    /* PH口时钟使能 */

/*霍尔传感器接口二*/
#define HALL2_TIM_CH1_PIN           GPIO_PIN_12     /* U */
#define HALL2_TIM_CH1_GPIO          GPIOD
#define HALL2_U_GPIO_CLK_ENABLE()   do{  __HAL_RCC_GPIOD_CLK_ENABLE(); }while(0)    /* PD口时钟使能 */

#define HALL2_TIM_CH2_PIN           GPIO_PIN_13     /* V */
#define HALL2_TIM_CH2_GPIO          GPIOD
#define HALL2_V_GPIO_CLK_ENABLE()   do{  __HAL_RCC_GPIOD_CLK_ENABLE(); }while(0)    /* PD口时钟使能 */

#define HALL2_TIM_CH3_PIN           GPIO_PIN_8      /* W */
#define HALL2_TIM_CH3_GPIO          GPIOB
#define HALL2_W_GPIO_CLK_ENABLE()   do{  __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)    /* PB口时钟使能 */




/********************************************************************************************/
#define MAX_PWM_DUTY    (((168000/18) - 1)*0.96)

#define H_PWM_L_ON
#ifndef H_PWM_L_ON
#define H_PWM_L_PWM
#endif

#define CCW                         (1)                 /* 逆时针 */
#define CW                          (2)                 /* 顺时针 */
#define HALL_ERROR                  (0xF0)              /* 霍尔错误标志 */
#define RUN                         (1)                 /* 电机运动标志 */
#define STOP                        (0)                 /* 电机停机标志 */
#define LOCK_TAC                     2                  /* 堵转处理:2为开启,其他关闭 */

#define SPEED_COEFF      (uint32_t)((18000/4)*60)       /* 旋转一圈变化4个信号,2对级永磁体特性,NSNS共4级数*/

#define ADC2CURT    (float)(3.3f/4.096f/0.12f)
#define ADC2VBUS    (float)(3.3f*25/4096)

#define NUM_CLEAR(para,val)     {if(para >= val){para=0;}}
#define NUM_MAX_LIMIT(para,val) {if(para > val){para=val;}}
#define NUM_MIN_LIMIT(para,val) {if(para < val){para=val;}}

typedef void(*pctr) (void);

void stop_motor1(void);
void start_motor1(void);

#define FirstOrderRC_LPF(Yn_1,Xn,a) Yn_1 = (1-a)*Yn_1 + a*Xn;   /* Yn:out;Xn:in;a:系数 */
/******************************************************************************************/
/* 外部接口函数*/
void bldc_init(uint16_t arr, uint16_t psc);                     /* BLDC初始化 */
uint8_t check_hall_dir(_bldc_obj * obj);                        /* 检测电机旋转方向 */
extern pctr pfunclist_m1[6];                                    /* 六步换相函数指针数组 */
void bldc_ctrl(uint8_t motor_id,int32_t dir,float duty);        /* bldc控制函数 */
uint8_t uemf_edge(uint8_t val);                                 /* 波形状态检测 */
float get_temp(uint16_t para);                                  /* 获取温度值 */
void calc_adc_val(uint16_t * p);                                /* adc数据软件滤波函数 */
void hall_gpio_init(void);                                      /* 霍尔接口初始化 */
uint32_t hallsensor_get_state(uint8_t motor_id);                /* 获取霍尔状态 */
/* 六步换相 */
void m1_uhvl(void);
void m1_uhwl(void);
void m1_vhwl(void);
void m1_vhul(void);
void m1_whul(void);
void m1_whvl(void);

#endif

  霍尔传感器.C

 
#include "./BSP/BLDC/bldc.h"
#include "./BSP/TIMER/bldc_tim.h"
#include "./BSP/ADC/adc.h"
#include "math.h"

_bldc_obj g_bldc_motor1 = {STOP,0,0,CCW,0,0,0,0,0,0};   /* 电机结构体 */

const uint8_t hall_table_cw[6] = {6,2,3,1,5,4};         /* 顺时针旋转表 */
const uint8_t hall_table_ccw[6] = {5,1,3,2,6,4};        /* 逆时针旋转表 */

const uint8_t hall_cw_table[12] = {0x62,0x23,0x31,0x15,0x54,0x46,0x63,0x21,0x35,0x14,0x56,0x42};  /* 顺方向组合 */
const uint8_t hall_ccw_table[12] = {0x45,0x51,0x13,0x32,0x26,0x64,0x41,0x53,0x12,0x36,0x24,0x65}; /* 逆方向组合 */
/**
 * @brief       无刷电机初始化,包括定时器,霍尔接口以及SD引脚初始化
 * @param       arr: 自动重装值
 * @param       psc: 时钟预分频数
 * @retval      无
 */
void bldc_init(uint16_t arr, uint16_t psc)
{       
    GPIO_InitTypeDef gpio_init_struct;
    
    SHUTDOWN_PIN_GPIO_CLK_ENABLE();
    SHUTDOWN2_PIN_GPIO_CLK_ENABLE();
  
    gpio_init_struct.Pin = SHUTDOWN_PIN;
    gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
    gpio_init_struct.Pull = GPIO_NOPULL;
    gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(SHUTDOWN_PIN_GPIO, &gpio_init_struct);    
    
    gpio_init_struct.Pin = SHUTDOWN2_PIN;
    HAL_GPIO_Init(SHUTDOWN2_PIN_GPIO, &gpio_init_struct);  
    hall_gpio_init();             /* 霍尔接口初始化 */
    atim_timx_oc_chy_init(arr,  psc);
    btim_timx_int_init(1000 - 1 , 84 - 1);
}

/**
 * @brief       BLDC控制函数
 * @param       dir :电机方向, Duty:PWM占空比
 * @retval      无
 */
void bldc_ctrl(uint8_t motor_id,int32_t dir,float duty)
{
    if(motor_id == MOTOR_1)
    {
        g_bldc_motor1.dir = dir;            /* 方向 */
        g_bldc_motor1.pwm_duty = duty;      /* 占空比 */
    }
}
/**
 * @brief       旋转方向检测函数
 * @param       obj:电机控制句柄
 * @retval      旋转方向定义如下:
 *              正转,CW
 *              反转,CCW
 */
uint8_t check_hall_dir(_bldc_obj * obj)
{
    uint8_t temp,res = HALL_ERROR;
    if((obj->step_last <= 6)&&(obj->step_sta <= 6))
    {
        temp = ((obj->step_last & 0x0F) << 4)|(obj->step_sta & 0x0F);
        if((temp == hall_ccw_table[0])||(temp == hall_ccw_table[1])||\
                (temp == hall_ccw_table[2])||(temp == hall_ccw_table[3])||\
                (temp == hall_ccw_table[4])||(temp == hall_ccw_table[5]))
        {
            res  = CCW;
        }
        else if((temp == hall_cw_table[0])||(temp == hall_cw_table[1])||\
                (temp == hall_cw_table[2])||(temp == hall_cw_table[3])||\
                (temp == hall_cw_table[4])||(temp == hall_cw_table[5]))
        {
            res  = CW;
        }
    }
    return res;
}
/*****************************************************************************************/
/*霍尔接口初始化*/

/**
  * @brief  霍尔传感器定时器初始化
  * @param  无
  * @retval 无
  */
void hall_gpio_init(void)
{
    GPIO_InitTypeDef gpio_init_struct;
    HALL1_U_GPIO_CLK_ENABLE();
    HALL1_V_GPIO_CLK_ENABLE();
    HALL1_W_GPIO_CLK_ENABLE();

    HALL2_U_GPIO_CLK_ENABLE();
    HALL2_V_GPIO_CLK_ENABLE();
    HALL2_W_GPIO_CLK_ENABLE();

    /* 霍尔通道 1 引脚初始化 */
    gpio_init_struct.Pin = HALL1_TIM_CH1_PIN;
    gpio_init_struct.Mode = GPIO_MODE_INPUT;
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(HALL1_TIM_CH1_GPIO, &gpio_init_struct);

    /* 霍尔通道 2 引脚初始化 */
    gpio_init_struct.Pin = HALL1_TIM_CH2_PIN;
    HAL_GPIO_Init(HALL1_TIM_CH2_GPIO, &gpio_init_struct);

    /* 霍尔通道 3 引脚初始化 */
    gpio_init_struct.Pin = HALL1_TIM_CH3_PIN;
    HAL_GPIO_Init(HALL1_TIM_CH3_GPIO, &gpio_init_struct);

}


/**
 * @brief       获取霍尔传感器引脚状态
 * @param       无
 * @retval      霍尔传感器引脚状态
 */
uint32_t hallsensor_get_state(uint8_t motor_id)
{
    __IO static uint32_t State ;
    State  = 0;
    if(motor_id == MOTOR_1)
    {
        if(HAL_GPIO_ReadPin(HALL1_TIM_CH1_GPIO,HALL1_TIM_CH1_PIN) != GPIO_PIN_RESET)  /* 霍尔传感器状态获取 */
        {
            State |= 0x01U;
        }
        if(HAL_GPIO_ReadPin(HALL1_TIM_CH2_GPIO,HALL1_TIM_CH2_PIN) != GPIO_PIN_RESET)  /* 霍尔传感器状态获取 */
        {
            State |= 0x02U;
        }
        if(HAL_GPIO_ReadPin(HALL1_TIM_CH3_GPIO,HALL1_TIM_CH3_PIN) != GPIO_PIN_RESET)  /* 霍尔传感器状态获取 */
        {
            State |= 0x04U;
            g_bldc_motor1.hall_single_sta=1;
        }
        else
            g_bldc_motor1.hall_single_sta=0;
    }
    return State;
}

/************************************* BLDC相关函数 *************************************/
/* 关闭电机运转 */
void stop_motor1(void)
{
    /* 关闭半桥芯片输出 */
    SHUTDOWN_OFF;
    /* 关闭PWM输出 */
    HAL_TIM_PWM_Stop(&g_atimx_handle,TIM_CHANNEL_1);
    HAL_TIM_PWM_Stop(&g_atimx_handle,TIM_CHANNEL_2);
    HAL_TIM_PWM_Stop(&g_atimx_handle,TIM_CHANNEL_3);
    /* 上下桥臂全部关断 */
    g_atimx_handle.Instance->CCR2 = 0;
    g_atimx_handle.Instance->CCR1 = 0;
    g_atimx_handle.Instance->CCR3 = 0;
    HAL_GPIO_WritePin(M1_LOW_SIDE_U_PORT,M1_LOW_SIDE_U_PIN,GPIO_PIN_RESET);
    HAL_GPIO_WritePin(M1_LOW_SIDE_V_PORT,M1_LOW_SIDE_V_PIN,GPIO_PIN_RESET);
    HAL_GPIO_WritePin(M1_LOW_SIDE_W_PORT,M1_LOW_SIDE_W_PIN,GPIO_PIN_RESET);
}

/* 开启电机运转 */
void start_motor1(void)
{
    SHUTDOWN_EN;
    /* 使能PWM输出 */
    HAL_TIM_PWM_Start(&g_atimx_handle,TIM_CHANNEL_1);
    HAL_TIM_PWM_Start(&g_atimx_handle,TIM_CHANNEL_2);
    HAL_TIM_PWM_Start(&g_atimx_handle,TIM_CHANNEL_3);
}

/*****************************************************************************************/
/*  六步换向函数指针 */
pctr pfunclist_m1[6] =
{
    &m1_uhwl, &m1_vhul, &m1_vhwl,
    &m1_whvl, &m1_uhvl, &m1_whul
};

/* 上下桥臂的导通情况,共6种,也称为6步换向 */
void m1_uhvl(void)
{
    g_atimx_handle.Instance->CCR2 = 0;
    g_atimx_handle.Instance->CCR1 = g_bldc_motor1.pwm_duty;                 /* U相上桥臂PWM */
    g_atimx_handle.Instance->CCR3 = 0;
    HAL_GPIO_WritePin(M1_LOW_SIDE_V_PORT,M1_LOW_SIDE_V_PIN,GPIO_PIN_SET);   /* V相下桥臂导通 */
    HAL_GPIO_WritePin(M1_LOW_SIDE_U_PORT,M1_LOW_SIDE_U_PIN,GPIO_PIN_RESET); /* U相下桥臂关闭 */
    HAL_GPIO_WritePin(M1_LOW_SIDE_W_PORT,M1_LOW_SIDE_W_PIN,GPIO_PIN_RESET); /* W相下桥臂关闭 */
}

void m1_uhwl(void)
{
    g_atimx_handle.Instance->CCR2 = 0;
    g_atimx_handle.Instance->CCR1 = g_bldc_motor1.pwm_duty;
    g_atimx_handle.Instance->CCR3 = 0;
    HAL_GPIO_WritePin(M1_LOW_SIDE_W_PORT,M1_LOW_SIDE_W_PIN,GPIO_PIN_SET);
    HAL_GPIO_WritePin(M1_LOW_SIDE_U_PORT,M1_LOW_SIDE_U_PIN,GPIO_PIN_RESET);
    HAL_GPIO_WritePin(M1_LOW_SIDE_V_PORT,M1_LOW_SIDE_V_PIN,GPIO_PIN_RESET);
}

void m1_vhwl(void)
{
    g_atimx_handle.Instance->CCR1=0;
    g_atimx_handle.Instance->CCR2 = g_bldc_motor1.pwm_duty;
    g_atimx_handle.Instance->CCR3=0;
    HAL_GPIO_WritePin(M1_LOW_SIDE_W_PORT,M1_LOW_SIDE_W_PIN,GPIO_PIN_SET);
    HAL_GPIO_WritePin(M1_LOW_SIDE_U_PORT,M1_LOW_SIDE_U_PIN,GPIO_PIN_RESET);
    HAL_GPIO_WritePin(M1_LOW_SIDE_V_PORT,M1_LOW_SIDE_V_PIN,GPIO_PIN_RESET);
}

void m1_vhul(void)
{
    g_atimx_handle.Instance->CCR1 = 0;
    g_atimx_handle.Instance->CCR2 = g_bldc_motor1.pwm_duty;
    g_atimx_handle.Instance->CCR3 = 0;
    HAL_GPIO_WritePin(M1_LOW_SIDE_U_PORT,M1_LOW_SIDE_U_PIN,GPIO_PIN_SET);
    HAL_GPIO_WritePin(M1_LOW_SIDE_V_PORT,M1_LOW_SIDE_V_PIN,GPIO_PIN_RESET);
    HAL_GPIO_WritePin(M1_LOW_SIDE_W_PORT,M1_LOW_SIDE_W_PIN,GPIO_PIN_RESET);
}


void m1_whul(void)
{
    g_atimx_handle.Instance->CCR2 = 0;
    g_atimx_handle.Instance->CCR3 = g_bldc_motor1.pwm_duty;
    g_atimx_handle.Instance->CCR1 = 0;
    HAL_GPIO_WritePin(M1_LOW_SIDE_U_PORT,M1_LOW_SIDE_U_PIN,GPIO_PIN_SET);
    HAL_GPIO_WritePin(M1_LOW_SIDE_V_PORT,M1_LOW_SIDE_V_PIN,GPIO_PIN_RESET);
    HAL_GPIO_WritePin(M1_LOW_SIDE_W_PORT,M1_LOW_SIDE_W_PIN,GPIO_PIN_RESET);
}

void m1_whvl(void)
{
    g_atimx_handle.Instance->CCR2 = 0;
    g_atimx_handle.Instance->CCR3 = g_bldc_motor1.pwm_duty;
    g_atimx_handle.Instance->CCR1 = 0;
    HAL_GPIO_WritePin(M1_LOW_SIDE_V_PORT,M1_LOW_SIDE_V_PIN,GPIO_PIN_SET);
    HAL_GPIO_WritePin(M1_LOW_SIDE_U_PORT,M1_LOW_SIDE_U_PIN,GPIO_PIN_RESET);
    HAL_GPIO_WritePin(M1_LOW_SIDE_W_PORT,M1_LOW_SIDE_W_PIN,GPIO_PIN_RESET);
}

/**
 * @brief       检测输入信号是否发生变化
 * @param       val :输入信号
 * @note        测量速度使用,获取输入信号状态翻转情况,计算速度
 * @retval      0:计算高电平时间,1:计算低电平时间,2:信号未改变
 */
uint8_t uemf_edge(uint8_t val)
{
    /* 主要是检测val信号从0 - 1 在从 1 - 0的过程,即高电平所持续的过程 */
    static uint8_t oldval=0;
    if(oldval != val)
    {
        oldval = val;
        if(val == 0) return 0;
        else return 1;
    }
    return 2;
}

/*************************************    第二部分    电压电流温度采集    **********************************************/
/*
    Rt = Rp *exp(B*(1/T1-1/T2))

    Rt 是热敏电阻在T1温度下的阻值;
    Rp是热敏电阻在T2常温下的标称阻值;
    exp是e的n次方,e是自然常数,就是自然对数的底数,近似等于 2.7182818;
    B值是热敏电阻的重要参数,教程中用到的热敏电阻B值为3380;
    这里T1和T2指的是开尔文温度,T2是常温25℃,即(273.15+25)K
    T1就是所求的温度
*/
const float Rp = 10000.0f;          /* 10K */
const float T2 = (273.15f + 25.0f); /* T2 */
const float Bx = 3380.0f;           /* B */
const float Ka = 273.15f;

/**
 * @brief       计算温度值
 * @param       para: 温度采集对应ADC通道的值(已滤波)
 * @note        计算温度分为两步:
                1.根据ADC采集到的值计算当前对应的Rt
                2.根据Rt计算对应的温度值
 * @retval      温度值
 */
float get_temp(uint16_t para)
{
    float Rt;
    float temp;
    Rt = 3.3f / (para * 3.3f / 4096.0f / 4700.0f) - 4700.0f;
    /* like this R=5000, T2=273.15+25,B=3470, RT=5000*EXP(3470*(1/T1-1/(273.15+25)) */
    temp = Rt / Rp;
    temp = log(temp);       /* ln(Rt/Rp) */
    temp /= Bx;             /* ln(Rt/Rp)/B */
    temp += (1.0f / T2);
    temp = 1.0f / (temp);
    temp -= Ka;
    return temp;
}

extern uint16_t g_adc_value[ADC_CH_NUM * ADC_COLL];
/**
 * @brief       计算ADC的平均值(滤波)
 * @param       * p :存放ADC值的指针地址
 * @note        此函数对电压、温度、电流对应的ADC值进行滤波
 * @retval      无
 */
void calc_adc_val(uint16_t * p)
{
    uint32_t temp[ADC_CH_NUM] = {0,0,0};             /* 定义一个缓存数组 */
    int i,j;                                         /* 循环采集ADC_COLL次数 */
    for(i=0;i<ADC_COLL;i++)                          /* 根据ADC通道数循环获取,并累加 */
    {
        for(j=0;j<ADC_CH_NUM;j++)                    /* 将采集到的ADC值,各通道进行累加 */
        {
            temp[j] += g_adc_value[j+i*ADC_CH_NUM];
        }
    }
    for(j=0;j<ADC_CH_NUM;j++)
    {
        temp[j] /= ADC_COLL;                         /* 获取平均值 */
        p[j] = temp[j];                              /* 存到*p */
    }
}

ADC.h

#ifndef __ADC_H
#define __ADC_H

#include "./SYSTEM/sys/sys.h"


/******************************************************************************************/
/* ADC及引脚 定义 */

#define ADC_ADCX_CH0_GPIO_PORT              GPIOB                                               /* 电源电压采集引脚 */
#define ADC_ADCX_CH0_GPIO_PIN               GPIO_PIN_1
#define ADC_ADCX_CH0_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)

#define ADC_ADCX_CH1_GPIO_PORT              GPIOA                                               /* 温度采集引脚 */
#define ADC_ADCX_CH1_GPIO_PIN               GPIO_PIN_0
#define ADC_ADCX_CH1_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)

#define ADC_ADCX_CH2_GPIO_PORT              GPIOB                                               /* U相采集引脚 */
#define ADC_ADCX_CH2_GPIO_PIN               GPIO_PIN_0
#define ADC_ADCX_CH2_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)

#define ADC_ADCX_CH3_GPIO_PORT              GPIOA                                               /* V相采集引脚 */
#define ADC_ADCX_CH3_GPIO_PIN               GPIO_PIN_6
#define ADC_ADCX_CH3_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)

#define ADC_ADCX_CH4_GPIO_PORT              GPIOA                                               /* W相采集引脚 */
#define ADC_ADCX_CH4_GPIO_PIN               GPIO_PIN_3
#define ADC_ADCX_CH4_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)

#define ADC_ADCX                            ADC1 
#define ADC_ADCX_CH0                        ADC_CHANNEL_9                                       /* 通道Y,  0 <= Y <= 17 */ 
#define ADC_ADCX_CH1                        ADC_CHANNEL_0
#define ADC_ADCX_CH2                        ADC_CHANNEL_8
#define ADC_ADCX_CH3                        ADC_CHANNEL_6
#define ADC_ADCX_CH4                        ADC_CHANNEL_3

#define ADC_ADCX_CHY_CLK_ENABLE()           do{ __HAL_RCC_ADC1_CLK_ENABLE(); }while(0)          /* ADC1 时钟使能 */

#define ADC_CH_NUM                          5                                                   /* 需要转换的通道数目 */
#define ADC_COLL                            50                                                  /* 单采集次数 */
#define ADC_SUM                             ADC_CH_NUM * ADC_COLL                               /* 总采集次数 */

/* ADC单通道/多通道 DMA采集 DMA数据流相关 定义
 * 注意: 这里我们的通道还是使用上面的定义.
 */
#define ADC_ADCX_DMASx                      DMA2_Stream4
#define ADC_ADCX_DMASx_Chanel               DMA_CHANNEL_0                                       /* ADC1_DMA请求源 */
#define ADC_ADCX_DMASx_IRQn                 DMA2_Stream4_IRQn
#define ADC_ADCX_DMASx_IRQHandler           DMA2_Stream4_IRQHandler

extern uint16_t g_adc_val[ADC_CH_NUM];


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

void adc_init(void);                                                                            /* ADC初始化 */
uint32_t adc_get_result_average(uint8_t ch);                                                    /* 获得某个通道值  */
void adc_nch_dma_init(void);

#endif 

 ADC.c


#include "./BSP/ADC/adc.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/DMA/dma.h"
#include "./BSP/BLDC/bldc.h"
#include "./BSP/TIMER/bldc_tim.h"

/* 多通道ADC采集 DMA读取 */
ADC_HandleTypeDef g_adc_nch_dma_handle;     /* 与DMA关联的ADC句柄 */
DMA_HandleTypeDef g_dma_nch_adc_handle;     /* 与ADC关联的DMA句柄 */
uint8_t g_adc_dma_sta = 0;                  /* DMA传输状态标志, 0,未完成; 1, 已完成 */

uint16_t g_adc_value[ADC_CH_NUM * ADC_COLL] = {0};     /* 存储ADC原始值 */
float g_adc_u_value[ADC_CH_NUM] = {0};      /* 存储ADC转换后的电压值 */

/***************************************多通道ADC采集(DMA读取)程序*****************************************/


/**
 * @brief       ADC初始化
 * @param       无
 * @retval      无
 */
void adc_init(void)
{
    ADC_ChannelConfTypeDef sConfig = {0};

    g_adc_nch_dma_handle.Instance = ADC_ADCX;
    g_adc_nch_dma_handle.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;            /* 4分频,ADCCLK = PCLK2/4 = 84/4 = 21Mhz */
    g_adc_nch_dma_handle.Init.Resolution = ADC_RESOLUTION_12B;                      /* 12位模式 */
    g_adc_nch_dma_handle.Init.ScanConvMode = ENABLE;                                /* 扫描模式 多通道使用 */
    g_adc_nch_dma_handle.Init.ContinuousConvMode = ENABLE;                          /* 连续转换模式,转换完成之后接着继续转换 */
    g_adc_nch_dma_handle.Init.DiscontinuousConvMode = DISABLE;                      /* 禁止不连续采样模式 */
    g_adc_nch_dma_handle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; /* 使用软件触发 */
    g_adc_nch_dma_handle.Init.ExternalTrigConv = ADC_SOFTWARE_START;                /* 软件触发 */
    g_adc_nch_dma_handle.Init.DataAlign = ADC_DATAALIGN_RIGHT;                      /* 右对齐 */
    g_adc_nch_dma_handle.Init.NbrOfConversion = ADC_CH_NUM;                         /* 使用转换通道数,需根据实际转换通道去设置 */
    g_adc_nch_dma_handle.Init.DMAContinuousRequests = ENABLE;                       /* 开启DMA连续转换 */
    g_adc_nch_dma_handle.Init.EOCSelection = ADC_EOC_SEQ_CONV;
    HAL_ADC_Init(&g_adc_nch_dma_handle);

    /* 配置使用的ADC通道,采样序列里的第几个转换,增加或者减少通道需要修改这部分 */
    sConfig.Channel = ADC_ADCX_CH0;                         /* 电源电压采集 */
    sConfig.Rank = 1;
    sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES;
    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &sConfig);

    sConfig.Channel = ADC_ADCX_CH1;                         /* 温度采集 */
    sConfig.Rank = 2;
    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &sConfig);

    sConfig.Channel = ADC_ADCX_CH2;                         /* U相电压采集 */
    sConfig.Rank = 3;
    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &sConfig);
    
    sConfig.Channel = ADC_ADCX_CH3;                         /* V相电压采集 */
    sConfig.Rank = 4;
    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &sConfig);
    
    sConfig.Channel = ADC_ADCX_CH4;                         /* W相电压采集 */
    sConfig.Rank = 5;
    HAL_ADC_ConfigChannel(&g_adc_nch_dma_handle, &sConfig);
    
}

/**
 * @brief       ADC DMA读取 初始化函数
 *   @note      本函数还是使用adc_init对ADC进行大部分配置,有差异的地方再单独配置
 * @param       par         : 外设地址
 * @param       mar         : 存储器地址
 * @retval      无
 */
void adc_nch_dma_init(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
      
    ADC_ADCX_CHY_CLK_ENABLE();           /* 使能ADCx时钟 */
    ADC_ADCX_CH0_GPIO_CLK_ENABLE();      /* 开启GPIO时钟 */
    ADC_ADCX_CH1_GPIO_CLK_ENABLE();
    ADC_ADCX_CH2_GPIO_CLK_ENABLE();
    ADC_ADCX_CH3_GPIO_CLK_ENABLE();
    ADC_ADCX_CH4_GPIO_CLK_ENABLE();
    
    /* AD采集引脚模式设置,模拟输入 */
    GPIO_InitStruct.Pin = ADC_ADCX_CH0_GPIO_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(ADC_ADCX_CH0_GPIO_PORT, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = ADC_ADCX_CH1_GPIO_PIN;
    HAL_GPIO_Init(ADC_ADCX_CH1_GPIO_PORT, &GPIO_InitStruct);
    
    GPIO_InitStruct.Pin = ADC_ADCX_CH2_GPIO_PIN;   
    HAL_GPIO_Init(ADC_ADCX_CH2_GPIO_PORT, &GPIO_InitStruct); 
    
    GPIO_InitStruct.Pin = ADC_ADCX_CH3_GPIO_PIN;   
    HAL_GPIO_Init(ADC_ADCX_CH3_GPIO_PORT, &GPIO_InitStruct); 
    
    GPIO_InitStruct.Pin = ADC_ADCX_CH4_GPIO_PIN;   
    HAL_GPIO_Init(ADC_ADCX_CH4_GPIO_PORT, &GPIO_InitStruct); 
    
    adc_init();
    
    if ((uint32_t)ADC_ADCX_DMASx > (uint32_t)DMA2)                              /* 大于DMA1_Channel7, 则为DMA2的通道了 */
    {
        __HAL_RCC_DMA2_CLK_ENABLE();                                            /* DMA2时钟使能 */
    }
    else 
    {
        __HAL_RCC_DMA1_CLK_ENABLE();                                            /* DMA1时钟使能 */
    }

    /* DMA配置 */
    g_dma_nch_adc_handle.Instance = ADC_ADCX_DMASx;                             /* 设置DMA通道 */
    g_dma_nch_adc_handle.Init.Channel = DMA_CHANNEL_0;
    g_dma_nch_adc_handle.Init.Direction = DMA_PERIPH_TO_MEMORY;                 /* DIR = 1 ,  外设到存储器模式 */
    g_dma_nch_adc_handle.Init.PeriphInc = DMA_PINC_DISABLE;                     /* 外设非增量模式 */
    g_dma_nch_adc_handle.Init.MemInc = DMA_MINC_ENABLE;                         /* 存储器增量模式 */
    g_dma_nch_adc_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;    /* 外设数据长度:16位 */
    g_dma_nch_adc_handle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;       /* 存储器数据长度:16位 */
    g_dma_nch_adc_handle.Init.Mode = DMA_CIRCULAR;                              /* 外设流控模式 */
    g_dma_nch_adc_handle.Init.Priority = DMA_PRIORITY_MEDIUM;                   /* 中等优先级 */
    HAL_DMA_Init(&g_dma_nch_adc_handle);
 
    __HAL_LINKDMA(&g_adc_nch_dma_handle,DMA_Handle,g_dma_nch_adc_handle);

    HAL_NVIC_SetPriority(ADC_ADCX_DMASx_IRQn, 2, 1);
    HAL_NVIC_EnableIRQ(ADC_ADCX_DMASx_IRQn);
    
    HAL_ADC_Start_DMA(&g_adc_nch_dma_handle,(uint32_t *)g_adc_value,ADC_CH_NUM * ADC_COLL);
}


/**
 * @brief       ADC DMA采集中断服务函数
 * @param       无 
 * @retval      无
 */
void ADC_ADCX_DMASx_IRQHandler(void)
{
    HAL_DMA_IRQHandler(&g_dma_nch_adc_handle);
}

uint16_t g_adc_val[ADC_CH_NUM];                     /* ADC平均值存放数组 */

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    if (hadc->Instance == ADC1)                     /* 大约2.6ms采集完成进入中断 */
    { 
        HAL_ADC_Stop_DMA(&g_adc_nch_dma_handle);    /* 关闭DMA转换 */
        calc_adc_val(g_adc_val);                    /* ADC数值转换 */
        HAL_ADC_Start_DMA(&g_adc_nch_dma_handle, (uint32_t *)&g_adc_value, (uint32_t)(ADC_SUM)); /* 再启动DMA转换 */
    }
}


/**
 * @brief       获取通道ch的转换值,取times次, 然后平均
 * @param       ch      : 通道号, 0~17
 * @retval      通道ch的times次转换结果平均值
 */
uint32_t adc_get_result_average(uint8_t ch)
{
    uint32_t temp_val = 0;
    uint16_t t;

    for (t = ch; t < ADC_SUM; t += ADC_CH_NUM )     /* 获取times次数据 */
    {
        temp_val += g_adc_value[t];
    }

    return temp_val / ADC_COLL;                     /* 返回平均值 */
}

 pid.h

#ifndef __PID_H
#define __PID_H

#include "./SYSTEM/sys/sys.h"

/************************************ PID相关参数 ****************************************/

#define  C_KP      2.00f            /* P参数 */
#define  C_KI      0.20f            /* I参数 */
#define  C_KD      0.01f            /* D参数 */

#define  S_KP      0.00800f         /* P参数 */
#define  S_KI      0.00025f         /* I参数 */
#define  S_KD      0.00020f         /* D参数 */

#define SMAPLSE_PID_SPEED  40       /* 采样率 单位ms */

/*PID结构体*/
typedef struct
{
    __IO float  SetPoint;           /* 设定目标 */
    __IO float  ActualValue;        /* 实际值 */
    __IO float  SumError;           /* 误差累计 */
    __IO float  Up;                 /* 比例项 */
    __IO float  Ui;                 /* 积分项 */
    __IO float  Ud;                 /* 微分项 */
    __IO float  Proportion;         /* 比例常数 P */
    __IO float  Integral;           /* 积分常数 I */
    __IO float  Derivative;         /* 微分常数 D */
    __IO float  Error;              /* Error[-1] */
    __IO float  LastError;          /* Error[-1] */
    __IO float  PrevError;          /* Error[-2] */
    __IO float  IngMin;
    __IO float  IngMax;
    __IO float  OutMin;
    __IO float  OutMax;
} PID_TypeDef;

#define LIMIT_OUT(var,max,min) {(var)=(var)>(max)?(max):(var);(var)=(var)<(min)?(min):(var);}

extern PID_TypeDef  g_current_pid;  /* 电流PID参数结构体 */
extern PID_TypeDef  g_speed_pid;    /* 速度PID参数结构体 */

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

void pid_init(void);                /* PID初始化函数 */
int32_t increment_pid_ctrl(PID_TypeDef *PID,float Feedback_value); /* PID控制算法 */

#endif

pid.c

#include "./BSP/PID/pid.h"
#include "./BSP/BLDC/bldc.h"

PID_TypeDef  g_current_pid;             /* 电流PID参数结构体 */
PID_TypeDef  g_speed_pid;               /* 速度PID参数结构体 */
/**
 * @brief       初始化PID
 * @param       无
 * @retval      无
 */
void pid_init(void)
{
    /* 设定电流目标1500mA(空载最小电流400mA左右)较高的转速对应的电流较大,力矩较大,可适应较高的转速调节*/
    /* 【注意】如设置的转速对应的电流超过了电流设定值,将导致PID转至电流环调节,转速将无法继续提升 */
    g_current_pid.SetPoint = 1500.0;
    g_current_pid.ActualValue = 0.0;    /* 设定目标Desired Value */
    g_current_pid.LastError = 0.0;      /* Error[1] */
    g_current_pid.LastError = 0.0;      /* Error[-1] */
    g_current_pid.PrevError = 0.0;      /* Error[-2] */
    g_current_pid.Proportion = C_KP;    /* 比例常数 Proportional Const */
    g_current_pid.Integral = C_KI;      /* 积分常数 Integral Const */
    g_current_pid.Derivative = C_KD;    /* 微分常数 Derivative Const */
    g_current_pid.IngMax = 9000;        /* 积分限制 */
    g_current_pid.IngMin = 600;
    g_current_pid.OutMin = 600;
    g_current_pid.OutMax = 9000;        /* 期望限制 */
    
    g_speed_pid.SetPoint = 0;           /* 设定目标Desired Value */
    g_speed_pid.ActualValue = 0.0;      /* 设定目标Desired Value */
    g_speed_pid.Ui = 0.0;
    g_speed_pid.Up = 0.0;
    g_speed_pid.Ud = 0.0;
    g_speed_pid.Error = 0.0;            /* Error[1] */
    g_speed_pid.LastError = 0.0;        /* Error[-1] */
    g_speed_pid.PrevError = 0.0;        /* Error[-2] */
    g_speed_pid.Proportion = S_KP;      /* 比例常数 Proportional Const */
    g_speed_pid.Integral = S_KI;        /* 积分常数 Integral Const */
    g_speed_pid.Derivative = S_KD;      /* 微分常数 Derivative Const */ 
    g_speed_pid.IngMax = 9000;
    g_speed_pid.IngMin = -9000;
    g_speed_pid.OutMax = 9000;          /* 输出限制 */
    g_speed_pid.OutMin = -9000;
}

/**
 * @brief       位置式PID算法
 * @param       *PID:PID结构体句柄所对应的目标值
 * @param       Feedback_value : 实际值
 * @retval      目标控制量
 */
int32_t increment_pid_ctrl(PID_TypeDef *PID,float Feedback_value)
{
    PID->Error = (float)(PID->SetPoint - Feedback_value);   /* 目标值与实际值的偏差值 */
    PID->Up = PID->Proportion * PID->Error;
    PID->Ui += (PID->Error * PID->Integral);
    LIMIT_OUT(PID->Ui,PID->IngMax,PID->IngMin);             /* 积分限制 */
    PID->Ud = PID->Derivative * (PID->Error - PID->LastError);
    PID->ActualValue = PID->Up + PID->Ui + PID->Ud;
    LIMIT_OUT(PID->ActualValue,PID->OutMax,PID->OutMin);    /* 输出限制 */
    PID->LastError = PID->Error;                            /* 存储上次误差,以便下次计算使用 */
    return ((int32_t)(PID->ActualValue));                   /* 返回实际控制数值 */
}

 main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/TIMER/bldc_tim.h"
#include "./BSP/KEY/key.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/BLDC/bldc.h"
#include "./BSP/PID/pid.h"
#include "./DEBUG/debug.h"
#include "./BSP/ADC/adc.h"

extern float*user_setpoint;
extern float debug_data_temp;
extern int32_t motor_pwm_s;
extern int32_t temp_pwm1;
extern int16_t adc_amp_un[3];
extern float  adc_amp_bus;
extern uint16_t g_adc_value[ADC_CH_NUM * ADC_COLL];
extern uint8_t clc;
void bldc_speed_stop(void);                  /* 清除电机状态并关闭电机 */

int main(void)
{
    uint8_t debug_cmd = 0;                   /* 存放上位机指令 */
    float current_lpf[4] = {0.0f};           /* 存放三相电流以及母线电流 */
    uint8_t key,t;
    char buf[32];
    float current[3] = {0.0f};
    int16_t speed_diplay = 0;
    float user_setpoint_temp  = 0.0;

    HAL_Init();                              /* 初始化HAL库 */
    sys_stm32_clock_init(336, 8, 2, 7);      /* 设置时钟,168Mhz */
    delay_init(168);                         /* 延时初始化 */
    usart_init(115200);                      /* 串口初始化为115200 */
    led_init();                              /* 初始化LED */
    key_init();                              /* 初始化按键 */
    lcd_init();                              /* 初始化LCD */
    bldc_init(168000/18-1,0);                /* 18KHz */
    bldc_ctrl(MOTOR_1,CCW,0);                /* 初始无刷电机接口1速度 */
    pid_init();
    g_point_color = WHITE;
    g_back_color  = BLACK;
    adc_nch_dma_init();
    while (1)
    {
        t++;
        if(t % 20 == 0)
        {
            sprintf(buf,"PWM_Duty:%.1f%%  ",(float)((g_bldc_motor1.pwm_duty/MAX_PWM_DUTY)*100));        /* 显示控制PWM占空比 */
            lcd_show_string(10,110,200,16,16,buf,g_point_color);

            user_setpoint_temp = (*user_setpoint);
            speed_diplay = g_bldc_motor1.speed;
            sprintf(buf,"SetSpeed:%4d   ",(int16_t)user_setpoint_temp);                                 /* 显示设置速度 */
            lcd_show_string(10,110,200,16,16,buf,g_point_color);
            sprintf(buf,"M1 speed:%4d   ",speed_diplay);                                                /* 显示转速 */
            lcd_show_string(10,130,200,16,16,buf,g_point_color);
            sprintf(buf,"M1 pos:%4d",g_bldc_motor1.pos);                                                /* 显示位置变化 */
            lcd_show_string(10,150,200,16,16,buf,g_point_color);
            sprintf(buf,"PWM_Duty:%.1f%%  ",(float)((g_bldc_motor1.pwm_duty/(float)MAX_PWM_DUTY)*100)); /* 显示控制PWM占空比 */
            lcd_show_string(10,170,200,16,16,buf,g_point_color);


            sprintf(buf,"Power:%.3fV ",g_adc_value[0]*ADC2VBUS);
            lcd_show_string(10,190,200,16,16,buf,g_point_color);
            sprintf(buf,"Temp:%.1fC ",get_temp(g_adc_value[1]));
            lcd_show_string(10,210,200,16,16,buf,g_point_color);
            LED0_TOGGLE();                                                                              /* LED0(红灯) 翻转 */
            /* 三相电流计算 */
            current[0] = adc_amp_un[0]* ADC2CURT;/*U*/
            current[1] = adc_amp_un[1]* ADC2CURT;/*V*/
            current[2] = adc_amp_un[2]* ADC2CURT;/*W*/

            /*一阶数字滤波 滤波系数0.1 用于显示*/
            FirstOrderRC_LPF(current_lpf[0],current[0],0.1f);
            FirstOrderRC_LPF(current_lpf[1],current[1],0.1f);
            FirstOrderRC_LPF(current_lpf[2],current[2],0.1f);
            FirstOrderRC_LPF(current_lpf[3],adc_amp_bus,0.1f);
            if(g_bldc_motor1.run_flag == STOP)                  /* 停机的电流显示 */
            {
                current_lpf[0]=0;
                current_lpf[1]=0;
                current_lpf[2]=0;
                current_lpf[3]=0;
            }
            
        }

        key = key_scan(0);
        if(key == KEY0_PRES)                                    /* 按下KEY0目标速度值++ */
        {
            g_bldc_motor1.run_flag = RUN;                       /* 开启运行 */
            start_motor1();                                     /* 开启运行 */

            if(g_bldc_motor1.dir == CCW && *user_setpoint == 0) /* 切换方向条件*/
            {
                g_bldc_motor1.dir = CW; 
            }
            *user_setpoint += 400;                              /* 逆时针旋转下递增 */
            if(*user_setpoint >= 3000)                          /* 最高不超过3000PRM */
                *user_setpoint = 3000;
            if(*user_setpoint == 0)
            {
                pid_init();                                     /* 初始化PID */
                g_bldc_motor1.run_flag = STOP;                  /* 标记停机 */
                stop_motor1();                                  /* 停机 */
                g_bldc_motor1.speed = 0;
                motor_pwm_s = 0;
                g_bldc_motor1.pwm_duty = 0;
            }
            debug_data_temp = *user_setpoint;
        }
        else if(key == KEY1_PRES)                               /* 按下KEY1目标速度值-- */
        {
            g_bldc_motor1.run_flag = RUN;                       /* 开启运行 */
            start_motor1();                                     /* 运行电机 */
            /* 切换方向条件 */
            if(g_bldc_motor1.dir == CW && *user_setpoint == 0)
            {
                g_bldc_motor1.dir = CCW;
            }
            *user_setpoint -= 400;                              /* 逆时针旋转下递增 */
            if(*user_setpoint <= -3000)                         /* 最高不超过300PRM */
                *user_setpoint = -3000;
            if(*user_setpoint == 0)
            {
                pid_init();                                     /* 初始化PID */
                g_bldc_motor1.run_flag = STOP;                  /* 标记停机 */
                stop_motor1();                                  /* 停机 */
                g_bldc_motor1.speed = 0;
                motor_pwm_s = 0;
                g_bldc_motor1.pwm_duty = 0;
            }

            debug_data_temp = *user_setpoint;
        }
        else if(key == KEY2_PRES)                               /* 按下KEY2关闭电机 */
        {
            bldc_speed_stop();
        }

        delay_ms(10);
    }
}
/**
 * @brief       关闭电机并清除状态
 * @param       无
 * @retval      无
 */
void bldc_speed_stop(void)
{
    pid_init();
    g_bldc_motor1.run_flag = STOP;  /* 标记停机 */
    stop_motor1();                  /* 停机 */
    g_bldc_motor1.speed = 0;
    motor_pwm_s = 0;
    g_bldc_motor1.pwm_duty = 0;
}

 g_bldc_motor1.count_j就是高电平的计数值。在高电平时先清零累加。从1到0为低电平时。后去 g_bldc_motor1.count_j的值就是高电平的计数值。

#define SPEED_COEFF      (uint32_t)((18000/4)*60)       /* 旋转一圈变化4个信号,2对级永磁体特性,NSNS共4级数 */

速度计算:temp_speed = (SPEED_COEFF/g_bldc_motor1.count_j)

速度的计算在代码的体现:电机是两对极。完全与公式是相同的。

  

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值