📄 avr_pd_timing.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 + -