/******************************************************************************* 华邦W79E833电动自行车方案程序 作者:邹工 13761016264 zou_zhi_chao@hotmail.com 注:程序在不同的电机上表现有一些差异,有任何问题可以与我联系; 若需要头文件,原理图、PCB也可以和我联系。 ******************************************************************************/ #include "intrins.h" #include "E_BIKE_83.H" #include"W79E834.h" #define Current_Max 0x700 /***************************************************************************** * 主函数 ******************************************************************************/ void main(void) { Init_IO(); // 初始化端口 Init(); // 初始化 H_Sample(); // 霍尔信号采样 EA=1; while(1) { PWM_Setting(); if(Speed_REQ) {PWM_ADJ();} EA=0; if(MotorStop_CNT > 5) { H_Sample(); Phase_Change(); MotorStop_CNT = 0; } EA=1; } } /****************************************************************************** * I/O端口初始化 ******************************************************************************/ void Init_IO(void) { P0M1=0xFC;//------P0端口设置------// P0M2=0x03; P0=0xFF; P1M1=0x1C;//------P1端口设置------// P1M2=0xC3; P1=0xFF; P2M1=0x01; //------P2端口设置------// P2M2=0x5E; P2=0xFF; } /****************************************************************************** * 初始化程序 ******************************************************************************/ void Init(void) { unsigned char i; PWMPH=0X03;//------PWM设置------// PWMPL=0X55; PWM0H=0X00; PWM0L=0X00; PWM1H=0X00; PWM1L=0X00; PWM2H=0X00; PWM2L=0X00; PWMCON1=0XC7; // 打开PWM电路,三个PWM口反相输出 PWMCON3=0xF0; P21 = 0; UT=0;VT=0;WT=0; UB=1;VB=1;WB=1; // 电机停转 while(P14==0)//-----相位检测-------// { H_Sample(); Phase_Detect(); } for (i=0;i<16;i++)//------变量初始化------// {Current_Buffer=0;} for (i=0;i<20;i++) {Speed_Buffer=0;} for (i=0;i<16;i++) {Voltage_Buffer=0;} Current_P=0; Speed_P=0; Voltage_P=0;; Speed_SUM=0; Current_SUM=0; Voltage_SUM=0; H_State=0; Old_State=0; PWM_Duty=0; Count_Current=0; Count_Speed=0; Count_Voltage=0; Speed_REQ=0; Current_REQ=0; Voltage_REQ=0; ADC_Ready=0; PWM_Duty_min=1; Motor_Speed = 0x50; Speed_Low=0x0500; TH0=0x7A;TL0=0x7A; // 设定定时器的初值 TMOD=0x22; // T0选为定时器(八位)模式2,TL0自动加载TH0中的初值 CKCON&=0X00; // 定时器选择为1/12系统时钟 ET0=1; // 允许定时器中断 TR0=1; // 启动定时器 AUXR1|=0x04; // 打开ADC电路 EADC=1; // 允许ADC中断 ADCCON &= 0xE7; CKCON=0x60; // Settings of Timer2 capture mode CAPCON0=0xA8; CAPCON1=0x00; T2MOD=0xF0; IE1 |= 0x80; // enable capture mode interrupt IP1H = 0x80; RCAP2L = 0x00; //自动重装载低位 RCAP2H = 0x00; //自动重装载高位 IE1 |= 0x40; T2CON |= 0x04;//enable timer2 } /****************************************************************************** * ADC中断处理程序 ******************************************************************************/ void ADC_ISR(void) interrupt 11 { ADC_Ready=1; ADCCON &= 0xE7; if(Current_REQ) // 电流采样 { Current_REQ=0; if(Current_SUM>Current_Buffer[Current_P]) Current_SUM -= Current_Buffer[Current_P]; Current_Buffer[Current_P]=ADCH; Current_SUM += ADCH; Current_P++; if(Current_P>15) Current_P=0; } if(Speed_REQ) // 转把电压采样 { Speed_REQ=0; if(Speed_SUM>Speed_Buffer[Speed_P]) Speed_SUM-=Speed_Buffer[Speed_P]; Speed_Buffer[Speed_P]=ADCH; Speed_SUM+=ADCH; Speed_P++; if(Speed_P == 14) Speed_P=0; } if(Voltage_REQ) // 电源电压采样 { Voltage_REQ=0; if(Voltage_SUM>Voltage_Buffer[Voltage_P]) Voltage_SUM -= Voltage_Buffer[Voltage_P]; Voltage_Buffer[Voltage_P]=ADCH; Voltage_SUM += ADCH; Voltage_P++; if(Voltage_P>15) Voltage_P=0; } } /****************************************************************************** * 定时器0中断处理函数 ******************************************************************************/ // ========== Interrupt Cycle: 100uS =================== void T0M1_ISR(void) interrupt 1 { ADC_Ready=0; Current_REQ=1; Speed_REQ=0; Voltage_REQ=0; ADCCON=3; Count_Speed++; if(Count_Speed>5)//17 { ADCCON=1; Current_REQ=0; Speed_REQ=1; Count_Speed=0; Count_Voltage++; Current_Protect(); if( Count_Voltage>20)//50 { ADCCON=2; Speed_REQ=0;Voltage_REQ=1; Count_Voltage=0; } } ADCCON&=0xef;ADCCON|=0x08; EADC=1; MotorStop_CNT++; } /****************************************************************************** * 定时器2捕获模式中断处理函数 ******************************************************************************/ void Timer2_ISR() interrupt 13 using 2 { EA = 0; Motor_Speed = TH2; TH2 = 0; TL2 = 0; MotorStop_CNT = 0; H_Sample(); // 霍尔信号采集 Phase_Change(); // 相位变换 EA = 1; } /****************************************************************************** * 定时器2溢出中断处理函数 ******************************************************************************/ void T2_ISR() interrupt 8 { TF2 = 0; Motor_Speed = 0x50; Block_Detect(); // 堵转保护 } /****************************************************************************** * 定时器3中断处理函数,采取捕获模式 ******************************************************************************/ void H_Sample(void) { CAPCON1 &= 0xF8; H1=P12; H2=P20; H3=P07; H_State=H1<<2; H_State+=H2<<1; H_State+=H3; } /****************************************************************************** * 根据电机霍尔换向信号给出相应控制信号 * 上桥臂:VT,UT,WT * 下桥臂:VB,UB,WB ******************************************************************************/ void Phase_Change(void) { if(PWM_Duty_min) { UT=0;VT=0;WT=0; UB=1;VB=1;WB=1; // 电机停转 PWM_Duty_Max = 0; } else//========// { switch(H_State) { case 6: // 110,V3,V4 VT=0;UT=0;VB=1;WB=1; WT=1;UB=0; break; case 2: // 010,V4,V5 case 7: UT=0;WT=0;VB=1;WB=1; VT=1;UB=0; break; case 3: // 011,V5,V6 UT=0;WT=0;UB=1;VB=1; VT=1;WB=0; break; case 1: // 001,V6,V1 WT=0;VT=0;UB=1;VB=1; UT=1;WB=0; break; case 5: // 101,V1,V2 case 0: WT=0;VT=0;UB=1;WB=1; VB=0;UT=1; break; case 4: // 100,V2,V3 UT=0;VT=0;UB=1;WB=1; WT=1;VB=0; break; case 9: UT=0;VT=0;WT=0; UB=1;VB=1;WB=1; break; default:break; } } } //-------检测--------// void Phase_Detect(void) { WT=0;UT=0;VT=0; switch(H_State) { case 6: // 110,V3,V4 UB=0;VB=1;WB=1; break; case 2: // 010,V4,V5 case 7: UB=0;VB=1;WB=1; break; case 3: // 011,V5,V6 UB=1;VB=1;WB=0; break; case 1: // 001,V6,V1 UB=1;VB=1;WB=0; break; case 5: // 101,V1,V2 case 0: UB=1;VB=0;WB=1; break; case 4: // 100,V2,V3 UB=1;VB=0;WB=1; break; default:break; } } /****************************************************************************** * PWM值转换程序 * 将转把电压ADC值转换为PWMn的值 ******************************************************************************/ void PWM_ADJ(void) { if(Speed_SUM < Speed_Low) { //---没有转把电压,由Speed_Low的值决定转把电压最小值---// PWM_Duty_Max = 0; PWM_Duty_min=1; // 停转标志 Block_Flag = 0; Block_CNT = 0; } else if(P14 == 1) { //---转把电压有效---// PWM_Duty_Max=Speed_SUM-Speed_Low; // 对应转把电压的最大计算值 if(PWM_Duty_min) { if(!Block_Flag) PWM_Duty_min = 0; // 退出无有效转把电压状况 } if(PWM_Duty_Max>0x06F0)PWM_Duty_Max = 0x06E8; // 最大值限制 if(Block_Flag)PWM_Duty_Max = 0; PWM_Duty_Max=PWM_Duty_Max>>1; // 由转把电压转换为PWMn的值 } } /****************************************************************************** * 电流闭环控制器 ******************************************************************************/ void Current_Protect(void) { if(Current_SUM < Current_Max) // 过流保护 { if(PWM_Duty < PWM_Duty_Max) PWM_Duty ++; // 转把电压相对应的PWMn值缓慢增加 else { if(PWM_Duty > 3) PWM_Duty --; // 转把电压相对应的PWMn值缓慢减小 else PWM_Duty = 0; } } else if(Current_SUM > Current_Max+5) { if(PWM_Duty > 2) PWM_Duty -= 2; else PWM_Duty=0; } PWM_Duty_H = PWM_Duty>>8; PWM_Duty_L = (PWM_Duty & 0x0FF); // 对应PWMn的值(高、低位) } /****************************************************************************** * 堵转保护程序 ******************************************************************************/ void Block_Detect(void) { if(Current_SUM > Current_Max-0x1A0) { Block_CNT++; } if(Current_SUM<0x300) Block_CNT = 0; if(Block_CNT >= 10) { EA = 0; UT=0;VT=0;WT=0; UB=1;VB=1;WB=1; // 电机停转 PWM_Duty_min = 1; Block_Flag = 1; PWM_Duty = 0; PWM_Duty_Max = 0; PWM_Duty_H = 0; PWM_Duty_L = 0; EA = 1; } } /****************************************************************************** * PWM设定 ******************************************************************************/ void PWM_Setting(void) { PWM0H=PWM_Duty_H; PWM0L=PWM_Duty_L; PWM1H=PWM_Duty_H; PWM1L=PWM_Duty_L; PWM2H=PWM_Duty_H; PWM2L=PWM_Duty_L; PWMCON1 |= 0x40; } /****************************************************************************** ******************************************************************************/ |