搜索
bottom↓
回复: 51

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

  [复制链接]

出0入0汤圆

发表于 2012-6-29 17:58:06 | 显示全部楼层 |阅读模式
本帖最后由 hmd420304805 于 2012-6-30 08:57 编辑

(增加modbus 和组态王   mcgs通讯 :支持01   03  05  06 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[0];  //初始速度赋值         
  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[0];        //初始速度赋值        
  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[l3];
        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[l4];
   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 协议
uchar  Rdata_size= 0;
uchar  UART_Input_First = 0;
uchar  UART_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[uIndex] ;
                uchCRCLo = auchCRCLo[uIndex] ;
        }
        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[1])           //功能码分解
        {
    case 0x01:                                                           //读内部线圈
                 crcv=crc16(&R_Buffer0[0],6);  //求CRC 如果CRC校验不正确则不处理
                         if(R_Buffer0[6]!=crcv>>8|R_Buffer0[7]!=crcv&0xff)        return;
                 addr=R_Buffer0[3];             //获取起始地址 (不同于寄存器)
                         readCount =R_Buffer0[5];   //获取读取线圈个数
                         S_Buffer0[0]=m_addr;
                         S_Buffer0[2]=0x01;
                         if(readCount>8)  S_Buffer0[2]=2; else  S_Buffer0[2]=1;
                         crcv=reg>>addr;
                         if(readCount>8)
                         {
                          S_Buffer0[3]=2;
                          S_Buffer0[5]=crcv&0xff;
                          temp=0xff;
                          temp=temp<<readCount-8;
                          temp=~temp;
                          crcv=crcv>>8;
                          crcv=temp&crcv;
                          S_Buffer0[4]=crcv&0xff;
                          crcv=crc16(&S_Buffer0[0],5);
                          S_Buffer0[5]=crcv>>8;
              S_Buffer0[6]=crcv&0xff;
                          while(!TX_Ready);                                                            
              urat0_Send_data(7);
                         }
                         else
                         {
                          S_Buffer0[3]=1;
                          temp=0xff;
                          temp=temp<<readCount;
                          temp=~temp;
                          crcv=crcv&temp;
                          S_Buffer0[4]=crcv&0xff;
                          crcv=crc16(&S_Buffer0[0],4);
                          S_Buffer0[4]=crcv>>8;
              S_Buffer0[5]=crcv&0xff;
                          while(!TX_Ready);                                                            
              urat0_Send_data(6);
                         }
                         modbus_flag=0;
                         break;
         case 0x05:                                                           //置某个位
                         crcv=crc16(&R_Buffer0[0],6);  //求CRC 如果CRC校验不正确则不处理
                         if(R_Buffer0[6]!=crcv>>8|R_Buffer0[7]!=crcv&0xff)        return;
                 addr=R_Buffer0[3];             //获取起始地址 (不同于寄存器)
                         temp=R_Buffer0[4];         //要设置的状态
                         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[0]=m_addr;
                         S_Buffer0[1]=0x05;
                         S_Buffer0[2]=0;
                         S_Buffer0[3]=addr;
                         S_Buffer0[4]=R_Buffer0[4];
             S_Buffer0[5]=R_Buffer0[5];
                         S_Buffer0[6]=R_Buffer0[6];
                         S_Buffer0[7]=R_Buffer0[7];
                         while(!TX_Ready);                                                            
             urat0_Send_data(8);
                         modbus_flag=0;
                         break;
         case 0x03:                                                            //主机要读本机的寄存器
                 crcv=crc16(&R_Buffer0[0],6);  //求CRC
                         if(R_Buffer0[6]!=crcv>>8|R_Buffer0[7]!=crcv&0xff)        return;
                 addr=R_Buffer0[3];            //要读的地址 0~6
             readCount =R_Buffer0[5]*2;        //要读的个数 (16位)
             if(addr>50|readCount>100-2*addr) return;
             S_Buffer0[0]=m_addr;                //目标机地址
             S_Buffer0[1]=3;                        //命令号
             S_Buffer0[2]=readCount;        //返回字节个数
             for(temp=0;temp<readCount+1;temp++)
             S_Buffer0[temp+3]=DATA[temp+addr*2];                        //数据
             crcv=crc16(&S_Buffer0[0],readCount+3);  //求CRC
             S_Buffer0[readCount+3]=crcv>>8;
             S_Buffer0[readCount+4]=crcv&0xff;
             while(!TX_Ready);                                                            
             urat0_Send_data(readCount+5);
                         modbus_flag=0;
                         break; //读寄存器
         case 0x6:                                                                //主机要写本机的寄存器(单个)
              addr=R_Buffer0[3];            //要写的地址
                          
              DATA[2*addr]=R_Buffer0[4];           //要写数据 高
              DATA[2*addr+1]=R_Buffer0[5];     //低
              for(temp=0;temp<6;temp++)
              S_Buffer0[temp]=R_Buffer0[temp];
              crcv=crc16(&S_Buffer0[0],6);
              S_Buffer0[6]=crcv>>8;
              S_Buffer0[7]=crcv&0xff;
              while(!TX_Ready);                                                            
              urat0_Send_data(8);
                          modbus_flag=0;
                           break; //设置单个寄存器
         case 0x10:                                                         //主机要写本机的寄存器(多个)
                   addr=R_Buffer0[3];           //要写的地址 0~6
               readCount =R_Buffer0[5]*2;        //要写的个数 (16位)
               if(addr>50|readCount>100-2*addr) return;
               for(temp=0;temp<readCount+1;temp++) DATA[addr+temp]=R_Buffer0[6+temp];    //数据copy
               S_Buffer0[0]=m_addr;
               S_Buffer0[1]=0x10;
               S_Buffer0[2]=0x00;
               S_Buffer0[3]=addr;
               S_Buffer0[4]=0x00;
               S_Buffer0[5]=R_Buffer0[5];
               crcv=crc16(&S_Buffer0[0],6);
               S_Buffer0[6]=crcv>>8;
               S_Buffer0[7]=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[0]==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[UART_Input_First] = 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[UART_Output_First];

         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];
  UART_Output_First++;
  Rdata_size--;
}
/*
//------------------------------
//阻塞方式读串口 ( 等待READTIMEOUT个周期)
//传入:需要获取的数据长度
//返回:0 读len个BYTE成功 或返回实际读取个数
//------------------------------
int urat0_Recv_data(uchar len)  
{
  uchar temp=0;
  for(;temp<BUFFERSIZE;temp++)  R_Buffer0[temp]=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];  //开辟一个 512 BYTE 的空间

/***********************************/
/* 函数名:void flash_read(void)
/*功能:把FLASH里的数据写进XRAM  在开机时候会启用
/* 传入值  
/*返回值
/***********************************/
void flash_read(void)
{
  uint temp=0;
  while(temp<100)
  {
  DATA[temp]=flash_page[temp];
  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[0];
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[0];
while(temp<100)
{
FLKEY=0XA5; //关键码1
FLKEY=0XF1; //关键码2
*p=DATA[temp];
  p++;
  temp++;
}
PSCTL =0; //清除写使能
EA=EA_s;
}

出0入0汤圆

发表于 2012-6-30 07:14:55 | 显示全部楼层
能发源码到我邮箱吗 ?281453291@qq.com 谢谢。。。最近也在做这方面的东西

出0入0汤圆

发表于 2012-6-30 08:00:25 | 显示全部楼层
不错,学习了,我也在做这方面的东西。

出0入0汤圆

发表于 2012-6-30 08:38:07 | 显示全部楼层
可以看看,谢谢了

出0入0汤圆

发表于 2012-6-30 08:51:17 来自手机 | 显示全部楼层
mark,回去认真看一下

出0入0汤圆

 楼主| 发表于 2012-6-30 08:59:21 | 显示全部楼层
windxiang 发表于 2012-6-30 07:14
能发源码到我邮箱吗 ? 谢谢。。。最近也在做这方面的东西

同学   源码已经在上面了         

出0入0汤圆

发表于 2012-6-30 09:10:40 | 显示全部楼层
加减速是关键

出0入0汤圆

发表于 2012-6-30 09:11:57 | 显示全部楼层
楼主做的效果怎么样,分享一下实验结果。

出0入0汤圆

发表于 2012-6-30 09:21:38 | 显示全部楼层
我不是很明白加速曲线需要那么多的表格数据么?

出0入0汤圆

 楼主| 发表于 2012-6-30 09:49:36 | 显示全部楼层
liming 发表于 2012-6-30 09:11
楼主做的效果怎么样,分享一下实验结果。

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

出0入0汤圆

 楼主| 发表于 2012-6-30 09:52:05 | 显示全部楼层
shi_90 发表于 2012-6-30 09:21
我不是很明白加速曲线需要那么多的表格数据么?

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

出0入0汤圆

发表于 2012-6-30 09:54:06 | 显示全部楼层
楼主用得多大的步进电机?

出0入0汤圆

 楼主| 发表于 2012-6-30 09:55:55 | 显示全部楼层
ITOP 发表于 2012-6-30 09:54
楼主用得多大的步进电机?

7A   的     丝杆螺距 25mm    呵呵

出0入0汤圆

发表于 2012-6-30 09:59:58 | 显示全部楼层
步距角是多少?多大电压?是三相还是两相?是86的步进电机?

出0入0汤圆

 楼主| 发表于 2012-6-30 10:03:35 | 显示全部楼层
ITOP 发表于 2012-6-30 09:59
步距角是多少?多大电压?是三相还是两相?是86的步进电机?

1.8 的  36v  两相

出0入0汤圆

发表于 2012-6-30 10:12:05 | 显示全部楼层
最近也要搞步进马达,不过只需拉动一二十KG的东西,还在选型步进电机和驱动器

出0入0汤圆

 楼主| 发表于 2012-6-30 10:55:30 | 显示全部楼层
ITOP 发表于 2012-6-30 10:12
最近也要搞步进马达,不过只需拉动一二十KG的东西,还在选型步进电机和驱动器 ...

需要步进 可以找我,

出0入0汤圆

发表于 2012-6-30 11:00:09 | 显示全部楼层
这东西值得学习,谢了

出0入0汤圆

发表于 2012-6-30 11:34:39 | 显示全部楼层
hmd420304805 发表于 2012-6-30 09:52
需要的定时器的装入值     定时器溢出就发脉冲
可以看做是分级调速  分成255级 ...

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

出0入0汤圆

 楼主| 发表于 2012-6-30 11:51:45 | 显示全部楼层
shi_90 发表于 2012-6-30 11:34
为什么不选用双定时器的方式呢?一个定时装入初值一个来进行时钟管理,这样减少数据的数量啊!!! ...

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

出0入0汤圆

发表于 2012-7-3 16:58:55 | 显示全部楼层
正是需要,学习了

出0入0汤圆

发表于 2012-7-4 15:20:26 | 显示全部楼层
刚好也遇到多轴的要求,正是需要这样单定时器方案,学习一下。

出0入0汤圆

发表于 2012-7-4 17:39:31 | 显示全部楼层
好帖子~

出0入0汤圆

发表于 2014-3-11 14:45:30 | 显示全部楼层
谢谢,确实好代码

出0入0汤圆

 楼主| 发表于 2014-3-11 14:52:05 来自手机 | 显示全部楼层
主控已经升级为stm32,4路100-60k全硬件定位脉冲输出.

出0入0汤圆

发表于 2014-6-11 01:25:33 | 显示全部楼层
学习学习 modbus

出0入0汤圆

发表于 2014-6-11 02:18:17 | 显示全部楼层
好代码,cool!

出0入0汤圆

发表于 2014-6-11 08:38:04 | 显示全部楼层
标记下  :步进电机加减速算法 +组态王modbus通讯 +状态机+掉电数据

出0入0汤圆

发表于 2014-6-19 07:06:00 | 显示全部楼层
很棒!我求这代码求了很久,花了700块才有人帮我写STM32的加速算法!

出0入0汤圆

发表于 2014-6-19 08:06:11 | 显示全部楼层
组态王modbus兼容freemodbus?

出0入0汤圆

发表于 2014-6-19 14:04:10 | 显示全部楼层
组态那端咋用? :}

