找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 8721|回復(fù): 4
收起左側(cè)

無刷直流電機(jī)控制應(yīng)用——基于STM8S系列單片機(jī)

[復(fù)制鏈接]
ID:190973 發(fā)表于 2017-4-18 20:26 | 顯示全部樓層 |閱讀模式
1、PWM程序
/*摘要:
功能:1. PA4\PA5指示端閃爍,指示系統(tǒng)處于工作狀態(tài)。
2. 上橋臂開關(guān)管PC1\PC2\PC3同時輸出占空比40%的PWM信號,即高電平占40%。
3. 下橋臂開關(guān)管PB0\PB1\PB2全部處于關(guān)斷狀態(tài),即為低電平。*/
#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信號周期
//初始化按鍵,指示燈端口
void GPIO_int(void)
{
    GPIOG->DDR=GPIOG->DDR&0x3f;//PG6,PG7按鍵配置為輸入模式
    GPIOG->CR1=GPIOG->CR1|0xC0;//PG6,PG7按鍵配置為上拉輸入
    GPIOA->DDR=GPIOA->DDR|0x30;//PA4,PA5指示燈配置為輸出模式
    GPIOA->CR1=GPIOA->CR1|0x30;//PA4,PA5指示燈d配置為推挽模式
    GPIOA->ODR|=0x30;//點亮指示燈
}
//系統(tǒng)時鐘配置:內(nèi)部16M
void Clock_init(void)
{
    CLK->CKDIVR=0;
}
//換相電路開關(guān)管IO初始化
void PWM_IO_init(void)
{   
//PB012 下橋臂1有效
    GPIOB->DDR=GPIOB->DDR|0x7;//PB012配置為輸出模式
    GPIOB->CR1=GPIOB->CR1|0x7;//PB012推挽模式
    GPIOB->ODR&=0xf8;//關(guān)閉下橋臂開關(guān)管
        //PC123上橋臂1有效
    GPIOC->DDR=GPIOC->DDR|0x0E;//PC123配置為輸出模式
    GPIOC->CR1=GPIOC->CR1|0x0E;//PC123推挽模式
    GPIOC->ODR&=~(0x0E);//關(guān)閉上橋臂開關(guān)管
}
//高級定時器初始化配置
void Tim1_init(void)
{
    //計數(shù)器禁止、ARR預(yù)裝載禁止、邊沿對齊模式
    TIM1->CR1= 0x04;
    TIM1->SMCR= 0;//禁止從模式
    TIM1->IER= 0;//禁止所有中斷
    TIM1->CCER1= 0; //禁止PWM輸出
    TIM1->CCER2= 0;
    TIM1->CCMR1= 0x60; //PWM1模式,禁止預(yù)裝載
    TIM1->CCMR2= 0x60;
    TIM1->CCMR3= 0x60;
    //prescale= div1 @ 16MHz -> 62.5ns/count, Full scale = 4.09ms
    TIM1->PSCRH= 0;
    TIM1->PSCRL= 0;
    TIM1->ARRH=hArrPwmVal/256;//PWM周期設(shè)定
    TIM1->ARRL=hArrPwmVal%256;
    //disablerepetition counter
    TIM1->RCR= 0;
TIM1->CCR1H=0;TIM1->CCR1L=0;//占空比輸出均為0
TIM1->CCR2H=0;TIM1->CCR1L=0;
TIM1->CCR3H=0;TIM1->CCR1L=0;
    //使能定時計數(shù)器
    TIM1->CR1|= 0x01;
}
main()
{
    unsignedint tem_c=0;
    unsignedint outpwm;
    for(tem_c=0;tem_c<50000;tem_c++);//上電延時,等待系統(tǒng)穩(wěn)定
    Clock_init();//時鐘配置
    GPIO_int();//指示燈端口初始化
    PWM_IO_init();//開關(guān)管控制端口初始化
    Tim1_init();//高級定時器配置
    outpwm=hArrPwmVal*0.4;//占空比輸出設(shè)為40%
    TIM1->CCR1H= (uint8_t)(outpwm >> 8);
    TIM1->CCR1L= (uint8_t)(outpwm);
    TIM1->CCR2H= (uint8_t)(outpwm >> 8);
    TIM1->CCR2L= (uint8_t)(outpwm);
    TIM1->CCR3H= (uint8_t)(outpwm >> 8);
    TIM1->CCR3L= (uint8_t)(outpwm);
    TIM1->CCER1=0x11;//CH1\CH2通道輸出PWM使能,高電平有效
    TIM1->CCER2=0x1;//CH3通道輸出PWM使能,高電平有效
    TIM1->BKR|=TIM1_BKR_MOE;//使能PWM輸出
    while(1)
    {      
      for(tem_c=0;tem_c<50000;tem_c++);
        GPIOA->ODR^=0x30;//PA4\PA5指示燈閃爍
    }
}
2、運轉(zhuǎn)程序
(1)hall.h
#include "stm8s.h"  
#define H1_PORT GPIOD->IDR
#define H1_PIN  BIT4
#define H2_PORT GPIOD->IDR
#define H2_PIN  BIT3
#define H3_PORT GPIOD->IDR
#define H3_PIN  BIT2
extern unsigned int OutPwmValue;
extern unsigned char bHallStartStep;
#define BIT0 0x01
#define BIT1 0x02
#define BIT2 0x04
#define BIT3 0x08
#define BIT4 0x10
#define BIT5 0x20
#define BIT6 0x40
#define BIT7 0x80
//下橋臂開關(guān)控制端口定義
#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_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 PWM_A_OFF MCO0_PORT->ODR &=(u8)(~MCO0_PIN);
#define PWM_B_OFF MCO2_PORT->ODR &=(u8)(~MCO2_PIN);
#define PWM_C_OFF MCO2_PORT->ODR &= (u8)(~MCO4_PIN);
void Init_TIM2(void);
void TIM2_InitCapturePolarity(void);
void ComHandler(void);  
(2)hall.c
#include "hall.h"
unsigned char bHallStartStep;//換相步序變量定義
//換相步序值0-5分別對應(yīng)AB\AC\BC\BA\CA\CB
unsigned int OutPwmValue=0;//PWM輸出值變量定義
unsigned char bHallSteps[2][8]={
{7,5,3,4,1,0,2,7},//正轉(zhuǎn)
{7,2,0,1,4,3,5,7}//反轉(zhuǎn)
};
const unsigned charPWM_EN1_TAB[6]={0x01,0x01,0x10,0x10,0x00,0x00};
//六步法中,CH1\CH2通道極性及使能配置
const unsigned charPWM_EN2_TAB[6]={0x0,0x00,0x00,0x0,0x1,0x1};
//六步法中,CH3通道極性及使能配置
//初始化HALL捕獲輸入定義器
void Init_TIM2(void)
{
    //計數(shù)器禁止、ARR預(yù)裝載禁止、向上計數(shù)、邊沿對齊模式
    TIM2->CR1= BIT2;
    //禁止TIM2所有中斷
    TIM2->IER= 0;//禁止中斷
    TIM2->CCMR1= 0x01;//TIM2的CH1\CH2\CH3通道配置為輸入
    TIM2->CCMR2= 0x01;
    TIM2->CCMR3= 0x01;
    #defineIC_FILTER (u8)(5 << 4)
    TIM2->CCMR1|= IC_FILTER; //輸入捕獲濾波器
    TIM2->CCMR2|= IC_FILTER;
    TIM2->CCMR3|= IC_FILTER;
    //prescale= div3 @ 16MHz -> 0.5us/count * 24MHz -> 0.33us/count
    TIM2->PSCR= 0;
    TIM2->ARRH=0xff;//計數(shù)周期設(shè)為最大
    TIM2->ARRL=0xff;
        TIM2->CCER1|= 0x01;//TIM2的CH1\CH2\CH3通道使能捕獲功能
    TIM2->CCER1|= 0x10;
    TIM2->CCER2|= 0x01;
    TIM2->CR1|= 0x01;//使能TIM2定時器
}
//根據(jù)HALL狀態(tài)換相,啟動電機(jī)運行
void TIM2_InitCapturePolarity(void)
    {
        u8bHStatus = 0;
        GPIOD->DDR&= (u8)(~(0x1c));//HALL端口模式配置
        //Read status of H1 and set the expected polarity
    if(H1_PORT & H1_PIN)
    {
        TIM2->CCER1|= BIT1;
        bHStatus|= BIT2;
    }
    else
    {
        TIM2->CCER1&= (u8)(~(BIT1));
    }
    //Read status of H2 and set the expected polarity
    if(H2_PORT & H2_PIN)
    {
        TIM2->CCER1|= BIT5;
        bHStatus|= BIT1;
    }
    else
    {
        TIM2->CCER1&= (u8)(~(BIT5));
    }
    //Read status of H3 and set the expected polarity
    if(H3_PORT & H3_PIN)
    {
            TIM2->CCER2|= BIT1;
            bHStatus|= BIT0;
    }
    else
    {
            TIM2->CCER2&= (u8)(~(BIT1));
    }
        bHallStartStep= bHallSteps[0][bHStatus];//得到換相步序
        if(bHallStartStep == 7)//不該出現(xiàn)的HALL狀態(tài)
        {           
            return;
        }
        TIM2->SR1=(u8)~(TIM2_IT_CC3|TIM2_IT_CC2|TIM2_IT_CC1);   
        TIM2->IER= 0x0e;//使能輸入捕獲中斷
        ComHandler();//輸出PWM信號,啟動電機(jī)
}
//捕獲中斷,即HALL狀態(tài)變化時,進(jìn)入此中斷
@near @interrupt @svlreg voidTIM2_CAP_COM_IRQHandler(void)
{
    u8bHStatus = 0;
    //Read status of H1 and set the expected polarity
    if(H1_PORT & H1_PIN)
    {
        TIM2->CCER1|= BIT1;
        bHStatus|= BIT2;
    }
    else
    {
        TIM2->CCER1&= (u8)(~(BIT1));
    }
    //Read status of H2 and set the expected polarity
    if(H2_PORT & H2_PIN)
    {
        TIM2->CCER1|= BIT5;
        bHStatus|= BIT1;
    }
    else
    {
        TIM2->CCER1&= (u8)(~(BIT5));
    }
    //Read status of H3 and set the expected polarity
    if(H3_PORT & H3_PIN)
    {
        TIM2->CCER2|= BIT1;
        bHStatus|= BIT0;
    }
    else
    {
        TIM2->CCER2&= (u8)(~(BIT1));
    }
    if(TIM2->SR1 & BIT2)
    {
        TIM2->SR1=(u8)(~TIM2_IT_CC2);
    }
    if(TIM2->SR1 & BIT1)
    {
        TIM2->SR1=(u8)(~TIM2_IT_CC1);
    }
    if(TIM2->SR1 & BIT3)
    {
        TIM2->SR1=(u8)(~TIM2_IT_CC3);
    }
    bHallStartStep= bHallSteps[0][bHStatus];//得到換相步序
    if(bHallStartStep == 7)
    { //故障,停止輸出
        TIM1->BKR&= (uint8_t)(~TIM1_BKR_MOE);//禁止PWM輸出
        PWM_A_OFF;
        PWM_B_OFF;
        PWM_C_OFF;
        return;
    }
    ComHandler();   //換相
    return;
}
//換相子函數(shù)
void    ComHandler(void)
{
    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;
    //根據(jù)換相步序,打開不同的開關(guān)管,并施加正確的PWM信號
    if(bHallStartStep==0)//AB
    {
        TIM1->CCR1H= (uint8_t)(OutPwmValue >> 8);
   TIM1->CCR1L = (uint8_t)(OutPwmValue);
        PWM_B_ON;
    }
  elseif(bHallStartStep==1)    //AC
    {
        TIM1->CCR1H= (uint8_t)(OutPwmValue >> 8);
   TIM1->CCR1L = (uint8_t)(OutPwmValue);
      PWM_C_ON;
    }
    elseif(bHallStartStep==2)  //BC
    {
        TIM1->CCR2H= (uint8_t)(OutPwmValue >> 8);
   TIM1->CCR2L = (uint8_t)(OutPwmValue);
      PWM_C_ON;
    }
    elseif(bHallStartStep==3)  //BA
    {
        TIM1->CCR2H= (uint8_t)(OutPwmValue >> 8);
   TIM1->CCR2L = (uint8_t)(OutPwmValue);
      PWM_A_ON;
    }
    elseif(bHallStartStep==4)//CA
    {
        TIM1->CCR3H= (uint8_t)(OutPwmValue >> 8);
   TIM1->CCR3L = (uint8_t)(OutPwmValue);
      PWM_A_ON;
    }
    elseif(bHallStartStep==5)  //CB
    {
        TIM1->CCR3H= (uint8_t)(OutPwmValue >> 8);
   TIM1->CCR3L = (uint8_t)(OutPwmValue);
      PWM_B_ON;
    }
    TIM1->CCER1=PWM_EN1_TAB[bHallStartStep];
    TIM1->CCER2=PWM_EN2_TAB[bHallStartStep];        
    TIM1->BKR|=TIM1_BKR_MOE;//使能PWM輸出
}
(3)mian.c
/*摘要:
功能:1. PA4\PA5指示端閃爍,指示系統(tǒng)處于工作狀態(tài)。
2. 上橋臂開關(guān)管PC1\PC2\PC3輸出占空比20%的PWM信號,即高電平占20%。
3. 上電根據(jù)HALL狀態(tài)換相,并在輸出PWM信號后,電機(jī)會轉(zhuǎn)動,同時HALL信號不斷改變,然后進(jìn)入捕獲中斷,進(jìn)行及時換相。如此實現(xiàn)電機(jī)的運轉(zhuǎn)控制。*/
#include "stm8s.h"   
#include "hall.h"
#define STM8_FREQ_MHZ 16
#define PWM_FREQUENCY 16000
static const u16 hArrPwmVal =((u16)((STM8_FREQ_MHZ * (u32)1000000)/PWM_FREQUENCY));
//PWM信號周期
//初始化按鍵,指示燈端口
void GPIO_int(void)
{
    GPIOG->DDR=GPIOG->DDR&0x3f;//PG6,PG7按鍵配置為輸入模式
    GPIOG->CR1=GPIOG->CR1|0xC0;//PG6,PG7按鍵配置為上拉輸入
    GPIOA->DDR=GPIOA->DDR|0x30;//PA4,PA5指示燈配置為輸出模式
    GPIOA->CR1=GPIOA->CR1|0x30;//PA4,PA5指示燈d配置為推挽模式
    GPIOA->ODR|=0x30;//點亮指示燈
}
//系統(tǒng)時鐘配置:內(nèi)部16M
void Clock_init(void)
{
    CLK->CKDIVR=0;
}
//換相電路開關(guān)管IO初始化
void PWM_IO_init(void)
{   
   //PB012 下橋臂1有效
    GPIOB->DDR=GPIOB->DDR|0x7;//PB012配置為輸出模式
    GPIOB->CR1=GPIOB->CR1|0x7;//PB012推挽模式
    GPIOB->ODR&=0xf8;//關(guān)閉下橋臂開關(guān)管
    //PC123上橋臂1有效
    GPIOC->DDR=GPIOC->DDR|0x0E;//PC123配置為輸出模式
    GPIOC->CR1=GPIOC->CR1|0x0E;//PC123推挽模式
    GPIOC->ODR&=~(0x0E);//關(guān)閉上橋臂開關(guān)管
}
//高級定時器初始化配置
void Tim1_init(void)
{
    //計數(shù)器禁止、ARR預(yù)裝載禁止、邊沿對齊模式
    TIM1->CR1= 0x04;
    TIM1->SMCR= 0;//禁止從模式
    TIM1->IER= 0;//禁止所有中斷
    TIM1->CCER1= 0; //禁止PWM輸出
    TIM1->CCER2= 0;
    TIM1->CCMR1= 0x60; //PWM1模式,禁止預(yù)裝載
    TIM1->CCMR2= 0x60;
    TIM1->CCMR3= 0x60;
    //prescale= div1 @ 16MHz -> 62.5ns/count, Full scale = 4.09ms
    TIM1->PSCRH= 0;
    TIM1->PSCRL= 0;
    TIM1->ARRH=hArrPwmVal/256;//PWM周期設(shè)定
    TIM1->ARRL=hArrPwmVal%256;
    //disablerepetition counter
    TIM1->RCR= 0;
TIM1->CCR1H=0;TIM1->CCR1L=0;//占空比輸出均為0
TIM1->CCR2H=0;TIM1->CCR1L=0;
TIM1->CCR3H=0;TIM1->CCR1L=0;
    //使能定時計數(shù)器
    TIM1->CR1|= 0x01;
}
main()
{
    unsignedint tem_c=0;
    for(tem_c=0;tem_c<50000;tem_c++);//上電延時,等待系統(tǒng)穩(wěn)定
    Clock_init();//時鐘配置
    GPIO_int();//指示燈端口初始化
    PWM_IO_init();//開關(guān)管控制端口初始化
    Tim1_init();//高級定時器配置   
    Init_TIM2();//捕獲輸入定時器初始化配置
    enableInterrupts();
    OutPwmValue=hArrPwmVal*0.2;//固定20%占空比的PWM值
    TIM2_InitCapturePolarity();//根據(jù)HALL狀態(tài)輸出PWM狀態(tài),啟動電機(jī)運行
    while(1)
    {      
      for(tem_c=0;tem_c<50000;tem_c++);
        GPIOA->ODR^=0x30;//PA4\PA5指示燈閃爍
    }
}
3、啟停和調(diào)速
(1)hall.h
#include "stm8s.h"  
#define H1_PORT GPIOD->IDR
#define H1_PIN  BIT4
#define H2_PORT GPIOD->IDR
#define H2_PIN  BIT3
#define H3_PORT GPIOD->IDR
#define H3_PIN  BIT2
extern unsigned char St_F;//啟停變量
extern unsigned char FaultF;//故障標(biāo)志
extern unsigned char Run_dir;//運轉(zhuǎn)標(biāo)志
extern unsigned int OutPwmValue;
extern unsigned char bHallStartStep;
#define BIT0 0x01
#define BIT1 0x02
#define BIT2 0x04
#define BIT3 0x08
#define BIT4 0x10
#define BIT5 0x20
#define BIT6 0x40
#define BIT7 0x80
//下橋臂開關(guān)控制端口定義
#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_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 PWM_A_OFF MCO0_PORT->ODR &=(u8)(~MCO0_PIN);
#define PWM_B_OFF MCO2_PORT->ODR &=(u8)(~MCO2_PIN);
#define PWM_C_OFF MCO2_PORT->ODR &=(u8)(~MCO4_PIN);
void Init_TIM2(void);
void TIM2_InitCapturePolarity(void);
void ComHandler(void);  
(2)hall.c
#include "hall.h"
unsigned char bHallStartStep;//換相步序變量定義
//換相步序值0-5分別對應(yīng)AB\AC\BC\BA\CA\CB
unsigned int OutPwmValue=0;//PWM輸出值變量定義
unsigned char St_F=0;//啟停標(biāo)志,0時為停止,1時為啟動
unsigned char FaultF=0;//故障標(biāo)志
unsigned char Run_dir=0;//運轉(zhuǎn)方向,0-1對立
unsigned char bHallSteps[2][8]={
{7,5,3,4,1,0,2,7},//正轉(zhuǎn)
{7,2,0,1,4,3,5,7}//反轉(zhuǎn)
};
const unsigned charPWM_EN1_TAB[6]={0x01,0x01,0x10,0x10,0x00,0x00};
//六步法中,CH1\CH2通道極性及使能配置
const unsigned charPWM_EN2_TAB[6]={0x0,0x00,0x00,0x0,0x1,0x1};
//六步法中,CH3通道極性及使能配置
//初始化HALL捕獲輸入定義器
void Init_TIM2(void)
{
    //計數(shù)器禁止、ARR預(yù)裝載禁止、向上計數(shù)、邊沿對齊模式
    TIM2->CR1= BIT2;
    //禁止TIM2所有中斷
    TIM2->IER= 0;//禁止中斷
    TIM2->CCMR1= 0x01;//TIM2的CH1\CH2\CH3通道配置為輸入
    TIM2->CCMR2= 0x01;
    TIM2->CCMR3= 0x01;
    #defineIC_FILTER (u8)(5 << 4)
    TIM2->CCMR1|= IC_FILTER; //輸入捕獲濾波器
    TIM2->CCMR2|= IC_FILTER;
    TIM2->CCMR3|= IC_FILTER;
    //prescale= div3 @ 16MHz -> 0.5us/count * 24MHz -> 0.33us/count
    TIM2->PSCR= 0;
    TIM2->ARRH=0xff;//計數(shù)周期設(shè)為最大
    TIM2->ARRL=0xff;
    TIM2->CCER1|= 0x01;//TIM2的CH1\CH2\CH3通道使能捕獲功能
    TIM2->CCER1|= 0x10;
    TIM2->CCER2|= 0x01;
    TIM2->CR1|= 0x01;//使能TIM2定時器
}
//根據(jù)HALL狀態(tài)換相,啟動電機(jī)運行
void TIM2_InitCapturePolarity(void)
    {
        u8bHStatus = 0;
        GPIOD->DDR&= (u8)(~(0x1c));//HALL端口模式配置
        //Read status of H1 and set the expected polarity
    if(H1_PORT & H1_PIN)
    {
        TIM2->CCER1|= BIT1;
        bHStatus|= BIT2;
    }
    else
    {
        TIM2->CCER1&= (u8)(~(BIT1));
    }
    //Read status of H2 and set the expected polarity
    if(H2_PORT & H2_PIN)
    {
        TIM2->CCER1|= BIT5;
        bHStatus|= BIT1;
    }
    else
    {
        TIM2->CCER1&= (u8)(~(BIT5));
    }
        //Read status of H3 and set the expected polarity
    if(H3_PORT & H3_PIN)
    {
            TIM2->CCER2|= BIT1;
            bHStatus|= BIT0;
    }
    else
    {
            TIM2->CCER2&= (u8)(~(BIT1));
    }
        bHallStartStep= bHallSteps[Run_dir][bHStatus];//得到換相步序
        if(bHallStartStep == 7)//不該出現(xiàn)的HALL狀態(tài)
        {           
            return;
        }
        TIM2->SR1=(u8)~(TIM2_IT_CC3|TIM2_IT_CC2|TIM2_IT_CC1);   
        TIM2->IER= 0x0e;//使能輸入捕獲中斷
        ComHandler();//輸出PWM信號,啟動電機(jī)
}
//捕獲中斷,即HALL狀態(tài)變化時,進(jìn)入此中斷
@near @interrupt @svlreg voidTIM2_CAP_COM_IRQHandler(void)
{
    u8bHStatus = 0;
    //Read status of H1 and set the expected polarity
    if(H1_PORT & H1_PIN)
    {
        TIM2->CCER1|= BIT1;
        bHStatus|= BIT2;
    }
    else
    {
        TIM2->CCER1&= (u8)(~(BIT1));
    }
    //Read status of H2 and set the expected polarity
    if(H2_PORT & H2_PIN)
    {
        TIM2->CCER1|= BIT5;
        bHStatus|= BIT1;
    }
    else
    {
        TIM2->CCER1&= (u8)(~(BIT5));
    }
    //Read status of H3 and set the expected polarity
    if(H3_PORT & H3_PIN)
    {
        TIM2->CCER2|= BIT1;
        bHStatus|= BIT0;
    }
    else
    {
        TIM2->CCER2&= (u8)(~(BIT1));
    }
    if(TIM2->SR1 & BIT2)
    {
        TIM2->SR1=(u8)(~TIM2_IT_CC2);
    }
    if(TIM2->SR1 & BIT1)
    {
        TIM2->SR1=(u8)(~TIM2_IT_CC1);
    }
    if(TIM2->SR1 & BIT3)
    {
        TIM2->SR1=(u8)(~TIM2_IT_CC3);
    }
    bHallStartStep= bHallSteps[Run_dir][bHStatus];//得到換相步序
    if(bHallStartStep == 7)
    { //故障,停止輸出
        TIM1->BKR&= (uint8_t)(~TIM1_BKR_MOE);//禁止PWM輸出
        PWM_A_OFF;
        PWM_B_OFF;
        PWM_C_OFF;
        return;
    }
    ComHandler();   //換相
    return;
}
//換相子函數(shù)
void    ComHandler(void)
{
    TIM1->BKR&= (uint8_t)(~TIM1_BKR_MOE);//禁止PWM輸出
    if(FaultF!=0||St_F==0)
        {PWM_A_OFF;PWM_B_OFF;PWM_C_OFF;return;}
    if(bHallStartStep!=3&&bHallStartStep!=4)
    PWM_A_OFF;
    if(bHallStartStep!=0&&bHallStartStep!=5)
    PWM_B_OFF;
    if(bHallStartStep!=1&&bHallStartStep!=2)
    PWM_C_OFF;
    //根據(jù)換相步序,打開不同的開關(guān)管,并施加正確的PWM信號
    if(bHallStartStep==0)//AB
    {
        TIM1->CCR1H= (uint8_t)(OutPwmValue >> 8);
   TIM1->CCR1L = (uint8_t)(OutPwmValue);
        PWM_B_ON;
    }
  elseif(bHallStartStep==1)    //AC
    {
        TIM1->CCR1H= (uint8_t)(OutPwmValue >> 8);
   TIM1->CCR1L = (uint8_t)(OutPwmValue);
      PWM_C_ON;
    }
    elseif(bHallStartStep==2)  //BC
    {
        TIM1->CCR2H= (uint8_t)(OutPwmValue >> 8);
   TIM1->CCR2L = (uint8_t)(OutPwmValue);
      PWM_C_ON;
    }
    elseif(bHallStartStep==3)  //BA
    {
        TIM1->CCR2H= (uint8_t)(OutPwmValue >> 8);
   TIM1->CCR2L = (uint8_t)(OutPwmValue);
      PWM_A_ON;
    }
    elseif(bHallStartStep==4)//CA
    {
        TIM1->CCR3H= (uint8_t)(OutPwmValue >> 8);
   TIM1->CCR3L = (uint8_t)(OutPwmValue);
      PWM_A_ON;
    }
    elseif(bHallStartStep==5)  //CB
    {
        TIM1->CCR3H= (uint8_t)(OutPwmValue >> 8);
   TIM1->CCR3L = (uint8_t)(OutPwmValue);
      PWM_B_ON;
    }
    TIM1->CCER1=PWM_EN1_TAB[bHallStartStep];
    TIM1->CCER2=PWM_EN2_TAB[bHallStartStep];        
    TIM1->BKR|=TIM1_BKR_MOE;//使能PWM輸出
}
(3)mian.c
/*功能:
1. PD5指示燈,上電亮,指示系統(tǒng)處于工作狀態(tài)。
2.PA4指示燈,指示電機(jī)啟停與否。
3.PA5指示燈,指示電機(jī)運行方向
4.上橋臂開關(guān)管PC1\PC2\PC3輸出可變PWM信號,以完成調(diào)速功能。
5.PG7按鍵為電機(jī)啟停控制鍵,PG6為電機(jī)方向切換鍵。
6.PF5電位器,旋轉(zhuǎn)時實現(xiàn)PWM開環(huán)調(diào)速功能。*/
#include "stm8s.h"   
#include "hall.h"
#define STM8_FREQ_MHZ 16
#define PWM_FREQUENCY 16000
static const u16 hArrPwmVal =((u16)((STM8_FREQ_MHZ * (u32)1000000)/PWM_FREQUENCY));
//PWM信號周期
//hArrPwmVal=1000
#define MINPWMPERCENT 10
#define MAXPWMPERCENT 90
#define MINVALUE MINPWMPERCENT*10
//hArrPwmVal=1000
//MINPWMPERCENT*hArrPwmVal/100簡化為MINPWMPERCENT*10
#define MAXVALUE MAXPWMPERCENT*10
//MAXPWMPERCENT*hArrPwmVal/100簡化MAXPWMPERCENT*10
//初始化按鍵,指示燈端口
void GPIO_int(void)
{
    GPIOG->DDR=GPIOG->DDR&0x3f;//PG6,PG7按鍵配置為輸入模式
    GPIOG->CR1=GPIOG->CR1|0xC0;//PG6,PG7按鍵配置為上拉輸入
    GPIOA->DDR=GPIOA->DDR|0x30;//PA4,PA5指示燈配置為輸出模式
    GPIOA->CR1=GPIOA->CR1|0x30;//PA4,PA5指示燈d配置為推挽模式
    GPIOA->ODR|=0x30;//關(guān)閉指示燈
    GPIOD->DDR=GPIOD->DDR|0x20;//PD5指示燈配置為輸出模式
    GPIOD->CR1=GPIOD->CR1|0x20;//PD5指示燈d配置為推挽模式
    GPIOD->ODR&=~0x20;//點亮指示燈,指示系統(tǒng)工作
}
//系統(tǒng)時鐘配置:內(nèi)部16M
void Clock_init(void)
{
    CLK->CKDIVR=0;
}
//電位器調(diào)速AD初始 PF5 初始化 AIN13
void AD_int(void)
{
    u8value;
    u16ADC_TDR_tmp;
    ADC2->CSR= 13; //AIN13通道選擇
    //select4MHz clock based on 16MHz fMaster (div4), single mode
    ADC2->CR1= 0x20;
    ADC2->CR2= 0x08;//數(shù)據(jù)右對齊
    ADC2->TDRH=0x20;//AIN13禁止施密特觸發(fā)  
    ADC2->CR1|= 0X01;//使能ADC
    value=30;
    while(value--);//等待ADC穩(wěn)定                  
    ADC2->CSR&= 0x7f;//清EOC標(biāo)志
    ADC2->CR1|= 0x01;//啟動AD
}
//換相電路開關(guān)管IO初始化
void PWM_IO_init(void)
{   
//PB012 下橋臂1有效
    GPIOB->DDR=GPIOB->DDR|0x7;//PB012配置為輸出模式
    GPIOB->CR1=GPIOB->CR1|0x7;//PB012推挽模式
    GPIOB->ODR&=0xf8;//關(guān)閉下橋臂開關(guān)管
    //PC123上橋臂1有效
    GPIOC->DDR=GPIOC->DDR|0x0E;//PC123配置為輸出模式
    GPIOC->CR1=GPIOC->CR1|0x0E;//PC123推挽模式
    GPIOC->ODR&=~(0x0E);//關(guān)閉上橋臂開關(guān)管
}
//高級定時器初始化配置
void Tim1_init(void)
{
    //計數(shù)器禁止、ARR預(yù)裝載禁止、邊沿對齊模式
    TIM1->CR1= 0x04;
    TIM1->SMCR= 0;//禁止從模式
    TIM1->IER= 0;//禁止所有中斷
    TIM1->CCER1= 0; //禁止PWM輸出
    TIM1->CCER2= 0;
    TIM1->CCMR1= 0x60; //PWM1模式,禁止預(yù)裝載
    TIM1->CCMR2= 0x60;
    TIM1->CCMR3= 0x60;
    //prescale= div1 @ 16MHz -> 62.5ns/count, Full scale = 4.09ms
    TIM1->PSCRH= 0;
    TIM1->PSCRL= 0;
    TIM1->ARRH=hArrPwmVal/256;//PWM周期設(shè)定
    TIM1->ARRL=hArrPwmVal%256;
    //disablerepetition counter
    TIM1->RCR= 0;
TIM1->CCR1H=0;TIM1->CCR1L=0;//占空比輸出均為0
TIM1->CCR2H=0;TIM1->CCR1L=0;
TIM1->CCR3H=0;TIM1->CCR1L=0;
    //使能定時計數(shù)器
    TIM1->CR1|= 0x01;
}
main()
{
    unsignedint tem_c=0;
    unsignedchar B_k1=0,B_k2=0;
    unsignedint ADConverValue=0;
    for(tem_c=0;tem_c<50000;tem_c++);//上電延時,等待系統(tǒng)穩(wěn)定
    Clock_init();//時鐘配置
    GPIO_int();//指示燈端口初始化
    PWM_IO_init();//開關(guān)管控制端口初始化
    Tim1_init();//高級定時器配置   
    Init_TIM2();//捕獲輸入定時器初始化配置
    enableInterrupts();
    AD_int();   
    OutPwmValue=MINVALUE;
    while(1)
    {if((GPIOG->IDR&0x80)==0x80)B_k1=0;//PG7為啟停鍵
        elseif(B_k1==0)//PG7按下時,指示燈亮
        {
            for(tem_c=0;tem_c<500;tem_c++);
            if((GPIOG->IDR&0x80)==0x00)
            {
                B_k1=1;
                if(FaultF!=0)FaultF=0;//當(dāng)前處于故障狀態(tài)
                St_F=1-St_F;//啟停標(biāo)志變量改變
               if(St_F==1)//啟動
                     {
                            TIM2_InitCapturePolarity();
                            //根據(jù)HALL狀態(tài)輸出PWM狀態(tài),啟動電機(jī)運行
                            GPIOA->ODR&=~(0x10);
                            //PA4指示燈亮,表示啟動電機(jī)
                            }
             else
                     {
                         ComHandler();//根據(jù)啟停標(biāo)志變量關(guān)閉PWM輸出。
                         GPIOA->ODR|=0x10;//電機(jī)停止運行指示燈指示
                         }
            }
        }
        if((GPIOG->IDR&0x40)==0x40)B_k2=0;//PG6為方向鍵
        elseif(B_k2==0)//PG7按下時,指示燈滅
        {
            for(tem_c=0;tem_c<500;tem_c++);
            if((GPIOG->IDR&0x40)==0x00)
            {
                B_k2=1;
                if(St_F==0)//電機(jī)處于停止?fàn)顟B(tài)
                {
                    Run_dir=1-Run_dir;//方向切換
                    GPIOA->ODR^=0x20;//PA5指示燈變換
                }
            }
        }
        if(ADC2->CSR&0x80)
        {
            ADC2->CSR&= (u8)(~0x80);//清除EOC標(biāo)志
            ADConverValue=ADC2->DRH*256+ADC2->DRL;//讀取AD轉(zhuǎn)換值
            ADC2->CR1|= 0x01;//啟動AD
                    if(ADConverValue<MINVALUE)                         ADConverValue=MINVALUE;
                    elseif(ADConverValue>MAXVALUE)                             ADConverValue=MAXVALUE;
                    OutPwmValue=ADConverValue;//賦值PWM輸出變量值
        }
        if(FaultF==1)
        {
            ComHandler();//故障時,關(guān)閉PWM輸出
            FaultF=2;
        }      
    }
}

相關(guān)帖子

回復(fù)

使用道具 舉報

ID:190973 發(fā)表于 2017-4-18 20:27 | 顯示全部樓層
這是一本書的源代碼  李家慶 李芳 葉問的
回復(fù)

使用道具 舉報

ID:191224 發(fā)表于 2017-4-19 14:56 | 顯示全部樓層
我想問51單片機(jī)能不能直接控制步進(jìn)電機(jī)或者直流電機(jī),我想制作一個單片機(jī)傳感器、控制電機(jī)正反轉(zhuǎn)’
回復(fù)

使用道具 舉報

ID:190973 發(fā)表于 2017-5-8 10:06 | 顯示全部樓層
單片機(jī)完全可以控制步進(jìn)電機(jī)和直流電機(jī)  沒問題的
回復(fù)

使用道具 舉報

ID:190973 發(fā)表于 2017-5-8 10:07 | 顯示全部樓層
可以的  51控制步進(jìn)電機(jī)和直流電機(jī)完全沒問題
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表