typedef struct { unsigned short Up; //темп разгона unsigned short Down; //темп торможения unsigned int MUp; //пересчитанный темп разгона unsigned int MDown; //пересчитанный темп торможения unsigned int M2; //пересчитанный темп второй производной }Temp_type; Temp_type *CurTmp; // Указывает на текущий темп (структуру), она уже где-то посчитана //**************************************************************************** Функция подготавливает коэффициенты для генератора рампы temp->up и temp->down задаются в секундах с десятыми долями смысл - число 48 (на пульте выглядит как 4.8) означает что переход от 0 до 4096 (это условная единица) пройдет за 4.8 секунды PwmFreq - частота циклов управления, вроде в герцах. Хотя давно это было, могу и наврать с масштабом :) K - константа, определяющая долю кривых участков в разгоне. А вообще, можно пользоваться сразу MUp,MDown и M2 - это ограничения первой производной в двух направлениях и ограничение второй производной. Но с масштабом тогда воюем сами :) void ReTemp(Temp_type *temp) { unsigned int MUp, MDown, M2; MUp = (temp->Up)?(((2048*65536/10)/PwmFreq)*256)/temp->Up:0; MDown = (temp->Down)?(((2048*65536/10)/PwmFreq)*256)/temp->Down:0; if (MUp>MDown) { if (MUp) M2=(MUp/temp->Up)/(PwmFreq*2); // K=0.4, 10*K/2 = 2 else M2=0; } else { if (MDown) M2=(MDown/temp->Down)/(PwmFreq*2); // K=0.4, 10*K/2 = 2 else M2=0; } temp->MUp = MUp; temp->MDown = MDown; temp->M2 = M2; } //**************************************************************************** А это собсно генератор рампы. SKharMode=0 - линейная SKharMode=1 - S-образная short StepReference(short Ref) { static int InternalRef=0; static int delta=0; int dval; int diff; int dir2; // Do the step diff=((Ref<<15)-InternalRef); dval=(delta+0x1000)>>13; dval=(dval*dval*2)/CurTmp->M2; if (InternalRef>=0) dir2=(diff<0)?-(int)CurTmp->MDown:(int)CurTmp->MUp; else dir2=(diff<0)?-(int)CurTmp->MUp:(int)CurTmp->MDown; if (SKharMode) { if (abs(diff)>>16<=dval) dir2=0; if ((dir2-delta)>(int)CurTmp->M2) delta+=(CurTmp->M2+1); else if ((dir2-delta)<-(int)CurTmp->M2) delta-=(CurTmp->M2+1); else delta=dir2; } else delta=dir2; if (abs(diff)<16384+abs(delta>>8)) { InternalRef=Ref<<15; delta=0; } else InternalRef+=(delta>>8); if (InternalRef<0) { dval=-delta; } else dval=delta; } return InternalRef>>15; }