hmd420304805 发表于 2012-6-29 17:58:06

步进电机加减速算法 +组态王modbus通讯 +状态机+掉电数据...

本帖最后由 hmd420304805 于 2012-6-30 08:57 编辑

(增加modbus 和组态王   mcgs通讯 :支持01   030506 10 功能码 )

下面的代码为正在机器使用的一段 加速曲线
   
CPU为 C8051F340   48M的频率   两个定时器控制4个步进电机进行定位(在某一时刻只有2台电机在运动)
晶震频率   = 48.000000;
极限转速   = 350;
周脉冲数   = 2000;
注:驱动方式为 脉冲+ 方向
废话不多说,需要的就读关键代码吧(整个工程代码比较多,1500多行就不上了)。希望对大家有那么一丝帮助,需要帮忙就联系我也行。


unsigned int code WaitTable[]={
        0x24AB, 0x3f5e, 0x3068, 0x6216, 0x7E4B, 0x9093, 0x9D78, 0xA6FA, 0xAE63, 0xB44B,// 10
        0xB91B, 0xBD28, 0xC093, 0xC387, 0xC61B, 0xC85C, 0xCA5F, 0xCC2B, 0xCDCB, 0xCF42,// 20
        0xD098, 0xD1D2, 0xD2F2, 0xD3FE, 0xD4F5, 0xD5DB, 0xD6B2, 0xD779, 0xD835, 0xD8E6,// 30
        0xD98E, 0xDA2C, 0xDAC0, 0xDB4E, 0xDBD5, 0xDC54, 0xDCCE, 0xDD41, 0xDDB0, 0xDE1B,// 40
        0xDE80, 0xDEE3, 0xDF40, 0xDF9B, 0xDFF1, 0xE044, 0xE094, 0xE0E2, 0xE12D, 0xE176,// 50
        0xE1BC, 0xE1FF, 0xE241, 0xE281, 0xE2BE, 0xE2FB, 0xE334, 0xE36C, 0xE3A4, 0xE3D9,// 60
        0xE40D, 0xE43F, 0xE470, 0xE4A1, 0xE4D0, 0xE4FD, 0xE52A, 0xE555, 0xE580, 0xE5A9,// 70
        0xE5D1, 0xE5F9, 0xE61F, 0xE646, 0xE66B, 0xE68E, 0xE6B3, 0xE6D5, 0xE6F7, 0xE718,// 80
        0xE739, 0xE759, 0xE779, 0xE798, 0xE7B6, 0xE7D4, 0xE7F1, 0xE80E, 0xE82A, 0xE846,// 90
        0xE861, 0xE87B, 0xE896, 0xE8B0, 0xE8C9, 0xE8E2, 0xE8FB, 0xE913, 0xE92B, 0xE942,// 100
        0xE959, 0xE970, 0xE987, 0xE99D, 0xE9B3, 0xE9C8, 0xE9DD, 0xE9F2, 0xEA07, 0xEA1B,// 110
        0xEA2F, 0xEA42, 0xEA56, 0xEA69, 0xEA7C, 0xEA8E, 0xEAA1, 0xEAB3, 0xEAC5, 0xEAD7,// 120
        0xEAE8, 0xEAF9, 0xEB0B, 0xEB1C, 0xEB2C, 0xEB3C, 0xEB4D, 0xEB5D, 0xEB6D, 0xEB7D,// 130
        0xEB8C, 0xEB9C, 0xEBAB, 0xEBBA, 0xEBC8, 0xEBD7, 0xEBE6, 0xEBF4, 0xEC02, 0xEC10,// 140
        0xEC1E, 0xEC2C, 0xEC39, 0xEC47, 0xEC54, 0xEC61, 0xEC6F, 0xEC7C, 0xEC88, 0xEC95,// 150
        0xECA1, 0xECAE, 0xECBA, 0xECC6, 0xECD2, 0xECDF, 0xECEB, 0xECF6, 0xED02, 0xED0D,// 160
        0xED19, 0xED24, 0xED2F, 0xED3A, 0xED45, 0xED50, 0xED5B, 0xED66, 0xED70, 0xED7B,// 170
        0xED85, 0xED90, 0xED9A, 0xEDA4, 0xEDAE, 0xEDB8, 0xEDC2, 0xEDCC, 0xEDD6, 0xEDE0,// 180
        0xEDE9, 0xEDF3, 0xEDFC, 0xEE06, 0xEE0F, 0xEE18, 0xEE21, 0xEE2B, 0xEE33, 0xEE3C,// 190
        0xEE45, 0xEE4E, 0xEE57, 0xEE60, 0xEE68, 0xEE71, 0xEE79, 0xEE82, 0xEE8A, 0xEE93,// 200
        0xEE9B, 0xEEA3, 0xEEAB, 0xEEB3, 0xEEBB, 0xEEC3, 0xEECB, 0xEED3, 0xEEDB, 0xEEE3,// 210
        0xEEEA, 0xEEF2, 0xEEFA, 0xEF01, 0xEF09, 0xEF10, 0xEF17, 0xEF1F, 0xEF26, 0xEF2E,// 220
        0xEF35, 0xEF3C, 0xEF43, 0xEF4A, 0xEF51, 0xEF58, 0xEF5F, 0xEF66, 0xEF6D, 0xEF74,// 230
        0xEF7B, 0xEF81, 0xEF88, 0xEF8E, 0xEF95, 0xEF9C, 0xEFA2, 0xEFA9, 0xEFAF, 0xEFB6,// 240
        0xEFBC, 0xEFC3, 0xEFC9, 0xEFCF, 0xEFD5, 0xEFDC, 0xEFE2, 0xEFE8, 0xEFEE, 0xEFF4,// 250
        0xEFFA
};




                               
//-----------------------------------------------------------------------------
//电机1、3运动初始化 --->使用定时器2
//-----------------------------------------------------------------------------
void T2_init(void)
{
if(TABM)                          //如果平台移动
{
if(dir_1) X+=steps1;//进给方向
else   X-=steps1; //原点方向
}
if(UDM)                          //如果上下钻移动
{
   if(dir_3) U+=steps1;//进给方向
   else      U-=steps1;//原点方向
}
CKCON |=0xf0;
T2_runflag=1;
nsteps1=steps1;
v0_1=1;
l4=0;
t1=v1*7;
if(steps1<2*t1) v1=steps1/2*t1;
TMR2CN =2;       //关定时器复位中断       
TMR2RL=WaitTable;//初始速度赋值         
TMR2 = TMR2RL;
ET2=1;         //中断使能
TMR2CN |= 1<<2;//开定时器          
}


