打印
[STM8]

【求解】无刷直流电机不转

[复制链接]
3277|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
thor1991|  楼主 | 2015-7-9 10:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 thor1991 于 2015-7-10 16:53 编辑
/* MAIN.C file
*
* Copyright (c) 2002-2005 STMicroelectronics
*/


/* MAIN.C file
摘要:
1.PD7延时反转,指示系统工作。
2.上电,按指定PWM输出换相,实现电机基本运转功能。
3.换相依据为HALl信号,采用PORTD中断功能完成.
总之,上电根据HALL状态换相,并在输出PWM信号后,电机会转动,
同时HALL信号不断改变,然后进入捕获中断,进行及时换相。
如此实现电机的运转控制。
2013.5.8
*/
#include "stm8s.h"

#define STM8_FREQ_MHZ 16
#define PWM_FREQUENCY 16000

static const u16 hArrPwmVal = ((u16)((STM8_FREQ_MHZ * (u32)1000000)/PWM_FREQUENCY));
//PWM信号周期

#define PWMOUT 20
//按15%占空比输出

const unsigned char PWM_EN1_TAB[6]={0x00,0x00,0x10,0x10,0x01,0x01};
//六步法中,CH1\CH2通道极性及使能配置
const unsigned char PWM_EN2_TAB[6]={0x01,0x01,0x00,0x00,0x0,0x00};
//六步法中,CH3通道极性及使能配置

//上桥臂开关控制端口定义
#define MCO1_PORT GPIOC
#define MCO1_PIN        GPIO_PIN_1
#define MCO3_PORT GPIOC
#define MCO3_PIN        GPIO_PIN_2
#define MCO5_PORT GPIOC
#define MCO5_PIN        GPIO_PIN_3

//下桥臂开关控制端口定义
#define MCO0_PORT GPIOB
#define MCO0_PIN        GPIO_PIN_0
#define MCO2_PORT GPIOB
#define MCO2_PIN        GPIO_PIN_1
#define MCO4_PORT GPIOB
#define MCO4_PIN        GPIO_PIN_2
//下桥臂低电平开关管导通
#define PWM_A_OFF MCO0_PORT->ODR |= (u8)MCO0_PIN;
#define PWM_B_OFF MCO2_PORT->ODR |= (u8)MCO2_PIN;
#define PWM_C_OFF MCO4_PORT->ODR |= (u8)MCO4_PIN;

#define PWM_A_ON MCO0_PORT->ODR &= (u8)(~MCO0_PIN);
#define PWM_B_ON MCO2_PORT->ODR &= (u8)(~MCO2_PIN);
#define PWM_C_ON MCO4_PORT->ODR &= (u8)(~MCO4_PIN);

//霍尔引脚定义
#define H1_PORT GPIOD->IDR
#define H1_PIN  BIT2

#define H2_PORT GPIOD->IDR
#define H2_PIN  BIT3

#define H3_PORT GPIOD->IDR
#define H3_PIN  BIT4

unsigned char bHallSteps[2][8]={
{7,5,3,4,1,0,2,7},//正转
{7,2,0,1,4,3,5,7}//反转
};

/* Private vars and define */
#define BIT0 0x01
#define BIT1 0x02
#define BIT2 0x04
#define BIT3 0x08
#define BIT4 0x10
#define BIT5 0x20
#define BIT6 0x40
#define BIT7 0x80

//换相子函数声明
void Commutation(unsigned char bHallStartStep,unsigned int OutPwmValue);

unsigned int outpwm=0;
        

//初始化按键,指示灯端口
void GPIO_int(void)
{
         /* LEDs */
        GPIO_Init(GPIOD, GPIO_PIN_7, GPIO_MODE_OUT_PP_HIGH_FAST);
}

//系统时钟配置:内部16M
void Clock_init(void)
{
        /* Select fCPU = 16MHz */
  CLK_SYSCLKConfig(CLK_PRESCALER_HSIDIV1);
}

//换相电路开关管IO初始化
void PWM_IO_init(void)
{        
  //PB012 下桥臂0有效 ,配置为高电平
        GPIO_Init(MCO0_PORT, MCO0_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);
        GPIO_Init(MCO2_PORT, MCO2_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);
        GPIO_Init(MCO4_PORT, MCO4_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);
        
        //PC123 上桥臂1有效,配置为低电平
        GPIO_Init(MCO1_PORT, MCO1_PIN,GPIO_MODE_OUT_PP_LOW_FAST);
        GPIO_Init(MCO3_PORT, MCO3_PIN,GPIO_MODE_OUT_PP_LOW_FAST);
        GPIO_Init(MCO5_PORT, MCO5_PIN,GPIO_MODE_OUT_PP_LOW_FAST);        
}