出0入0汤圆

发表于 2014-6-19 17:55:58 | 显示全部楼层
支持一个,还是期待楼主把stm32的贡献出来,参考参考。

出0入0汤圆

发表于 2014-7-5 21:03:52 | 显示全部楼层

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

出0入0汤圆

发表于 2014-7-16 18:40:24 | 显示全部楼层
谢谢,确实好代码

出0入0汤圆

发表于 2014-8-7 00:34:42 | 显示全部楼层
gxnnhy 发表于 2014-6-19 07:06
很棒!我求这代码求了很久,花了700块才有人帮我写STM32的加速算法!

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

出0入0汤圆

发表于 2014-8-7 08:43:00 | 显示全部楼层
是个好东西 支持了

出0入0汤圆

 楼主| 发表于 2014-8-7 10:13:44 | 显示全部楼层
gy54321 发表于 2014-8-7 00:34
700 块的加减速代码可真不贵。 找谁写的, 能否介绍下, 我也要写一个这种代码。 ...

我可以帮你写

出0入0汤圆

发表于 2014-8-7 10:40:10 | 显示全部楼层
开源的,不错,支持一下

出0入0汤圆

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

企鹅群里的小飞

出0入0汤圆

发表于 2014-8-8 12:27:39 | 显示全部楼层
mark........