//-----------------------------------------------------------------------------
//电机2、4运动初始化 --->使用定时器2
//-----------------------------------------------------------------------------

void T3_init(void)
{

   if(TABM1)                           //如果平台移动
{
if(dir_2) Y+=steps2; //进给方向
else   Y-=steps2;//原点方向
}
if(UDM1)                           //如果上下钻移动
{
   if(dir_4) D+=steps2;//进给方向
   else   D-=steps2; //原点方向
}
CKCON |=0xf0;
T3_runflag=1;
nsteps2=steps2;
l3=0;
v0_2=1;
t2=v2*7;
if(steps2<2*t2) v2=steps2/2*t2;
TMR3CN =2;         //关定时器   复位中断          系统时钟
TMR3RL =WaitTable;      //初始速度赋值      
TMR3 = TMR3RL;
EIE1|=1<<7;          //中断使能
TMR3CN |= 1<<2;      //开定时器
}

                                                                                                                                       
void Timer2_ISR (void) interrupt 5
{
   TMR2CN &= ~1<<7;    //清中断标志 关定时器
   if(T2_runflag)
   {
   if(UDM)PLU3=!PLU3;
   if(TABM)PLU1=!PLU1;
        if(l1==0)        TMR2RL=WaitTable;
        if(steps1-nsteps1<t1) {if(l1<7) l1++;else {l1=0;if(l3<v1)l3++;}}
           if(nsteps1<t1) {if(l1<7) l1++;else {l1=0;if(l3>v0_1)l3--;}}                                       
   nsteps1--;       
   if(nsteps1>0) TMR2CN |= 1<<2;         //开定时器
   if(nsteps1==0)
   T2_runflag=0;
   if(UDM)PLU3=!PLU3;                           //        if(P4&b6)
   if(TABM)PLU1=!PLU1;                   //if(!P3^3)           限位
   }
}