void Tim1_init(void)
{
         /* TIM1 Peripheral Configuration */
  TIM1_DeInit();

  TIM1_TimeBaseInit(0, TIM1_COUNTERMODE_UP, hArrPwmVal, 0);

  TIM1_OC1Init(TIM1_OCMODE_PWM1, TIM1_OUTPUTSTATE_ENABLE, TIM1_OUTPUTNSTATE_DISABLE, hArrPwmVal*0, TIM1_OCPOLARITY_HIGH, TIM1_OCNPOLARITY_LOW, TIM1_OCIDLESTATE_RESET, TIM1_OCNIDLESTATE_SET);

  TIM1_OC2Init(TIM1_OCMODE_PWM1, TIM1_OUTPUTSTATE_ENABLE, TIM1_OUTPUTNSTATE_DISABLE, hArrPwmVal*0, TIM1_OCPOLARITY_HIGH, TIM1_OCNPOLARITY_LOW, TIM1_OCIDLESTATE_RESET, TIM1_OCNIDLESTATE_SET);

  TIM1_OC3Init(TIM1_OCMODE_PWM1, TIM1_OUTPUTSTATE_ENABLE, TIM1_OUTPUTNSTATE_DISABLE, hArrPwmVal*0, TIM1_OCPOLARITY_HIGH, TIM1_OCNPOLARITY_LOW, TIM1_OCIDLESTATE_RESET, TIM1_OCNIDLESTATE_SET);

  TIM1_CCPreloadControl(DISABLE);
        TIM1_Cmd(ENABLE);
}

//初始化HALL捕获输入定义器,采用PD口外部中断捕获输入
void HALLEXTI_INIT(void)
{
        GPIO_Init(GPIOD, GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4,GPIO_MODE_IN_PU_IT);        //HALL端口模式配置
}

//根据HALL状态换相,启动电机运行
void HALL_START(void)
{
        u8 bHStatus = 0,bHallStartStep;
                        
                // Read status of H1
        if (H1_PORT & H1_PIN)
        {
                bHStatus |= BIT2;
        }
        
        // Read status of H2
        if (H2_PORT & H2_PIN)
        {
                bHStatus |= BIT1;
        }
               
                // Read status of H3
        if (H3_PORT & H3_PIN)
        {                        
                        bHStatus |= BIT0;
        }
        
        bHallStartStep = bHallSteps[1][bHStatus];//得到换相步序

        if (bHallStartStep == 7)//不该出现的HALL状态
        {                        
                        return;
        }
               
               
                GPIOD->CR2|=BIT3|BIT2|BIT4;
                EXTI->CR1|=BIT6|BIT7;
                Commutation(bHallStartStep,outpwm);//输出PWM信号,启动电机
}

@far@interruptvoid EXTI_PORTD_IRQHandler(void)
{
        /* in order to detect unexpected events during development,
           it is recommended to set a breakpoint on the following instruction
        */
        u8 bHStatus =0,i,bHallStartStep;
               
        bHStatus=(GPIO_ReadInputData(GPIOD)>>2)&0x07;
        for(i=0;i<50;i++);//滤波时间
        i=(GPIO_ReadInputData(GPIOD)>>2)&0x07;
        if(bHStatus!=i)return;
        
        bHStatus=0;        
                // Read status of H1
        if (H1_PORT & H1_PIN)
        {
                bHStatus |= BIT2;
        }
        
        // Read status of H2
        if (H2_PORT & H2_PIN)
        {
                bHStatus |= BIT1;
        }
                        
        // Read status of H3
        if (H3_PORT & H3_PIN)
        {
                        bHStatus |= BIT0;
        }

                bHallStartStep = bHallSteps[1][bHStatus];//得到换相步序

                if (bHallStartStep == 7)
                { //故障,停止输出
                        TIM1->BKR &= (uint8_t)(~TIM1_BKR_MOE);//禁止PWM输出
                        PWM_A_OFF;
                        PWM_B_OFF;
                        PWM_C_OFF;
                        return;
                }
               
               
                EXTI->CR1|=BIT6|BIT7;
                Commutation(bHallStartStep,outpwm);//输出PWM信号,启动电机
        return;
}

void ChongD(void)
{        
  unsigned int tem_c=0;
        PWM_A_ON;PWM_B_ON;PWM_C_ON;
        for(tem_c=0;tem_c<50000;tem_c++);
        PWM_A_OFF;PWM_B_OFF;PWM_C_OFF;
}

