|
我給你來個驅(qū)動航模用的無傳感器無刷三相直流馬達(dá)程序
BLDC-20腳MCU-實(shí)驗(yàn)電路.jpg (168.68 KB, 下載次數(shù): 31)
下載附件
2019-9-14 07:13 上傳
- /*---------------------------------------------------------------------*/
- /* --- STC MCU International Limited ----------------------------------*/
- /* --- STC 1T Series MCU Demo Programme -------------------------------*/
- /* --- Mobile: 13922805190 --------------------------------------------*/
- /* --- Fax: 0513-55012956,55012947,55012969 ---------------------------*/
- /* --- Tel: 0513-55012928,55012929,55012966 ---------------------------*/
- /* --- Web: www.GXWMCU.com www.stcmcu.com ---------------------------*/
- /* --- QQ: 800003751 -------------------------------------------------*/
- /* 如果要在程序中使用此代碼,請?jiān)诔绦蛑凶⒚魇褂昧撕昃Э萍嫉馁Y料及程序 */
- /*---------------------------------------------------------------------*/
- /************* 功能說明 **************
- 本程序試驗(yàn)使用STC15W401AS-35I-SOP16<RMB1.6>來驅(qū)動航模用的無傳感器無刷三相直流馬達(dá).
- 本程序參考自網(wǎng)上的代碼(作者: 瑞生), 改良而來.
- 電路圖見文件 "BLDC-V10-實(shí)驗(yàn)電路.pdf".
- 控制信號由P3.2輸入正脈沖信號, 間隔5~20ms, 脈沖寬度1.000~1.610ms.
- 1.160ms開始啟動, 1.610ms為最高速度, 分辨率為2us.
- 本程序僅僅是簡單控制, 軟件沒有處理 過0延時30度切換 過流檢測.
- 由于過0檢測部分有RC濾波, 所以改變電容值可以大約的對應(yīng)在最高速時延時30度的時間.
- 有意者可自行完善電路和程序.
- ******************************************/
- #define MAIN_Fosc 24000000L //定義主時鐘
- #include "STC15Fxxxx.H"
- #define MCU_PIN 16 /* 選擇MCU引腳數(shù), 只支持16或20腳(28腳或32腳跟20腳一樣) */
- //CMPCR1
- #define CMPEN 0x80 //1: 允許比較器, 0: 禁止,關(guān)閉比較器電源
- #define CMPIF 0x40 //比較器中斷標(biāo)志, 包括上升沿或下降沿中斷, 軟件清0
- #define PIE 0x20 //1: 比較結(jié)果由0變1, 產(chǎn)生上升沿中斷
- #define NIE 0x10 //1: 比較結(jié)果由1變0, 產(chǎn)生下降沿中斷
- #define PIS 0x08 //輸入正極性選擇, 0: 選擇外部P5.5做正輸入, 1: 由ADCIS[2:0]所選擇的ADC輸入端做正輸入.
- #define NIS 0x04 //輸入負(fù)極性選擇, 0: 選擇內(nèi)部BandGap電壓BGv做負(fù)輸入, 1: 選擇外部P5.4做輸入.
- #define CMPOE 0x02 //1: 允許比較結(jié)果輸出到P1.2, 0: 禁止.
- #define CMPRES 0x01 //比較結(jié)果, 1: CMP+電平高于CMP-, 0: CMP+電平低于CMP-, 只讀
- //CMPCR2
- #define INVCMPO 0x80 //1: 比較器輸出取反, 0: 不取反
- #define DISFLT 0x40 //1: 關(guān)閉0.1uF濾波, 0: 允許
- #define LCDTY 0x00 //0~63, 比較結(jié)果變化延時周期數(shù)
- #if (MCU_PIN == 20)
- sbit PWM2_L = P3^4;
- sbit PWM1_L = P3^5;
- sbit PWM0_L = P3^6;
- #endif
- #if (MCU_PIN == 16)
- sbit PWM2_L = P5^5;
- sbit PWM1_L = P3^3;
- sbit PWM0_L = P3^6;
- #endif
- u8 Step;
- u8 PWM_Value; // 決定PWM占空比的值
- u16 RxPulseWide;
- bit B_RxOk;
- bit B_RUN;
- u8 PWW_Set;
- u8 cnt10ms;
- u8 Rx_cnt;
- u8 TimeOut; //堵轉(zhuǎn)超時
- #define DISABLE_CMP_INT CMPCR1 &= ~0X40 // 關(guān)閉比較器中斷
- #define ENABLE_CMP_INT CMPCR1 |= 0X40 // 打開比較器中斷
- /*************************/
- void Delay_n_ms(u8 dly)
- {
- u16 j;
- do
- {
- j = MAIN_Fosc / 13000; //延時1ms, 主程序在此節(jié)拍下運(yùn)行
- while(--j) ;
- }while(--dly);
- }
- void delay_us(u8 us)
- {
- do
- {
- NOP(20); //@24MHz
- }
- while(--us);
- }
- void StepXL(void) // 換相序列函數(shù)
- {
- switch(Step)
- {
- case 0: // AB
- PWM0_L=0; PWM2_L=0;
- CCAP0H = PWM_Value; CCAP1H=0; CCAP2H=0; // 打開A相的高端
- PWM1_L = 1; // 打開B相的低端
- ADC_CONTR = 0XED; // 選擇P1.5作為ADC輸入 即c相電壓
- CMPCR1 = 0x9C; //bit7=1 允許比較器, bit4=1 比較結(jié)果由1變0, 產(chǎn)生下降沿中斷 (不能響應(yīng)下降沿中斷?)
- break;
- case 1: // AC
- PWM0_L=0; PWM1_L=0;
- CCAP0H = PWM_Value; CCAP1H=0; CCAP2H=0; // 打開A相的高端
- PWM2_L = 1; // 打開C相的低端
- ADC_CONTR = 0XEC; // 選擇P1.4作為ADC輸入 即B相電壓
- CMPCR1 = 0xAC; //上升沿中斷
-
- break;
- case 2: // BC
- PWM0_L=0; PWM1_L=0;
- CCAP0H=0; CCAP2H=0; CCAP1H = PWM_Value; // 打開B相的高端
- PWM2_L = 1; // 打開C相的低端
- ADC_CONTR = 0XEB; // 選擇P1.3作為ADC輸入 即a相電壓
- CMPCR1 = 0x9C; //下降沿中斷
- break;
- case 3: // BA
- PWM1_L=0; PWM2_L=0;
- CCAP0H=0; CCAP2H=0; CCAP1H = PWM_Value; // 打開B相的高端
- PWM0_L = 1; // 打開A相的低端
- ADC_CONTR = 0XED; // 選擇P1.5作為ADC輸入 即c相電壓
- CMPCR1 = 0xAC; //上升沿中斷
-
- break;
- case 4: // CA
- PWM1_L=0; PWM2_L=0;
- CCAP0H=0; CCAP1H=0; CCAP2H = PWM_Value; // 打開C相的高端
- PWM0_L = 1; // 打開A相的低端
- ADC_CONTR = 0XEC; // 選擇P1.4作為ADC輸入 即B相電壓
- CMPCR1 = 0x9C; //下降沿中斷
- break;
- case 5: // CB
- PWM0_L=0; PWM2_L=0;
- CCAP0H=0; CCAP1H=0; CCAP2H = PWM_Value;// 打開C相的高端
- PWM1_L = 1; // 打開B相的低端
- ADC_CONTR = 0XEB; // 選擇P1.3作為ADC輸入 即a相電壓
- CMPCR1 = 0xAC; //上升沿中斷
-
- break;
-
- default:
- break;
- }
- }
- void PWM_Init(void)
- {
- PWM0_L = 0;
- PWM1_L = 0;
- PWM2_L = 0;
-
- #if (MCU_PIN == 20)
- P3n_push_pull(0x70);
- #endif
- #if (MCU_PIN == 16)
- P3n_push_pull(0x48);
- P5n_push_pull(0x20);
- #endif
- // CMOD = 1 << 1; //選擇系統(tǒng)時鐘/2為時鐘源,即PWM頻率=24M/2/256=46.9K
- CMOD = 5 << 1; //選擇系統(tǒng)時鐘/4為時鐘源,即PWM頻率=24M/4/256=23.4K
- // CMOD = 6 << 1; //選擇系統(tǒng)時鐘/6為時鐘源,即PWM頻率=24M/6/256=15.6K
- CL=0; // PCA計(jì)數(shù)器清零
- CH=0;
-
- PCA_PWM0 = 0X00;
- CCAP0H=0; // 初始化占空比為0% H的值裝載到L中
- CCAP0L=0;
- CCAPM0=0x42; // 設(shè)置為PWM模式
-
- PCA_PWM1 = 0X00;
- CCAP1H=0; // 初始化占空比為0%
- CCAP1L=0;
- CCAPM1=0x42; // 設(shè)置為PWM模式
-
- PCA_PWM2 = 0X00;
- CCAP2H=0; // 初始化占空比為0%
- CCAP2L=0;
- CCAPM2=0x42; // 設(shè)置為PWM模式
-
- CR = 1;
- }
- void ADC_Init(void)
- {
- P1n_pure_input(0x38);
- P1ASF = 0X38; // 開通P1.3 P1.4 P1.5的AD輸入口
- }
- void CMP_INT(void) interrupt 21
- {
- CMPCR1 &= ~0X40; // 需軟件清除中斷標(biāo)志位
- if(Step<5) Step++;
- else Step = 0;
- StepXL();
- TimeOut = 10; //10ms超時
- }
- void CMP_Init(void)
- {
- CMPCR1 = 0X8C; // 1000 1100 打開比較器,P5.4作為比較器的反相輸入端,ADC引腳作為正輸入端
- CMPCR2 = 60; // 60個時鐘濾波
- P5n_pure_input(0x10);
- }
- u8 StartMotor(void)
- {
- u16 timer,i;
- DISABLE_CMP_INT; // 禁止比較器中斷
- PWM_Value = 30; // 初始占空比=16/256=6%
- Step = 0;
- StepXL(); // 初始位置
- Delay_n_ms(5);//delay_ms(5);
- timer = 300;
- while(1)
- {
- for(i=0; i<timer; i++) delay_us(50); //
- timer -= timer /15 + 1;
- if(timer < 25) return(1);
- if( Step < 5) Step++;
- else Step = 0;
- StepXL();
- }
- }
- void T0_Iint(void)
- {
- Timer0_AsTimer(); /* 時器0用做定時器 */
- Timer0_12T(); /* Timer0 clodk = fo/12 12分頻, default */
- Timer0_16bit();
- Timer0_Gate_INT0_P32(); /* 時器0由外部INT0高電平允許定時計(jì)數(shù) */
- TH0 = 0;
- TL0 = 0;
- TR0 = 1; // 打開定時器0
- ET0 = 1;// 允許ET0中斷
- }
- void T0_Interrupt(void) interrupt 1
- {
- Rx_cnt = 0; //一旦出現(xiàn)溢出, 則開始的n個脈沖無效
- RxPulseWide = 1000; //停止
- B_RxOk = 1; //虛擬收到一個脈沖
- }
- /********************* INT0中斷函數(shù) *************************/
- void INT0_int (void) interrupt INT0_VECTOR
- {
- u16 j;
-
- TR0 = 0;
- j = ((u16)TH0 << 8) + TL0;
- TH0 = 0;
- TL0 = 0;
- TR0 = 1;
- if(++Rx_cnt >= 5) Rx_cnt = 5;
- j >>= 1; //為了好處理, 轉(zhuǎn)成單位為us
- if((j >= 800) && (j <= 2000) && (Rx_cnt == 5))
- {
- RxPulseWide = j;
- B_RxOk = 1; //標(biāo)志收到一個脈沖
- }
- }
- /**********************************************/
- void main(void)
- {
- u16 j;
- PWM_Init();
- ADC_Init();
- CMP_Init();
- T0_Iint();
- IE0 = 0; // 清除外中斷0標(biāo)志位
- EX0 = 1; // INT0 Enable
- IT0 = 1; //INT0 下降沿中斷
-
- RxPulseWide = 1000;
- PWW_Set = 0;
- cnt10ms = 0;
- Rx_cnt = 0;
- TimeOut = 0;
- EA = 1; // 打開總中斷
-
- while (1)
- {
- Delay_n_ms(1); //延時1ms, 主程序在此節(jié)拍下運(yùn)行
- if(TimeOut > 0)
- {
- if(--TimeOut == 0) //堵轉(zhuǎn)超時
- {
- CCAP0H=0; CCAP1H=0; CCAP2H=0; // 占空比為0
- PWM0_L=0; PWM1_L=0; PWM2_L=0;
- DISABLE_CMP_INT; // 關(guān)比較器中斷
- Delay_n_ms(250); //堵轉(zhuǎn)時,延時1秒再啟動
- Delay_n_ms(250);
- Delay_n_ms(250);
- Delay_n_ms(250);
- RxPulseWide = 1000;
- PWW_Set = 0;
- PWM_Value = 0;
- B_RxOk = 0;
- B_RUN = 0;
- Rx_cnt = 0;
- TimeOut = 0;
- }
- }
-
- if(B_RxOk) //收到一個脈沖
- {
- B_RxOk = 0;
- j = RxPulseWide;
- if(j >= 1100) // 1100~1610對應(yīng)PWM占空比值0~255
- {
- j = (j - 1100) >> 1; //2us對應(yīng)PWM一個步進(jìn)
- if(j > 256) j = 255;
- }
- else j = 0;
- PWW_Set = (u8)j;
- }
-
- if(!B_RUN && (PWW_Set >= 30)) // PWM_Set >= 30, 并且馬達(dá)未運(yùn)行, 則啟動馬達(dá)
- {
- StartMotor(); // 啟動馬達(dá)
- CMPCR1 &= ~0X40; // 需軟件清除中斷標(biāo)志位
- ENABLE_CMP_INT; // 打開比較器中斷
- B_RUN = 1;
- TimeOut = 0;
- }
-
-
- if(++cnt10ms >= 10) // 10ms時隙
- {
- cnt10ms = 0;
- if(B_RUN)
- {
- if(PWM_Value < PWW_Set) PWM_Value++;
- if(PWM_Value > PWW_Set) PWM_Value--;
- if(PWM_Value < 20) // 停轉(zhuǎn)
- {
- PWM_Value = 0;
- B_RUN = 0;
- CCAP0H=0; CCAP1H=0; CCAP2H=0; // 占空比為0
- PWM0_L=0; PWM1_L=0; PWM2_L=0;
- DISABLE_CMP_INT; // 關(guān)比較器中斷
- }
- }
- }
-
- }
- }
復(fù)制代碼
|
|