void Timer3_ISR (void) interrupt 14
{
   TMR3CN &= ~1<<7;                     //清中断标志 关定时器
   if(T3_runflag)
   {
   if(UDM1)PLU4=!PLU4;                                  //到限位开关停止发脉冲
   if(TABM1)PLU2=!PLU2;
   if(l2==0) TMR3RL=WaitTable;
   if(steps2-nsteps2<t2) {if(l2<7) l2++;else {l2=0;if(l4<v2)l4++;}}
   if(nsteps2<t2) {if(l2<7) l2++;else {l2=0;if(l4>v0_2)l4--;}}       
   nsteps2--;
   if(nsteps2>0) TMR3CN |= 1<<2;          //开定时器
   if(nsteps2==0)
   T3_runflag=0;
   if(UDM1)PLU4=!PLU4;                                  //一个中断发一个完整个脉冲段             到限位开关停止发脉冲                                       
   if(TABM1) PLU2=!PLU2;
   }
}

modbus 协议
ucharRdata_size= 0;
ucharUART_Input_First = 0;
ucharUART_Output_First = 0;
bit TX_Ready =1;
bit modbus_flag=0;
/* CRC低位字节值表*/

const uchar code auchCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
} ;
const uchar code auchCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;
//------------------------------
//        CRC计算器
//------------------------------
uint crc16(uchar *puchMsg, uint usDataLen)
{
        uchar uchCRCHi = 0xFF ; /* 高CRC字节初始化 */
        uchar uchCRCLo = 0xFF ; /* 低CRC 字节初始化 */
        uint uIndex ; /* CRC循环中的索引 */
        while (usDataLen--) /* 传输消息缓冲区 */
        {
                uIndex = uchCRCHi ^ *puchMsg++ ; /* 计算CRC */
                uchCRCHi = uchCRCLo ^ auchCRCHi ;
                uchCRCLo = auchCRCLo ;
        }
        return (uchCRCHi << 8 | uchCRCLo) ;
}
//------------------------------
//        定时器0器初始化
//------------------------------

void Timer0_Init(void)
{
   TH0 = Overflagtime&0xff00;                             
   TL0 = Overflagtime&0x00ff;
   TMOD|= 0x01;                        // Timer0 in 16-bit reload mode
   //CKCON |= 0x02;                     // Timer0 uses a 1:48 prescaler
   ET0=1;                           // Timer0 interrupt enabled
}

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
// P0.4   digital   push-pull    UART TX
// P0.5   digital   open-drain   UART RX
//-----------------------------------------------------------------------------
                                       
//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
                          
void UART0_Init (void)
{       

   SCON0 = 0x10;                      // SCON0: 8-bit variable bit rate
                                       //      level of STOP bit is ignored
                                       //      RX enabled
                                       //      ninth bits are zeros
                                       //      clear RI0 and TI0 bits
   TH1 =0x30;
   CKCON &= 0xf0;                     //SCA1:0 = xx;T1M = 1;
   CKCON |=0x08;                                     //T1M = 1;
   TMOD &=0x0f;                      // TMOD: timer 1 in 8-bit autoreload
   TMOD |=0x20;                     
   TR1 = 1;                            // START Timer1
   IP |= 0x10;                         // Make UART high priority
   ES0 = 1;
   TX_Ready = 1;                     // Flag showing that UART can transmit
Timer0_Init();

}
/*************************************/
/* 函数名:void modbus_proc(void)
/*功能:modbus 处理函数        每次把整个循环BUFFER都扫描一遍
/* 传入值 void   
/*************************************/

void modbus_proc(void)
{
uint crcv;
uchar addr,temp,readCount;                                                                                                               
   if(modbus_flag)
        {
           switch(R_Buffer0)         //功能码分解
        {
    case 0x01:                                                           //读内部线圈
                 crcv=crc16(&R_Buffer0,6);//求CRC 如果CRC校验不正确则不处理
                       if(R_Buffer0!=crcv>>8|R_Buffer0!=crcv&0xff)        return;
                 addr=R_Buffer0;           //获取起始地址 (不同于寄存器)
                       readCount =R_Buffer0;   //获取读取线圈个数
                       S_Buffer0=m_addr;
                       S_Buffer0=0x01;
                       if(readCount>8)S_Buffer0=2; elseS_Buffer0=1;
                       crcv=reg>>addr;
                       if(readCount>8)
                       {
                          S_Buffer0=2;
                          S_Buffer0=crcv&0xff;
                          temp=0xff;
                          temp=temp<<readCount-8;
                          temp=~temp;
                          crcv=crcv>>8;
                          crcv=temp&crcv;
                          S_Buffer0=crcv&0xff;
                          crcv=crc16(&S_Buffer0,5);
                          S_Buffer0=crcv>>8;
            S_Buffer0=crcv&0xff;
                          while(!TX_Ready);                                                          
            urat0_Send_data(7);
                       }
                       else
                       {
                          S_Buffer0=1;
                          temp=0xff;
                          temp=temp<<readCount;
                          temp=~temp;
                          crcv=crcv&temp;
                          S_Buffer0=crcv&0xff;
                          crcv=crc16(&S_Buffer0,4);
                          S_Buffer0=crcv>>8;
            S_Buffer0=crcv&0xff;
                          while(!TX_Ready);                                                          
            urat0_Send_data(6);
                       }
                       modbus_flag=0;
                       break;
       case 0x05:                                                           //置某个位
                       crcv=crc16(&R_Buffer0,6);//求CRC 如果CRC校验不正确则不处理
                       if(R_Buffer0!=crcv>>8|R_Buffer0!=crcv&0xff)        return;
                 addr=R_Buffer0;           //获取起始地址 (不同于寄存器)
                       temp=R_Buffer0;         //要设置的状态
                       if(temp==0xff)        //置1
                       {
                          crcv=1;
                          crcv=crcv<<addr;
                          reg=reg|crcv;
                       }
                       else                        //置0
                       {
                          crcv=1;
                          crcv=crcv<<addr;
                          crcv=~crcv;
                          reg=reg&crcv;
                       }
                       S_Buffer0=m_addr;
                       S_Buffer0=0x05;
                       S_Buffer0=0;
                       S_Buffer0=addr;
                       S_Buffer0=R_Buffer0;
             S_Buffer0=R_Buffer0;
                       S_Buffer0=R_Buffer0;
                       S_Buffer0=R_Buffer0;
                       while(!TX_Ready);                                                          
             urat0_Send_data(8);
                       modbus_flag=0;
                       break;
       case 0x03:                                                            //主机要读本机的寄存器
                 crcv=crc16(&R_Buffer0,6);//求CRC
                       if(R_Buffer0!=crcv>>8|R_Buffer0!=crcv&0xff)        return;
                 addr=R_Buffer0;            //要读的地址 0~6
             readCount =R_Buffer0*2;        //要读的个数 (16位)
             if(addr>50|readCount>100-2*addr) return;
             S_Buffer0=m_addr;                //目标机地址
             S_Buffer0=3;                        //命令号
             S_Buffer0=readCount;        //返回字节个数
             for(temp=0;temp<readCount+1;temp++)
             S_Buffer0=DATA;                        //数据
             crcv=crc16(&S_Buffer0,readCount+3);//求CRC
             S_Buffer0=crcv>>8;
             S_Buffer0=crcv&0xff;
             while(!TX_Ready);                                                          
             urat0_Send_data(readCount+5);
                       modbus_flag=0;
                       break; //读寄存器
       case 0x6:                                                                //主机要写本机的寄存器(单个)
            addr=R_Buffer0;            //要写的地址
                          
            DATA=R_Buffer0;           //要写数据 高
            DATA=R_Buffer0;   //低
            for(temp=0;temp<6;temp++)
            S_Buffer0=R_Buffer0;
            crcv=crc16(&S_Buffer0,6);
            S_Buffer0=crcv>>8;
            S_Buffer0=crcv&0xff;
            while(!TX_Ready);                                                          
            urat0_Send_data(8);
                          modbus_flag=0;
                           break; //设置单个寄存器
       case 0x10:                                                       //主机要写本机的寄存器(多个)
                   addr=R_Buffer0;         //要写的地址 0~6
               readCount =R_Buffer0*2;        //要写的个数 (16位)
               if(addr>50|readCount>100-2*addr) return;
               for(temp=0;temp<readCount+1;temp++) DATA=R_Buffer0;    //数据copy
               S_Buffer0=m_addr;
               S_Buffer0=0x10;
               S_Buffer0=0x00;
               S_Buffer0=addr;
               S_Buffer0=0x00;
               S_Buffer0=R_Buffer0;
               crcv=crc16(&S_Buffer0,6);
               S_Buffer0=crcv>>8;
               S_Buffer0=crcv&0xff;
               while(!TX_Ready);                                                          
               urat0_Send_data(8);
                           modbus_flag=0;
                           break;//设置多个寄存器
       default:break;
        }
}
}       
// timer0中断处理(modbus一个包接收完成)
//    完成标志为3.5个BYTE的延时时间
//-----------------------------          
void Timer0_ISR (void) interrupt 1
{
        TR0=0;         // Timer0 OFF
        if(UART_Input_First<4)                        //丢数据
        {                                                                       
        TH0 = Overflagtime&0xff00;         // Init Timer0 High register                    
    TL0 = Overflagtime&0x00ff;         // Set the intial Timer0 value       
        UART_Input_First=0;          
          return;       
        }
        TR0=0;                           
        if(R_Buffer0==m_addr)//是否是本机地址 并且是已处理完成包
        modbus_flag=1;
    UART_Input_First = 0;               //接收缓冲偏移归零
        TH0 = Overflagtime&0xff00;         // Init Timer0 High register                    
    TL0 = Overflagtime&0x00ff;         // Set the intial Timer0 value                  
        TR0=1;                                                 //开定时器       
}




//-----------------------------------------------------------------------------
// UART0_Interrupt
//-----------------------------------------------------------------------------
// 串口中断处理
//-----------------------------------------------------------------------------

void UART0_Interrupt (void) interrupt INTERRUPT_UART0
{
   uchar Byte;
   if (RI0 == 1)
   {
      RI0 = 0;            
      Byte = SBUF0;                           // Read a character from UART
          R_Buffer0 = Byte;
          UART_Input_First++;                                                                                                  
      TR0 = 0;                        // Timer0 OFF                                          说明:modbus的包尾为3.5个Byte的延时       
          TH0 = Overflagtime>>8;         // Init Timer0 High register                   使用定时器检查,如果定时器溢出
      TL0 = Overflagtime&0xff;         // Set the intial Timer0 value                   就去处理这个包。
          TR0 = 1;                                                // Timer0 On
                          
   }

   if (TI0 == 1)                   // Check if transmit flag is set
   {
      TI0 = 0;                           // Clear interrupt flag

      if (Rdata_size!= 1)         // If buffer not empty
      {
         Byte =S_Buffer0;

         SBUF0 = Byte;                   // Transmit to Hyperterminal

         UART_Output_First++;            // Update counter

      Rdata_size--;             // Decrease array size

      }
      else
      {
         Rdata_size = 0;            // Set the array size to 0
         TX_Ready = 1;                  // Indicate transmission complete
      }
   }
}                                  
//------------------------------
//写串口
//------------------------------
void urat0_Send_data(uchar len)
{   
UART_Output_First=0;
Rdata_size=len+1;
while(!TX_Ready);
TX_Ready=0;
SBUF0=S_Buffer0;
UART_Output_First++;
Rdata_size--;
}
/*
//------------------------------
//阻塞方式读串口 ( 等待READTIMEOUT个周期)
//传入:需要获取的数据长度
//返回:0 读len个BYTE成功 或返回实际读取个数
//------------------------------
int urat0_Recv_data(uchar len)
{
uchar temp=0;
for(;temp<BUFFERSIZE;temp++)R_Buffer0=0;
UART_Input_First=0;
temp=0;
while(UART_Input_First<len) {temp++; if(temp>READTIMEOUT) return UART_Input_First;};
return 0;
}                 */
//-------------------------------------------
//------------EOF------------------
//--------------------------------------------

/*
掉电数据存储
开辟一个CONST数组
用于数据的存储
*/
#include <main.h>
uchar code flash_page;//开辟一个 512 BYTE 的空间

/***********************************/
/* 函数名:void flash_read(void)
/*功能:把FLASH里的数据写进XRAM在开机时候会启用
/* 传入值
/*返回值
/***********************************/
void flash_read(void)
{
uint temp=0;
while(temp<100)
{
DATA=flash_page;
temp++;
}
}

/***********************************/
/* 函数名:void flash_write(void)
/*功能:把XRAM里的数据写进FLASH在掉电的时候会启用
/*工作机制 在掉电的一瞬间 全部外设的供电失效
/*IO输入io口在100ms 以内 全都为 “0”信号
/*但是单片机在储能电容的供电下仍然会运行大致500MS
/*利用这剩余的400 ms的时间进行数据的保存
/***********************************/
void flash_write(void)
{
uint temp=0;
uchar xdata* data p;
bit EA_s=EA;
EA=0;
FLSCL=0x81; //使能FLASH单稳态定时器       SYSCLK =48M
VDM0CN=0x80;//使能VDD监视器
RSTSRC=0X02; //上电复位VDD监视器复位标志
p=(uchar xdata *)&flash_page;
FLKEY=0XA5; //关键码1
FLKEY=0XF1; //关键码2
PSCTL |=0X03; //允许擦写
VDM0CN=0x80;//使能VDD监视器
RSTSRC=0X02; //上电复位VDD监视器复位标志
*p=0;
PSCTL &=~0X03; //禁止擦写
temp=0;
PSCTL =0;
PSCTL=0X01; //写使能
p=(uchar xdata *)&flash_page;
while(temp<100)
{
FLKEY=0XA5; //关键码1
FLKEY=0XF1; //关键码2
*p=DATA;
p++;
temp++;
}
PSCTL =0; //清除写使能
EA=EA_s;
}

windxiang 发表于 2012-6-30 07:14:55

能发源码到我邮箱吗 ?281453291@qq.com 谢谢。。。最近也在做这方面的东西

zhangyb 发表于 2012-6-30 08:00:25

不错,学习了,我也在做这方面的东西。

337zhang 发表于 2012-6-30 08:38:07

可以看看,谢谢了

cco 发表于 2012-6-30 08:51:17

mark,回去认真看一下

hmd420304805 发表于 2012-6-30 08:59:21

windxiang 发表于 2012-6-30 07:14 static/image/common/back.gif
能发源码到我邮箱吗 ? 谢谢。。。最近也在做这方面的东西

同学   源码已经在上面了         

cqfeiyuxmj 发表于 2012-6-30 09:10:40

加减速是关键

liming 发表于 2012-6-30 09:11:57

楼主做的效果怎么样,分享一下实验结果。

shi_90 发表于 2012-6-30 09:21:38

我不是很明白加速曲线需要那么多的表格数据么?

hmd420304805 发表于 2012-6-30 09:49:36

liming 发表于 2012-6-30 09:11 static/image/common/back.gif
楼主做的效果怎么样,分享一下实验结果。

这个不是实验已经在机器上应用了
7A的步进   拖着一个400KG 的东西 加减速不抖动,不丢步,跑一圈下来误差 5个丝。

hmd420304805 发表于 2012-6-30 09:52:05

shi_90 发表于 2012-6-30 09:21 static/image/common/back.gif
我不是很明白加速曲线需要那么多的表格数据么?

需要的定时器的装入值   定时器溢出就发脉冲
可以看做是分级调速分成255级

ITOP 发表于 2012-6-30 09:54:06

楼主用得多大的步进电机?

hmd420304805 发表于 2012-6-30 09:55:55

ITOP 发表于 2012-6-30 09:54 static/image/common/back.gif
楼主用得多大的步进电机?

7A   的   丝杆螺距 25mm    呵呵

ITOP 发表于 2012-6-30 09:59:58

步距角是多少?多大电压?是三相还是两相?是86的步进电机?{:lol:}

hmd420304805 发表于 2012-6-30 10:03:35

ITOP 发表于 2012-6-30 09:59 static/image/common/back.gif
步距角是多少?多大电压?是三相还是两相?是86的步进电机?

1.8 的36v两相

ITOP 发表于 2012-6-30 10:12:05

最近也要搞步进马达,不过只需拉动一二十KG的东西,还在选型步进电机和驱动器

hmd420304805 发表于 2012-6-30 10:55:30

ITOP 发表于 2012-6-30 10:12 static/image/common/back.gif
最近也要搞步进马达,不过只需拉动一二十KG的东西,还在选型步进电机和驱动器 ...

需要步进 可以找我, {:lol:}

lw32 发表于 2012-6-30 11:00:09

这东西值得学习,谢了

shi_90 发表于 2012-6-30 11:34:39

hmd420304805 发表于 2012-6-30 09:52 static/image/common/back.gif
需要的定时器的装入值   定时器溢出就发脉冲
可以看做是分级调速分成255级 ...

为什么不选用双定时器的方式呢?一个定时装入初值一个来进行时钟管理,这样减少数据的数量啊!!!

hmd420304805 发表于 2012-6-30 11:51:45

shi_90 发表于 2012-6-30 11:34 static/image/common/back.gif
为什么不选用双定时器的方式呢?一个定时装入初值一个来进行时钟管理,这样减少数据的数量啊!!! ...

定时器不够用    如果用这种方法    4个轴就必须要8个定时器       就算复用也要四个定时器
定时器还要用在其他地方    表格放在了CODE 区64K 的大小完全可以塞得下!

schlang 发表于 2012-7-3 16:58:55

正是需要,学习了

schlang 发表于 2012-7-4 15:20:26

刚好也遇到多轴的要求,正是需要这样单定时器方案,学习一下。

YAO342510 发表于 2012-7-4 17:39:31

{:loveliness:}好帖子~

nishuizhou 发表于 2014-3-11 14:45:30

谢谢,确实好代码

hmd420304805 发表于 2014-3-11 14:52:05

主控已经升级为stm32,4路100-60k全硬件定位脉冲输出.

tuowai 发表于 2014-6-11 01:25:33

学习学习 modbus

yangbing2020 发表于 2014-6-11 02:18:17

好代码,cool!

gmajvfhpa 发表于 2014-6-11 08:38:04

标记下:步进电机加减速算法 +组态王modbus通讯 +状态机+掉电数据

gxnnhy 发表于 2014-6-19 07:06:00

很棒!我求这代码求了很久,花了700块才有人帮我写STM32的加速算法!

sdsdc 发表于 2014-6-19 08:06:11

组态王modbus兼容freemodbus?

wkman 发表于 2014-6-19 14:04:10

组态那端咋用? :}{:victory:}{:shocked:}

huangxuankui 发表于 2014-6-19 17:55:58

支持一个,还是期待楼主把stm32的贡献出来,参考参考。

zhoust 发表于 2014-7-5 21:03:52


标记下:步进电机加减速算法 +组态王modbus通讯 +状态机+掉电数据,记号!

Cavsle 发表于 2014-7-16 18:40:24

谢谢,确实好代码

gy54321 发表于 2014-8-7 00:34:42

gxnnhy 发表于 2014-6-19 07:06
很棒!我求这代码求了很久,花了700块才有人帮我写STM32的加速算法!

700 块的加减速代码可真不贵。 找谁写的, 能否介绍下, 我也要写一个这种代码。

霸气侧漏 发表于 2014-8-7 08:43:00

是个好东西 支持了

hmd420304805 发表于 2014-8-7 10:13:44

gy54321 发表于 2014-8-7 00:34
700 块的加减速代码可真不贵。 找谁写的, 能否介绍下, 我也要写一个这种代码。 ...

我可以帮你写{:lol:}

mu838 发表于 2014-8-7 10:40:10

开源的,不错,支持一下

gxnnhy 发表于 2014-8-8 12:13:58

gy54321 发表于 2014-8-7 00:34
700 块的加减速代码可真不贵。 找谁写的, 能否介绍下, 我也要写一个这种代码。 ...

企鹅群里的小飞

机器人天空 发表于 2014-8-8 12:27:39

mark........

gy54321 发表于 2014-8-9 03:17:11

hmd420304805 发表于 2014-8-7 10:13
我可以帮你写

http://www.amobbs.com/thread-5529816-1-1.html

在这里买了个开发板, 提供了一个参考程序, 还正是我们这行用的, 所以, 我先研究一下。
实在搞不定, 再来找你们帮忙!!!
{:smile:} {:titter:}

136420962 发表于 2014-8-18 01:01:30

MARK            

ZYBing 发表于 2014-8-27 21:36:47

谢谢分享!

strongking 发表于 2014-9-7 09:43:36

不知道步进电机能加速到我少转/分?

Cavsle 发表于 2014-9-7 10:49:55

学习了,我也在做这方面的东西。

LCH201328 发表于 2014-9-7 11:13:53

最近正想玩玩步进电机,感谢分享资料

wenliangxc 发表于 2014-9-7 12:26:36

mark!{:victory:}

wq_601840968 发表于 2014-9-24 17:22:45

楼主是什么加减速 S型的吗

end2000 发表于 2014-10-12 22:52:10

步进电机。

sunli_suzhou 发表于 2014-10-24 17:42:25

步进电机!

amm 发表于 2014-10-25 14:25:18

步进电机加减速算法 +组态王modbus通讯 +状态机+掉电数据,记号!

阿文 发表于 2014-10-25 18:02:44

以后慢慢看。
页: [1]
查看完整版本: 步进电机加减速算法 +组态王modbus通讯 +状态机+掉电数据...