main()
{
  unsigned int tem_c=0;
        unsigned char step=0;
        
        for(tem_c=0;tem_c<50000;tem_c++);//上电延时,等待系统稳定

        Clock_init();//指示灯端口初始化
        GPIO_int();//时钟配置
        
        PWM_IO_init();//开关管控制端口初始化
        Tim1_init();//高级定时器配置        
        HALLEXTI_INIT();//HALL端口初始化配置
        ChongD();
        outpwm=hArrPwmVal*PWMOUT/100;//固定占空比的PWM值
        HALL_START();//根据HALL状态输出PWM状态,启动电机运行
        enableInterrupts();
        
        while (1);
        {
                for(tem_c=0;tem_c<50000;tem_c++);//延时时间
                GPIO_WriteReverse(GPIOD,GPIO_PIN_7);//PD7指示灯反转
        }
}

//换向输出PWM值,
//bHallStartStep:当前换相步序0-5,OutPwmValue 输出PWM值
void Commutation(unsigned char bHallStartStep,unsigned int OutPwmValue)
{        
   TIM1->BKR &= (uint8_t)(~TIM1_BKR_MOE);//禁止PWM输出
        if(bHallStartStep!=3&&bHallStartStep!=4)
        PWM_A_OFF;
        if(bHallStartStep!=0&&bHallStartStep!=5)
        PWM_B_OFF;
        if(bHallStartStep!=1&&bHallStartStep!=2)
        PWM_C_OFF;
         
        //根据换相步序,打开不同的开关管,并施加正确的PWM信号
        if(bHallStartStep==0)//AB
        {
                TIM1->CCR3H = (uint8_t)(OutPwmValue >> 8);
    TIM1->CCR3L = (uint8_t)(OutPwmValue);
                PWM_B_ON;
        }
  else if(bHallStartStep==1)        //AC
        {
                TIM1->CCR3H = (uint8_t)(OutPwmValue >> 8);
    TIM1->CCR3L = (uint8_t)(OutPwmValue);
          PWM_C_ON;
        }
        else if(bHallStartStep==2)        //BC
        {
                TIM1->CCR2H = (uint8_t)(OutPwmValue >> 8);
    TIM1->CCR2L = (uint8_t)(OutPwmValue);
          PWM_C_ON;
        }
        else if(bHallStartStep==3)        //BA
        {
                TIM1->CCR2H = (uint8_t)(OutPwmValue >> 8);
    TIM1->CCR2L = (uint8_t)(OutPwmValue);
          PWM_A_ON;
        }
        else if(bHallStartStep==4)//CA
        {
                TIM1->CCR1H = (uint8_t)(OutPwmValue >> 8);
    TIM1->CCR1L = (uint8_t)(OutPwmValue);
          PWM_A_ON;
        }
        else if(bHallStartStep==5)        //CB
        {
                TIM1->CCR1H = (uint8_t)(OutPwmValue >> 8);
    TIM1->CCR1L = (uint8_t)(OutPwmValue);
          PWM_B_ON;
        }
        
        TIM1->CCER1=PWM_EN1_TAB[bHallStartStep];
        TIM1->CCER2=PWM_EN2_TAB[bHallStartStep];               
        TIM1->BKR|=TIM1_BKR_MOE;//使能PWM输出
}

#ifdef USE_FULL_ASSERT

/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  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(u8* file, u32 line)
{
  /* 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) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif



程序控制三相120°无刷直流电机,芯片为stm8s207rb其中有六状态,本应该是下面六种相序
UH WL           UH VL
WH  VL         WH UL
VH UL          VH  WL
用PD口外部中断捕获霍尔信号,却出现
UH VL WL       UH UL WL   
WH WL UL      WH WL UL
VH VL UL       VH VL WL
写的程序出现了上下桥同时导通的情况
请问各位大神,这个该怎么解决?????
沙发
CS_Police| | 2015-7-29 13:47 | 只看该作者
很明显是你的关闭打开控制不够彻底,需要在动态过程中看波形。

使用特权

评论回复
板凳
Thomas1990| | 2015-11-3 00:53 | 只看该作者
楼主,你好,我也正在做无位置无刷直流电机,看到你这个帖子,跟我做的很像,可以加你聊下吗,我的qq807695272

使用特权

评论回复
地板
waterbaby2011| | 2016-8-26 13:53 | 只看该作者
时序状态不对,

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

14

帖子

0

粉丝