直流电机闭环控制Keil c51源代码
- //-----------------------函数声明,变量定义--------------------------------------------------------
- #include <reg51.h>
- sbit INT_0 =P3^2; // 将p3.2外部中断0
- sbit pulse_A=P1^2; // P1.2为脉冲A输入
- sbit PWM=P1^0; //PWM波形输出
- sbit DR=P1^1; //方向控制
- //-----------------------预定义值--------------------------------------------------------
- #define PWM_T 1800 //定义PWM的周期T为18ms
- #define Ts 1000 //定义光电编码器采样时间为10ms
- #define timer_data (256-10) //定时器预置值,12M时钟是,定时0.01ms
- //-----------------------预设定值--------------------------------------------------------
- bit direction; //方向标志位 用户设定
- unsigned char R; //需要得到的直流电机转速 用户设定
- //-----------------------实际运行状态--------------------------------------------------------
- bit real_direction; //电机实际运行方向
- unsigned char Rr; //直流电机实际转速
- //-----------------------计算所得补偿状态------------------------------------------
- bit compensate_polarity; //补偿极性
- unsigned char dR; //转速补偿
- //-----------------------经补偿后得到的脉宽------------------------------------------
- unsigned char PWM_t; //PWM_t为脉冲宽度(320~400)时间为3.2~4.0ms
- unsigned char PWM_count; //输出PWM周期计数
- //-----------------------各中间计数值------------------------------------------
- unsigned char pulseB_count; //脉冲计数
- unsigned char time0_count; //定时计数
- unsigned char time1_count; //定时计数
- //--------------------------------------------------------------------------------------------------
- // 函数名称:timer_init
- // 函数功能:初始化设置定时器
- //--------------------------------------------------------------------------------------------------
- void timer_init()
- {
- TMOD=0x22; /*定时器1为工作模式2(8位自动重装),0为模式2(8位自动重装) */
- PCON=0x00;
- TF0=0;
- TH0=timer_data; //保证定时时长为0.01ms
- TL0=TH0;
- TH1=timer_data; //保证定时时长为0.01ms
- TL1=TH0;
- ET0=1; //定时器0中断允许
- TR0=1; //定时器0开始计数
- ET1=1; //定时器1中断允许
- TR1=1; //定时器1开始计数
- EA=1; //中断允许
- }
- //--------------------------------------------------------------------------------------------------
- // 函数名称: INT0_init()
- // 函数功能: 初始化设置
- // 设定INT0的工作方式
- //--------------------------------------------------------------------------------------------------
- void INT0_init(void )
- {
- pulseB_count=0; //脉冲计数器清零
- IT0=1; //选择INT0为沿触发方式
- EX0=1; //外部中断允许
- EA=1; //系统中断允许
- }
- //--------------------------------------------------------------------------------------------------
- // 函数名称:setting_PWM
- // 函数功能:设置PWM的脉冲宽度和设定方向
- //--------------------------------------------------------------------------------------------------
- void setting_PWM()
- {
- // direction=1; //设定转动方向
- // R=540; //设定转速
- // dR=0; //转速补偿为零
- // calculate_PWM_t(); //重新计算脉宽
- }
- //--------------------------------------------------------------------------------------------------
- // 函数名称: calculate_PWM_t
- // 入口参数: R需要得到的直流电机转速,dR转速补偿
- // 出口参数: PWM_t为脉冲宽度(320~400)时间为3.2~4.0ms
- // 函数功能: 计算脉冲宽度,PWM_t=R/150;
- //--------------------------------------------------------------------------------------------------
- void calculate_PWM_t()
- {
- if(compensate_polarity==1) //正补偿
- PWM_t=(R+dR)/150;
- else
- PWM_t=(R-dR)/150; //负修正
- }
- //--------------------------------------------------------------------------------------------------
- // 函数名称: calculate_Rr
- // 入口参数: pulseB_count脉冲计数
- // 出口参数: Rr直流电机实际转速
- // 函数功能: 计算实际转速
- //--------------------------------------------------------------------------------------------------
- void calculate_Rr()
- {
- Rr=pulseB_count/6;
- }
- //--------------------------------------------------------------------------------------------------
- // 函数名称: compensate_dR
- // 入口参数: Rr直流电机实际转速
- // R需要得到的直流电机转速
- // 出口参数: dR转速补偿
- // 函数功能: 计算实际补偿值和补偿极性 ,根据不同的补偿算法重新设计
- //--------------------------------------------------------------------------------------------------
- void compensate_Rr()
- {
- Rr=1;
- if(Rr>R)
- compensate_polarity=0; //补偿极性
- else
- compensate_polarity=1;
- }
- //--------------------------------------------------------------------------------------------------
- // 函数名称: INT0_intrupt
- // 函数功能: 外部中断0处理程序
- //--------------------------------------------------------------------------------------------------
- void INT0_intrupt() interrupt 0 using 1
- {
- pulseB_count++;
- if(pulse_A==0)
- {
- real_direction=1; //若P1.2为低电平,则电机为正转,计数器N的值加1
- }
- else //若为高电平,则电机为反转,计数器N值减l。
- {
- real_direction=1;
- }
- }
- //--------------------------------------------------------------------------------------------------
- // 函数名称:IntTimer0
- // 函数功能:定时器中断处理程序
- //--------------------------------------------------------------------------------------------------
- void IntTimer0() interrupt 1
- {
- time0_count++;
- DR=direction;
- if(time0_count>=PWM_T)
- {
- time0_count=0;
- PWM_count++;
- setting_PWM(); //每输出一个PWM波调用一次
- }
- if(time0_count<PWM_t)
- PWM=1;
- else
- PWM=0;
- }
- //--------------------------------------------------------------------------------------------------
- // 函数名称:IntTimer1
- // 函数功能:定时器中断处理程序
- //--------------------------------------------------------------------------------------------------
- void IntTimer1() interrupt 3
- {
- time1_count++;
- if(time1_count==1)
- {
- INT0_init(); //初始化外部中断设置
- }
- if(time1_count>=Ts)
- {
- time1_count=0; //一个补偿周期结束,计数器清零
- calculate_Rr(); //计算实际转速
- compensate_Rr(); //计算实际补偿值和补偿极性
- calculate_PWM_t(); //重新计算脉宽
- }
- }
- //--------------------------------------------------------------------------------------------------
- // 函数名称:main
- // 用户主函数
- // 函数功能:主函数
- //--------------------------------------------------------------------------------------------------
- void main()
- {
- direction=1; //设定转动方向
- R=540; //设定转速
- dR=0; //转速补偿为零
- calculate_PWM_t(); //重新计算脉宽
- timer_init();
- }