|
看了大概一個月的程序,基本理解了,根據(jù)自己的理解對程序做了詳盡注釋,希望能夠幫助后來者。接下來要學(xué)習(xí)ppm信號,希望能夠很快對接起來。
電路原理圖如下:
51hei.png (79.39 KB, 下載次數(shù): 134)
下載附件
2021-12-10 18:28 上傳
單片機(jī)源程序如下:
- /***************************功能說明***************************
- 本程序試驗使用STC15W408AS來驅(qū)動航模用的無感無刷三相直流馬達(dá).
- 本程序參考自網(wǎng)上的代碼(作者: 瑞生), 改良而來.
- 電路圖見文件 "BLDC-V10-實(shí)驗電路.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"
- //CMPCR1(比較器控制寄存器 1)
- #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(比較器控制寄存器 2)
- #define INVCMPO 0x80 //1: 比較器輸出取反, 0: 不取反
- #define DISFLT 0x40 //1: 關(guān)閉0.1us濾波, 0: 允許
- #define LCDTY 0x00 //關(guān)閉數(shù)字濾波功能. 數(shù)字濾波功能即為數(shù)字信號去抖動功能.
- sbit PWM0_L = P3^4;
- sbit PWM1_L = P3^5;
- sbit PWM2_L = P3^6;
- u8 Step;
- u8 PWM_Value; // 決定PWM占空比的值
- u16 RxPulseWide;
- bit B_RxOk; //定義一個bool量.
- bit B_RUN;
- u8 PWW_Set;
- u8 cnt10ms;
- u8 Rx_cnt;
- u8 TimeOut; //堵轉(zhuǎn)超時
- #define DISABLE_CMP_INT CMPCR1 &= ~0X40 // 比較器中斷標(biāo)志位清0.
- #define ENABLE_CMP_INT CMPCR1 |= 0X40 // 比較器中斷標(biāo)志位置1.
- /*********************************************************************/
- 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; PWM1_L = 1; PWM2_L=0; // Q4常開.
- CCAP0H = PWM_Value; CCAP1H=0; CCAP2H=0; // A相由占空比控制.
- ADC_CONTR = 0XCD; // ADC電源開,ADC轉(zhuǎn)換開,選擇P1.5作為ADC輸入口
- CMPCR1 = 0x9C; // 比較器使能, 下降沿中斷允許,通過ADC的P1.5口作為比較器的正極輸入端,
- //選擇外部端口P5.4作為比較器負(fù)極輸入端.
- break;
- case 1: // AC
- PWM0_L=0; PWM1_L=0; PWM2_L = 1; // Q4常開
- CCAP0H = PWM_Value; CCAP1H=0; CCAP2H=0; // A相由占空比控制.
- ADC_CONTR = 0XCC; // ADC電源開,ADC轉(zhuǎn)換開,選擇P1.4作為ADC輸入端
- CMPCR1 = 0xAC; // 比較器使能, 上升沿中斷允許,通過ADC的P1.4口作為比較器的正極輸入端
- //選擇外部端口P5.4作為比較器負(fù)極輸入端.
- break;
- case 2: // BC
- PWM0_L=0; PWM1_L=0; PWM2_L = 1; // Q2常開
- CCAP0H=0; CCAP2H=0; CCAP1H = PWM_Value; // B相由占空比控制.
- ADC_CONTR = 0XCB; // ADC電源開,ADC轉(zhuǎn)換開,選擇P1.3作為ADC輸入口測量A點(diǎn)電壓
- CMPCR1 = 0x9C; // 比較器使能, 下降沿中斷允許,通過ADC的P1.3口作為比較器的正極輸入端
- //選擇外部端口P5.4作為比較器負(fù)極輸入端.
- break;
- case 3: // BA
- PWM0_L = 1; PWM1_L=0; PWM2_L=0; // Q6常開
- CCAP0H=0; CCAP2H=0; CCAP1H = PWM_Value; // B相由占空比控制.
- ADC_CONTR = 0XCD; // ADC電源開,ADC轉(zhuǎn)換開,選擇P1.5作為ADC輸入口測量C點(diǎn)電壓
- CMPCR1 = 0xAC; // 比較器使能, 上升沿中斷允許,通過ADC的P1.5口作為比較器的正極輸入端
- //選擇外部端口P5.4作為比較器負(fù)極輸入端.
- break;
- case 4: // CA
- PWM0_L = 1; PWM1_L=0; PWM2_L=0; // Q6常開
- CCAP0H=0; CCAP1H=0; CCAP2H = PWM_Value; // C相由占空比控制.
- ADC_CONTR = 0XCC; // ADC電源開,ADC轉(zhuǎn)換開,選擇P1.4作為ADC輸入口測量B點(diǎn)電壓
- CMPCR1 = 0x9C; // 比較器使能, 下降沿中斷允許,通過ADC的P1.4口作為比較器的正極輸入端
- //選擇外部端口P5.4作為比較器負(fù)極輸入端.
- break;
- case 5: // CB
- PWM0_L=0; PWM2_L=0; PWM1_L = 1; // Q4常開
- CCAP0H=0; CCAP1H=0; CCAP2H = PWM_Value; // C相由占空比控制.
- ADC_CONTR = 0XCB; // ADC電源開,ADC轉(zhuǎn)換開,選擇P1.3作為ADC輸入口測量A點(diǎn)電壓
- CMPCR1 = 0xAC; // 比較器使能, 上升沿中斷允許,通過ADC的P1.3口作為比較器的正極輸入端
- //選擇外部端口P5.4作為比較器負(fù)極輸入端.
- break;
- default:
- break;
- }
- }
- /***************************************************************
- * PCA模塊PWM輸出設(shè)置 *
- ***************************************************************/
- void PWM_Init(void)
- {
- PWM0_L = 0; // 初始化P3^4為低電平.sbit PWM0_L = P3^4;
- PWM1_L = 0; // 初始化P3^5為低電平.sbit PWM1_L = P3^5;
- PWM2_L = 0; // 初始化P3^6為低電平.sbit PWM2_L = P3^6;
-
- P3n_push_pull(0x70); // 設(shè)置P3.4/3.5、3.6為推挽輸出. P3M1 &= ~(bitn), P3M0 |= (bitn)
-
- CMOD = 5 << 1; //5(0101)左移1位,設(shè)置PCA的輸入時鐘源為系統(tǒng)時鐘的1/4,即PWM頻率=24M/4.
-
- CH=0; // PCA(Programmable Counter Array)清零
- CL=0; //
-
- PCA_PWM0 = 0X00; // 對PCA_PWM0模塊0清0,并設(shè)置PWM為8位(EBS0[1:0]=00).
- CCAP0H = 0x00; // 重載值為{EPCnH,CCAPnH[7:0]}.
- CCAP0L = 0x00; // 比較值為{EPCnL,CCAPnL[7:0]}.
- CCAPM0 = 0x42; // 設(shè)置PCA模塊0的控制模式(0100 0010).ECOM0=1,允許PCA模塊0的比較功能.
- // PWM0=1,設(shè)置PCA模塊0為脈寬調(diào)制輸出功能.
- // 當(dāng)PCA 模塊工作在8位PWM模式時,{0,CL[7:0]}與{EPCnL,CCAPnL[7:0]}
- // 中的值進(jìn)行比較,小于,輸出低電平,大于等于輸出高電平.
- PCA_PWM1 = 0X00; // 對PCA_PWM0模塊0清0,并設(shè)置PWM為8位(EBS0[1:0]=00).
- CCAP1H = 0x00; // 重載值為{EPCnH,CCAPnH[7:0]}.
- CCAP1L = 0x00; // 比較值為{EPCnL,CCAPnL[7:0]}.
- CCAPM1 = 0x42; // 設(shè)置PCA模塊1的控制模式(0100 0010).ECOM0=1,允許PCA模塊1的比較功能.
- // PWM1=1,設(shè)置PCA模塊1為脈寬調(diào)制輸出功能.
- // 當(dāng)PCA 模塊工作在8位PWM模式時,{0,CL[7:0]}與{EPCnL,CCAPnL[7:0]}
- // 中的值進(jìn)行比較,小于,輸出低電平,大于等于輸出高電平.
- PCA_PWM2 = 0X00; // 對PCA_PWM2模塊進(jìn)行設(shè)置.其中,EBS2[1:0]=00,PWM為8位.
- CCAP2H = 0x00; // 重載值為{EPCnH,CCAPnH[7:0]}.
- CCAP2L = 0x00; // 比較值為{EPCnL,CCAPnL[7:0]}.
- CCAPM2 = 0x42; // 設(shè)置PCA模塊2的控制模式(0100 0010).ECOM0=1,允許PCA模塊2的比較功能.
- // PWM2=1,設(shè)置PCA模塊2為脈寬調(diào)制輸出功能.
- // 當(dāng)PCA 模塊工作在8位PWM模式時,{0,CL[7:0]}與{EPCnL,CCAPnL[7:0]}
- // 中的值進(jìn)行比較,小于,輸出低電平,大于等于輸出高電平.
- CR = 1; // PCA計數(shù)允許控制位,1:啟動PCA計數(shù).
- }
- void ADC_Init(void)
- {
- P1n_pure_input(0x38); // 設(shè)置P1.3/1.4/1.5口為高阻輸入(電流既不能流入也不能流出).P1M1 |= (bitn), P1M0 &= ~(bitn)
- P1ASF = 0X38; // 開通P1.3 P1.4 P1.5的AD輸入口(0011 1000)
- }
- /***************************************************************
- * 比較器中斷服務(wù)函數(shù) *
- ***************************************************************/
- void CMP_INT(void) interrupt 21
- {
- CMPCR1 &= ~0X40; // 軟件清除中斷標(biāo)志位
- if(Step<5) Step++;
- else Step = 0;
- StepXL(); // 進(jìn)入換相程序. 在換相程序中,已經(jīng)對比較器的正負(fù)極輸入端做了設(shè)置.
- // ADC的P1.4/P1.5/P1.6口作為比較器的正極輸入端,選擇外部端口P5.4作為比較器負(fù)極輸入端.
- TimeOut = 10; // 在執(zhí)行完比較器中斷函數(shù)后,賦值TimeOut=10.
- }
- /***************************************************************
- * 比較器初始化設(shè)置 *
- ***************************************************************/
- void CMP_Init(void)
- {
- CMPCR1 = 0X8C; // 1000 1100 比較器使能,比較器正負(fù)極輸入端設(shè)置, 通過ADC_CHS位選擇比較器的正極輸入端,選擇P5.4作為負(fù)極.
- CMPCR2 = 60; // 60個時鐘濾波
- P5n_pure_input(0x10); // 設(shè)置P5.4口為高阻輸入(電流既不能流入也不能流出).P5M1 |= (bitn), P5M0 &= ~(bitn)
- }
- /***************************************************************
- * 電機(jī)啟動函數(shù) *
- ***************************************************************/
- u8 StartMotor(void)
- {
- u16 timer,i;
- DISABLE_CMP_INT; // 比較器中斷標(biāo)志位清0,不產(chǎn)生比較中斷.
- PWM_Value = 30; // 設(shè)置占空比初值
- Step = 0;
- StepXL(); // ∵step=0, ∴ 進(jìn)入AB相導(dǎo)通的初始位置
- Delay_n_ms(5); // 延時5ms
- 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();
- }
- }
- /***************************************************************
- * 定時器T0初始化函數(shù) *
- ***************************************************************/
- void T0_Init(void) // 這里設(shè)置TH0/TL0=0,定時器T0為16位不自動重載,
- {
- Timer0_AsTimer(); // 設(shè)置定時器T0用做定時器. TMOD &= ~(1<<2)
- Timer0_12T(); // 定時器0 12分頻. AUXR &= ~(1<<7)
- Timer0_16bit(); // 定時器0 16位不自動重載模式. TMOD = (TMOD & ~0x03) | 0x01
- Timer0_Gate_INT0_P32(); // T0_GATE置1, 只有在INT0腳為高及TR0=1時才可啟動定時器T0.TMOD |= (1<<3).
- TH0 = 0;
- TL0 = 0;
- TR0 = 1; // 定時器 T0 準(zhǔn)備工作.
- ET0 = 1; // 定時器 T0 的溢出中斷允許位.
- }
- /***************************************************************
- * 定時器T0中斷服務(wù)函數(shù) *
- ***************************************************************/
- void T0_Interrupt(void) interrupt 1
- {
- Rx_cnt = 0; // 一旦出現(xiàn)溢出, 則開始的n個脈沖無效
- RxPulseWide = 1000; // 停止
- B_RxOk = 1; // 在執(zhí)行完T0中斷服務(wù)函數(shù)后,給B_RxOk賦值.
- }
- /***************************************************************
- * INT0(外部中斷0)中斷服務(wù)函數(shù) *
- ***************************************************************/
- void INT0_int (void) interrupt 0
- {
- u16 j;
- TR0 = 0;
- TH0 = 0;
- TL0 = 0;
- j = ((u16)TH0 << 8) + TL0;
- TR0 = 1; // 定時器T0的運(yùn)行控制位,允許T0計數(shù), 這時候TH0、TL0就開始計數(shù)了.
- 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; // unsigned int.
- PWM_Init(); // 設(shè)置P3.4/3.5、3.6為推挽輸出. 當(dāng)PCA 模塊工作在8位PWM模式時,{0,CL[7:0]}與{EPCnL,CCAPnL[7:0]}
- // 中的值進(jìn)行比較并決定輸出高電平還是低電平.此電平作為
- ADC_Init(); // 開通P1.3 P1.4 P1.5的AD輸入口.√
- CMP_Init(); // 比較器初始化設(shè)置. 對比較器正負(fù)極輸入端進(jìn)行設(shè)置, 通過ADC_CHS位選擇比較器的正極輸入端,選擇P5.4作為負(fù)極.
- T0_Init(); // 定時器T0初始化設(shè)置, 定時器0 12分頻. (AUXR &= ~(1<<7)).
- IE0 = 0; // 外部中斷0(INT0/P3.2)中斷請求標(biāo)志位清零.
- EX0 = 1; // 外部中斷0(INT0)中斷允許.
- IT0 = 1; // 外部中斷0(INT0)為下降沿觸發(fā).
-
- 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) // 在執(zhí)行完比較器中斷函數(shù)后,進(jìn)入此模塊.
- {
- if(--TimeOut == 0)
- {
- CCAP0H=0; CCAP1H=0; CCAP2H=0; // PCA模塊復(fù)原.
- PWM0_L=0; PWM1_L=0; PWM2_L=0; // P3.4/3.5、3.6腳復(fù)原.
- 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) // 在執(zhí)行完T0中斷服務(wù)函數(shù)后,執(zhí)行此模塊.
- {
- 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; // B_RUN只是一個標(biāo)志位,便于管理
- 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)
- {
- 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ù)制代碼
51hei.png (7.77 KB, 下載次數(shù): 112)
下載附件
2021-12-10 18:29 上傳
上圖Keil代碼下載:
51-STC15W408AS-電調(diào).rar
(111.84 KB, 下載次數(shù): 436)
2021-12-10 17:27 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|
評分
-
查看全部評分
|