⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 avr_pd_timing.c

📁 菜鸟编写基于AVR的电机PD调速程序
💻 C
字号:
//ICC-AVR application builder : 2009-4-6 19:44:11
// 型号 : M8
// 晶振: 8Mhz
// 作者:汝正阳
// 太原工业学院 09rebocon
// 功能:实现电机速度闭环
//说明:基本稳定,给值不要超过电机最大速度,否则跳变
#include<iom8v.h>
#include<macros.h>
#define uint unsigned int 
#define uchar unsigned char
#define Kprop 0.08                            //需要调整Kprop0.08,Krate0.0008,Kint0.05
#define Krate 0.0001
#define F_cpu 8000000						  //晶振频率
#define M_list 360
void Timer1_init(void);
void Timer2_init(void);
void Setpwm(long int CV);
int ReadMotorSpeed(void);
void adjust_P(void);
void main()
{
    CLI(); 			   						              //禁止所有中断
	Timer1_init();
	Timer2_init();
	SEI();		  							              //开全局中断
	while(1)
	{
	  ;
	}
}
//定时器1预分频宏定义
//定时器1初始化程序,使用输入捕获,并开启噪声抑制
//系统时钟8M,为获取高精度,不进行时钟分频
void Timer1_init(void)
{
	TCCR1B=0x00;		  		 		      //关闭定时/计数器0
	TCCR1A=0X00;								   		  //普通工作模式
	ICR1=0X0000;
	TIMSK=(1<<TICIE1);		  					   		  //开启输入捕获中断
	DDRB&=~(1<<PB0);					  		   		  //将ICR1引脚设置为输入
	PORTB|=(1<<PB0);						  			  //开启上拉电阻
	TCCR1B=(1<<ICNC1)|				  		  			  //开启输入噪声抑制
           (1<<ICES1)|					  				  //上升沿触发捕获
           (1<<CS10);
}
void Timer2_init(void)
{
    DDRB|=(1<<PB3);
    TCCR2=(1<<CS20)|(1<<WGM20)|(1<<COM21);				  //相位修正1分频8M,15.996kHZ
    OCR2=30; 											  //用以改变占空比
}
volatile unsigned long g_wPulseWidth=1;       //脉冲周期
static volatile unsigned short s_hwLastICR=0; //辅助变量
//定时器1捕获中断处理程序
//增量式频率计算
#pragma interrupt_handler TIMER1_CAPT_vect:6 //定时计数器1,捕捉中断
void TIMER1_CAPT_vect(void)
{
    unsigned long wTemp=ICR1;		      		  		  //记录捕获结果
    if(s_hwLastICR>=ICR1)			      				  //检查是否发生了溢出
      {
	    wTemp+=0xFFFF;
      }
    wTemp-=(unsigned long)s_hwLastICR;	      //计算周期
    s_hwLastICR=ICR1;			      		  			  //保存本次的测量数值
    g_wPulseWidth=wTemp;			      				  //更新测量结果
    TIMSK=0X00;
	adjust_P();
}
void Setpwm(long int CV)
{
    int M_pluse,M_re;  		  					 			  //定义脉宽的绝对值
    M_pluse=OCR2;
    M_pluse=M_pluse+CV;
	
	if(M_pluse>0)
	  {
	    if(M_pluse<=255)
		 {
	        OCR2=M_pluse;	
		 }
		else
		 {
		    OCR2=255;
		 }
	  }
	  else
	  {
	    M_pluse=-(M_pluse/2);
		OCR2=M_pluse;
	  }
	TIMSK=(1<<TICIE1);		  					   		  //开启输入捕获中断
}
 int ReadMotorSpeed(void)
{
    int Time_round;	//电机运行一分钟走过圈数
	Time_round=1333333/g_wPulseWidth;
    return Time_round;
 
}

/*void adjust_P(void)                           //比例算法P
{
    long int Error;
	long int CV;
	float PS,PV;  									  	  //PS为转速期望值										  //PV反馈值
	PS=50;	   								 			  //试验用设定值,到时用主控将数值传来
    PV=ReadMotorSpeed();                      		      //读取本次反馈值
    Error=PS-PV;                              	          //将期望值和反馈值之差给Error
    CV=Error*Kprop;							 		      //决定占空比的控制量给值。Error*常数
    Setpwm(CV);			           			 		      //使用次循环量输出.注意:CV不是使用绝对值,使用的是差值
}*/
void adjust_P(void)						  //比例微分算法PD
{
    long int Error,LastError,Rate;
	long int CV;
	float PS,PV;  		
    PV=ReadMotorSpeed();                      		      //读取本次反馈值
    LastError=Error;							 		      //赋上次偏差值
	PS=20;	
    Error=PS-PV;                              		      //将期望值和反馈值之差给Error
    Rate=Error-LastError;					 		      //计算微分项,偏差的差
    CV=Error*Kprop+Krate*Rate;				 		      //决定占空比的控制量给值。Error*常数
    Setpwm(CV);			           			 		      //使用次循环量输出.注意:CV不是使用绝对值,使用的是差值
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -