成品網(wǎng)站好嗎萬江專業(yè)網(wǎng)站快速排名
【電機(jī)控制】基于STC8H1K28的六步換向——方波驅(qū)動(dòng)(軟件篇)
文章目錄
- @[TOC](文章目錄)
- 前言
- 一、main.c
- 二、GPIO.c
- 三、PWMA.c
- 四、ADC.c
- 五、CMP.c
- 六、Timer.c
- 七、PMSM.c
- 八、參考資料
- 總結(jié)
文章目錄
- @[TOC](文章目錄)
- 前言
- 一、main.c
- 二、GPIO.c
- 三、PWMA.c
- 四、ADC.c
- 五、CMP.c
- 六、Timer.c
- 七、PMSM.c
- 八、參考資料
- 總結(jié)
前言
【電機(jī)控制】STC8H無感方波驅(qū)動(dòng)—反電動(dòng)勢(shì)過零檢測(cè)六步換向法
提示:以下是本篇文章正文內(nèi)容,下面案例可供參考
一、main.c
void main(void)
{GPIO_Init(); //IO初始化Uart1_Init(); //串口初始化PWMA_config(); //PWMA初始化ADC_config(); //ADC初始化CMP_config(); //比較器初始化Timer0_config(); // Timer0初始化函數(shù) 4ms定時(shí)器,用于事件處理Timer3_Config(); // Timer3初始化函數(shù) 1ms定時(shí)器,用于換向時(shí)間計(jì)算Timer4_Config(); // Timer4初始化函數(shù) 4us定時(shí)器,用于計(jì)算六步換向PWW_Set = 0; //初始PWM設(shè)定值TimeOut = 0; //超時(shí)設(shè)定值初始化EA = 1; // 打開總中斷while (1){Event_Deal();}
}
二、GPIO.c
配置IO
void GPIO_Init(void)
{P2n_standard(0xf8);P3n_standard(0xbf);P5n_standard(0x10);
}
三、PWMA.c
u8 PWM_Value; // 決定PWM占空比的值
u8 PWW_Set; //目標(biāo)PWM設(shè)置
void PWMA_config(void)
{P_SW2 |= 0x80; //SFR enable PWM1 = 0;PWM1_L = 0;PWM2 = 0;PWM2_L = 0;PWM3 = 0;PWM3_L = 0;P1n_push_pull(0x3f);
// 預(yù)分頻寄存器, 分頻 Fck_cnt = Fck_psc/(PSCR[15:0}+1),
// 邊沿對(duì)齊PWM頻率 = SYSclk/((PSCR+1)*(AAR+1)),
// 中央對(duì)齊PWM頻率 = SYSclk/((PSCR+1)*(AAR+1)*2).PWMA_PSCR = 3; PWMA_DTR = 24; // 死區(qū)時(shí)間配置, n=0~127: DTR= n T, 0x80 ~(0x80+n), n=0~63: DTR=(64+n)*2T, // 0xc0 ~(0xc0+n), n=0~31: DTR=(32+n)*8T, 0xE0 ~(0xE0+n), n=0~31: DTR=(32+n)*16T,PWMA_ARR = 255; // 自動(dòng)重裝載寄存器, 控制PWM周期PWMA_CCER1 = 0;PWMA_CCER2 = 0;PWMA_SR1 = 0;PWMA_SR2 = 0;PWMA_ENO = 0;PWMA_PS = 0;PWMA_IER = 0;
// PWMA_ISR_En = 0;PWMA_CCMR1 = 0x68; // 通道模式配置, PWM模式1, 預(yù)裝載允許PWMA_CCR1 = 0; // 比較值, 控制占空比(高電平時(shí)鐘數(shù))PWMA_CCER1 |= 0x05; // 開啟比較輸出, 高電平有效PWMA_PS |= 0; // 選擇IO, 0:選擇P1.0 P1.1, 1:選擇P2.0 P2.1, 2:選擇P6.0 P6.1,
// PWMA_ENO |= 0x01; // IO輸出允許, bit7: ENO4N, bit6: ENO4P, bit5: ENO3N, bit4: ENO3P, bit3: ENO2N, bit2: ENO2P, bit1: ENO1N, bit0: ENO1P
// PWMA_IER |= 0x02; // 使能中斷PWMA_CCMR2 = 0x68; // 通道模式配置, PWM模式1, 預(yù)裝載允許PWMA_CCR2 = 0; // 比較值, 控制占空比(高電平時(shí)鐘數(shù))PWMA_CCER1 |= 0x50; // 開啟比較輸出, 高電平有效PWMA_PS |= (0<<2); // 選擇IO, 0:選擇P1.2 P1.3, 1:選擇P2.2 P2.3, 2:選擇P6.2 P6.3,
// PWMA_ENO |= 0x04; // IO輸出允許, bit7: ENO4N, bit6: ENO4P, bit5: ENO3N, bit4: ENO3P, bit3: ENO2N, bit2: ENO2P, bit1: ENO1N, bit0: ENO1P
// PWMA_IER |= 0x04; // 使能中斷PWMA_CCMR3 = 0x68; // 通道模式配置, PWM模式1, 預(yù)裝載允許PWMA_CCR3 = 0; // 比較值, 控制占空比(高電平時(shí)鐘數(shù))PWMA_CCER2 |= 0x05; // 開啟比較輸出, 高電平有效PWMA_PS |= (0<<4); // 選擇IO, 0:選擇P1.4 P1.5, 1:選擇P2.4 P2.5, 2:選擇P6.4 P6.5,
// PWMA_ENO |= 0x10; // IO輸出允許, bit7: ENO4N, bit6: ENO4P, bit5: ENO3N, bit4: ENO3P, bit3: ENO2N, bit2: ENO2P, bit1: ENO1N, bit0: ENO1P
// PWMA_IER |= 0x08; // 使能中斷PWMA_BKR = 0x80; // 主輸出使能 相當(dāng)于總開關(guān)PWMA_CR1 = 0x81; // 使能計(jì)數(shù)器, 允許自動(dòng)重裝載寄存器緩沖, 邊沿對(duì)齊模式, 向上計(jì)數(shù), bit7=1:寫自動(dòng)重裝載寄存器緩沖(本周期不會(huì)被打擾), =0:直接寫自動(dòng)重裝載寄存器本(周期可能會(huì)亂掉)PWMA_EGR = 0x01; //產(chǎn)生一次更新事件, 清除計(jì)數(shù)器和與分頻計(jì)數(shù)器, 裝載預(yù)分頻寄存器的值
// PWMA_ISR_En = PWMA_IER; //設(shè)置標(biāo)志允許通道1~4中斷處理
}// PWMA_PS = (0<<6)+(0<<4)+(0<<2)+0; //選擇IO, 4項(xiàng)從高到低(從左到右)對(duì)應(yīng)PWM1 PWM2 PWM3 PWM4, 0:選擇P1.x, 1:選擇P2.x, 2:選擇P6.x,
// PWMA_PS PWM4N PWM4P PWM3N PWM3P PWM2N PWM2P PWM1N PWM1P
// 00 P1.7 P1.6 P1.5 P1.4 P1.3 P1.2 P1.1 P1.0
// 01 P2.7 P2.6 P2.5 P2.4 P2.3 P2.2 P2.1 P2.0
// 02 P6.7 P6.6 P6.5 P6.4 P6.3 P6.2 P6.1 P6.0
// 03 P3.3 P3.4 -- -- -- -- -- --
四、ADC.c
void ADC_config(void) //ADC初始化函數(shù)(為了使用ADC輸入端做比較器信號(hào), 實(shí)際沒有啟動(dòng)ADC轉(zhuǎn)換)
{P1n_pure_input(0xc0); //設(shè)置為高阻輸入P0n_pure_input(0x0f); //設(shè)置為高阻輸入ADC_CONTR = 0x80 + 6; //ADC on + channelADCCFG = RES_FMT + ADC_SPEED;P_SW2 |= 0x80; //訪問XSFRADCTIM = CSSETUP + CSHOLD + SMPDUTY;
}
//========================================================================
// 函數(shù): u16 Get_ADC10bitResult(u8 channel)) //channel = 0~15
//========================================================================
u16 Get_ADC10bitResult(u8 channel) //channel = 0~15
{u8 i;ADC_RES = 0;ADC_RESL = 0;ADC_CONTR = 0x80 | ADC_START | channel; NOP(5); //
// while((ADC_CONTR & ADC_FLAG) == 0) ; //等待ADC結(jié)束i = 255;while(i != 0){i--;if((ADC_CONTR & ADC_FLAG) != 0) break; //等待ADC結(jié)束}ADC_CONTR &= ~ADC_FLAG;return ((u16)ADC_RES * 256 + (u16)ADC_RESL);
}
五、CMP.c
void CMP_config(void) //比較器初始化程序
{CMPCR1 = 0x8C; // 1000 1100 打開比較器,P3.6作為比較器的反相輸入端,ADC引腳作為正輸入端 CMPCR2 = 60; //60個(gè)時(shí)鐘濾波 比較結(jié)果變化延時(shí)周期數(shù), 0~63P3n_pure_input(0x40); //CMP-(P3.6)設(shè)置為高阻.P_SW2 |= 0x80; //SFR enable
// CMPEXCFG |= (0<<6); //bit7 bit6: 比較器遲滯輸入選擇: 0: 0mV, 1: 10mV, 2: 20mV, 3: 30mV
// CMPEXCFG |= (0<<2); //bit2: 輸入負(fù)極性選擇, 0: 選擇P3.6做輸入, 1: 選擇內(nèi)部BandGap電壓BGv做負(fù)輸入.
// CMPEXCFG |= 0; //bit1 bit0: 輸入正極性選擇, 0: 選擇P3.7做輸入, 1: 選擇P5.0做輸入, 2: 選擇P5.1做輸入, 3: 選擇ADC輸入(由ADC_CHS[3:0]所選擇的ADC輸入端做正輸入).
// CMPEXCFG = (0<<6)+(0<<2)+3;
}void CMP_ISR(void) interrupt 21 //比較器中斷函數(shù), 檢測(cè)到反電動(dòng)勢(shì)過0事件
{u8 i;CMPCR1 &= ~0x40; // 需軟件清除中斷標(biāo)志位if(XiaoCiCnt == 0) //消磁后才檢測(cè)過0事件, XiaoCiCnt=1:需要消磁, =2:正在消磁, =0已經(jīng)消磁{T4T3M &= ~(1<<3); // Timer3停止運(yùn)行if(B_Timer3_OverFlow) //切換時(shí)間間隔(Timer3)有溢出{B_Timer3_OverFlow = 0;PhaseTime = 8000; //換相時(shí)間最大8ms, 2212電機(jī)12V空轉(zhuǎn)最高速130us切換一相(200RPS 12000RPM), 480mA}else{PhaseTime = (((u16)T3H << 8) + T3L) >> 1; //單位為1usif(PhaseTime >= 8000) PhaseTime = 8000; //換相時(shí)間最大8ms, 2212電機(jī)12V空轉(zhuǎn)最高速130us切換一相(200RPS 12000RPM), 480mA}T3H = 0; T3L = 0;T4T3M |= (1<<3); //Timer3開始運(yùn)行PhaseTimeTmp[TimeIndex] = PhaseTime; //保存一次換相時(shí)間if(++TimeIndex >= 8) TimeIndex = 0; //累加8次for(PhaseTime=0, i=0; i<8; i++) PhaseTime += PhaseTimeTmp[i]; //求8次換相時(shí)間累加和PhaseTime = PhaseTime >> 4; //求8次換相時(shí)間的平均值的一半, 即30度電角度if((PhaseTime >= 40) && (PhaseTime <= 1000)) TimeOut = 125; //堵轉(zhuǎn)500ms超時(shí)if( PhaseTime >= 60) PhaseTime -= 40; //修正由于濾波電容引起的滯后時(shí)間else PhaseTime = 20;// PhaseTime = 20; //只給20us, 則無滯后修正, 用于檢測(cè)濾波電容引起的滯后時(shí)間T4T3M &= ~(1<<7); //Timer4停止運(yùn)行PhaseTime = PhaseTime << 1; //2個(gè)計(jì)數(shù)1usPhaseTime = 0 - PhaseTime;T4H = (u8)(PhaseTime >> 8); //裝載30度角延時(shí)T4L = (u8)PhaseTime;T4T3M |= (1<<7); //Timer4開始運(yùn)行XiaoCiCnt = 1; //1:需要消磁, 2:正在消磁, 0已經(jīng)消磁}
}
六、Timer.c
void Timer0_config(void) //Timer0初始化函數(shù)
{Timer0_16bitAutoReload(); // T0工作于16位自動(dòng)重裝Timer0_12T();TH0 = (65536UL-MAIN_Fosc/12 / 250) / 256; //4msv4000us=4msTL0 = (65536UL-MAIN_Fosc/12 / 250) % 256;TR0 = 1; // 打開定時(shí)器0ET0 = 1;// 允許ET0中斷
}
void Timer0_ISR(void) interrupt 1 //Timer0中斷函數(shù), 20us
{B_4ms = 1; //4ms定時(shí)標(biāo)志
}
//============================ timer3初始化函數(shù) ============================================
void Timer3_Config(void)
{P_SW2 |= 0x80; //SFR enable T4T3M &= 0xf0; //停止計(jì)數(shù), 定時(shí)模式, 12T模式, 不輸出時(shí)鐘T3H = 0;T3L = 0;T3T4PIN = 0x01; //選擇IO, 0x00: T3--P0.4, T3CLKO--P0.5, T4--P0.6, T4CLKO--P0.7; 0x01: T3--P0.0, T3CLKO--P0.1, T4--P0.2, T4CLKO--P0.3;IE2 |= (1<<5); //允許中斷T4T3M |= (1<<3); //開始運(yùn)行
}
//=========================== timer3中斷函數(shù) =============================================
void timer3_ISR (void) interrupt TIMER3_VECTOR
{B_Timer3_OverFlow = 1; //溢出標(biāo)志
}
//============================ timer4初始化函數(shù) ============================================
void Timer4_Config(void)
{P_SW2 |= 0x80; //SFR enable T4T3M &= 0x0f; //停止計(jì)數(shù), 定時(shí)模式, 12T模式, 不輸出時(shí)鐘T4H = 0;T4L = 0;T3T4PIN = 0x01; //選擇IO, 0x00: T3--P0.4, T3CLKO--P0.5, T4--P0.6, T4CLKO--P0.7; 0x01: T3--P0.0, T3CLKO--P0.1, T4--P0.2, T4CLKO--P0.3;IE2 |= (1<<6); //允許中斷
// T4T3M |= (1<<7); //開始運(yùn)行
}
//=========================== timer4中斷函數(shù) =============================================
void timer4_ISR (void) interrupt TIMER4_VECTOR
{T4T3M &= ~(1<<7); //Timer4停止運(yùn)行if(XiaoCiCnt == 1) //標(biāo)記需要消磁. 每次檢測(cè)到過0事件后第一次中斷為30度角延時(shí), 設(shè)置消磁延時(shí).{XiaoCiCnt = 2; //1:需要消磁, 2:正在消磁, 0已經(jīng)消磁if(B_RUN) //電機(jī)正在運(yùn)行{if(++step >= 6) step = 0;StepMotor();}//消磁時(shí)間, 換相后線圈(電感)電流減小到0的過程中, 出現(xiàn)反電動(dòng)勢(shì), 電流越大消磁時(shí)間越長(zhǎng), 過0檢測(cè)要在這個(gè)時(shí)間之后//100%占空比時(shí)施加較重負(fù)載, 電機(jī)電流上升, 可以示波器看消磁時(shí)間.//實(shí)際上, 只要在換相后延時(shí)幾十us才檢測(cè)過零, 就可以了T4H = (u8)((65536UL - 40*2) >> 8); //裝載消磁延時(shí)T4L = (u8)(65536UL - 40*2);T4T3M |= (1<<7); //Timer4開始運(yùn)行}else if(XiaoCiCnt == 2) XiaoCiCnt = 0; //1:需要消磁, 2:正在消磁, 0已經(jīng)消磁
}
七、PMSM.c
/******************* 強(qiáng)制電機(jī)啟動(dòng)函數(shù) ***************************/
void StartMotor(void)
{u16 timer,i;CMPCR1 = 0x8C; // 關(guān)比較器中斷PWM_Value = D_START_PWM+10; // 初始占空比, 根據(jù)電機(jī)特性設(shè)置PWMA_CCR1L = PWM_Value;PWMA_CCR2L = PWM_Value;PWMA_CCR3L = PWM_Value;step = 0; StepMotor(); Delay_n_ms(100); //Delay_n_ms(250);// 初始位置timer = 300; //電機(jī)啟動(dòng)值PWM_Value = D_START_PWM/1.2; // 根據(jù)電機(jī)特性設(shè)置while(1){for(i=0; i<timer; i++) delay_us(70); //根據(jù)電機(jī)加速特性, 最高轉(zhuǎn)速等等調(diào)整啟動(dòng)加速速度timer -= timer /10; //設(shè)置加速時(shí)間if(++step >= 6) step = 0; //設(shè)置換向次數(shù)StepMotor(); //開啟電機(jī)換向if(timer < 40) return; //剩余啟動(dòng)值}
}
void StepMotor(void) // 換相序列函數(shù)
{switch(step){case 0: // AB PWM1, PWM2_L=1PWMA_ENO = 0x00; PWM1_L=0; PWM3_L=0;Delay_500ns();PWMA_ENO = 0x01; // 打開A相的高端PWMPWM2_L = 1; // 打開B相的低端ADC_CONTR = 0x80+10; // 選擇P0.2作為ADC輸入 即C相電壓CMPCR1 = 0x8c + 0x10; //比較器下降沿中斷break;case 1: // AC PWM1, PWM3_L=1PWMA_ENO = 0x01; PWM1_L=0; PWM2_L=0; // 打開A相的高端PWMDelay_500ns();PWM3_L = 1; // 打開C相的低端ADC_CONTR = 0x80+9; // 選擇P0.1作為ADC輸入 即B相電壓CMPCR1 = 0x8c + 0x20; //比較器上升沿中斷break;case 2: // BC PWM2, PWM3_L=1PWMA_ENO = 0x00; PWM1_L=0; PWM2_L=0;Delay_500ns();PWMA_ENO = 0x04; // 打開B相的高端PWMPWM3_L = 1; // 打開C相的低端ADC_CONTR = 0x80+8; // 選擇P0.0作為ADC輸入 即A相電壓CMPCR1 = 0x8c + 0x10; //比較器下降沿中斷break;case 3: // BA PWM2, PWM1_L=1PWMA_ENO = 0x04; PWM2_L=0; PWM3_L=0; // 打開B相的高端PWMDelay_500ns();PWM1_L = 1; // 打開C相的低端ADC_CONTR = 0x80+10; // 選擇P0.2作為ADC輸入 即C相電壓CMPCR1 = 0x8c + 0x20; //比較器上升沿中斷break;case 4: // CA PWM3, PWM1_L=1PWMA_ENO = 0x00; PWM2_L=0; PWM3_L=0;Delay_500ns();PWMA_ENO = 0x10; // 打開C相的高端PWMPWM1_L = 1; // 打開A相的低端ADC_CONTR = 0x80+9; // 選擇P0.1作為ADC輸入 即B相電壓CMPCR1 = 0x8c + 0x10; //比較器下降沿中斷break;case 5: // CB PWM3, PWM2_L=1PWMA_ENO = 0x10; PWM1_L=0; PWM3_L=0; // 打開C相的高端PWMDelay_500ns();PWM2_L = 1; // 打開B相的低端adc11 = ((adc11 *7)>>3) + Get_ADC10bitResult(6);ADC_CONTR = 0x80+8; // 選擇P0.0作為ADC輸入 即A相電壓CMPCR1 = 0x8c + 0x20; //比較器上升沿中斷break;default:break;}if(B_start) CMPCR1 = 0x8C; // 啟動(dòng)時(shí)禁止下降沿和上升沿中斷
}
八、參考資料
【電機(jī)控制】六步換向——方波驅(qū)動(dòng)(算法篇)
總結(jié)
本文僅僅簡(jiǎn)單介紹了【電機(jī)控制】基于STC8H1K28的六步換向——方波驅(qū)動(dòng)(軟件篇),評(píng)論區(qū)歡迎討論。