出0入0汤圆

发表于 2014-8-9 03:17:11 | 显示全部楼层

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

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

出0入0汤圆

发表于 2014-8-18 01:01:30 | 显示全部楼层
MARK            

出0入0汤圆

发表于 2014-8-27 21:36:47 | 显示全部楼层
谢谢分享!

出0入0汤圆

发表于 2014-9-7 09:43:36 | 显示全部楼层
不知道步进电机能加速到我少转/分?

出0入0汤圆

发表于 2014-9-7 10:49:55 | 显示全部楼层
学习了,我也在做这方面的东西。

出0入0汤圆

发表于 2014-9-7 11:13:53 | 显示全部楼层
最近正想玩玩步进电机,感谢分享资料

出0入0汤圆

发表于 2014-9-7 12:26:36 | 显示全部楼层
mark!

出0入0汤圆

发表于 2014-9-24 17:22:45 | 显示全部楼层
楼主是什么加减速 S型的吗

出0入0汤圆

发表于 2014-10-12 22:52:10 | 显示全部楼层
步进电机。

出0入0汤圆

发表于 2014-10-24 17:42:25 | 显示全部楼层
步进电机!

出0入0汤圆

发表于 2014-10-25 14:25:18 | 显示全部楼层
步进电机加减速算法 +组态王modbus通讯 +状态机+掉电数据,记号!

出0入0汤圆

发表于 2014-10-25 18:02:44 | 显示全部楼层
以后慢慢看。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-4 07:38

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表