//-----------------------函数声明,变量定义-------------------------------------------------------- #include <reg51.h> #include <intrins.h> #include <ABSACC.H> //-----------------------定义管脚-------------------------------------------------------- sbit PWM = P1 ^ 0; //PWM波形输出 sbit DR = P1 ^ 1; //方向控制 #definetimer_data(256-100) //定时器预置值,12M时钟是,定时0.1ms #definePWM_T 100//定义PWM的周期T为10ms unsigned char PWM_t;//PWM_t为脉冲宽度(0~100)时间为0~10ms unsigned char PWM_count;//输出PWM周期计数 unsigned char time_count;//定时计数 bit direction;//方向标志为 //-------------------------------------------------------------------------------------------------- // 函数名称:timer_init // 函数功能:初始化设施定时器 //-------------------------------------------------------------------------------------------------- void timer_init() { TMOD = 0x22; /*定时器1为工作模式2(8位自动重装),0为模式2(8位自动重装) */ PCON = 0x00; TF0 = 0; TH0 = timer_data; //保证定时时长为0.1ms TL0 = TH0; ET0 = 1; TR0 = 1; //开始计数 EA = 1; //中断允许 } //-------------------------------------------------------------------------------------------------- // 函数名称:setting_PWM // 函数功能:设置PWM的脉冲宽度和设定方向 //-------------------------------------------------------------------------------------------------- void setting_PWM() { if (PWM_count == 0) { //初始设置 PWM_t = 20; direction = 1; } } //-------------------------------------------------------------------------------------------------- // 函数名称:IntTimer0 // 函数功能:定时器中断处理程序 //-------------------------------------------------------------------------------------------------- void IntTimer0() interrupt 1 { time_count++; DR = direction; if (time_count >= PWM_T) { time_count = 0; PWM_count++; setting_PWM();//每输出一个PWM波调用一次 } if (time_count < PWM_t) { PWM = 1; } else { PWM = 0; } } //-------------------------------------------------------------------------------------------------- // 函数名称:main // 用户主函数 // 函数功能:主函数 //-------------------------------------------------------------------------------------------------- void main() { timer_init(); setting_PWM(); } <h5>直流电机闭环控制Keil c51源代码 < / h5 > //-----------------------函数声明,变量定义-------------------------------------------------------- #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 Ts1000//定义光电编码器采样时间为10ms #definetimer_data(256-10) //定时器预置值,12M时钟是,定时0.01ms //-----------------------预设定值-------------------------------------------------------- bit direction;//方向标志位用户设定 unsigned char R;//需要得到的直流电机转速用户设定 //-----------------------实际运行状态-------------------------------------------------------- bit real_direction;//电机实际运行方向 unsigned char Rr;//直流电机实际转速 //-----------------------计算所得补偿状态------------------------------------------ bitcompensate_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(); }