?? stepmotor.c
字號:
/****************************************************************************
x和y兩個步進電機構成的一個平面上的直線函數,加減速直線函數. 使用Bresenham直線算法
適用于lpc2114,CPU頻率為55MHZ.
該直線算法在51單片機上也能獲得很好的效果
****************************************************************************/
typedef unsigned char uint8; /* defined for unsigned 8-bits integer variable 無符號8位整型變量 */
typedef signed char int8; /* defined for signed 8-bits integer variable 有符號8位整型變量 */
typedef unsigned short uint16; /* defined for unsigned 16-bits integer variable 無符號16位整型變量 */
typedef signed short int16; /* defined for signed 16-bits integer variable 有符號16位整型變量 */
typedef unsigned int uint32; /* defined for unsigned 32-bits integer variable 無符號32位整型變量 */
typedef signed int int32; /* defined for signed 32-bits integer variable 有符號32位整型變量 */
typedef float fp32; /* single precision floating point variable (32bits) 單精度浮點數(32位長度) */
typedef double fp64; /* double precision floating point variable (64bits) 雙精度浮點數(64位長度) */
// I/O口定義
#define XPU 0x00000400 //OUT P0.10口 X脈沖輸出端
#define XDR 0x00000800 //OUT P0.11口 X方向控制端 - 0右1左
#define YPU 0x00001000 //OUT P0.12口 Y脈沖輸出端
#define YDR 0x00002000 //OUT P0.13口 Y方向控制端 - 0上1下
uint32 x0 = 0; //步進平面中,x的當前坐標
uint32 y0 = 0; //步進平面中,y的當前坐標
//加/減速的相關參數,由系統參數中設置
uint8 dastep = 10; //加減速時的計數步長(即N個脈沖才加減一次速),設置范圍為1~100.
/****************************************************************************
* 名稱:Delay_n(uint32 delayn)
* 功能: 延時
* 入口參數:delayn - 延時長度
* 出口參數:
* delay_n(1) = 約為0.108083us
****************************************************************************/
void Delay_n(uint32 delayn)
{
for(; delayn > 0; delayn--);
}
/****************************************************************************
* 名稱:move_x(uint8 dr,uint32 delay)
* 功能:x方向走一步
* 入口參數: dr - 走線方向(1=正向,0=反向)
* delay - 走線速度的延時
* 出口參數:x0(全局變量) - x的當前坐標值
*
****************************************************************************/
void move_x(uint8 dr,uint32 delay)
{ uint8 xa;
IO0CLR = XPU; //輸出低電平
Delay_n(delay); //延時,為脈沖(低電平)寬度
IO0SET = XPU; //輸出高電平
Delay_n(delay); //延時,為脈沖(高電平)寬度
//計算當前的坐標值
if(dr)
{
x0++;
}
else
{
x0--;
}
}
/****************************************************************************
* 名稱:move_y(uint8 dr,uint32 delay)
* 功能:Y方向走一步
* 入口參數: dr - 走線方向(1=正向,0=反向)
* delay - 走線速度的延時
* 出口參數:y0(全局變量) - y的當前坐標值
*
****************************************************************************/
void move_y(uint8 dr,uint32 delay)
{ uint8 xa;
IO0CLR = YPU; //輸出低電平
Delay_n(delay); //延時,為脈沖(低電平)寬度
IO0SET = YPU; //輸出高電平
Delay_n(delay); //延時,為脈沖(高電平)寬度
//計算當前的坐標值
if(dr)
{
y0++;
}
else
{
y0--;
}
}
/****************************************************************************
* 名稱: Line_To_xy(uint32 x1,uint32 y1,uint32 delayn)
* 功能:x和y按指定的速度走一直線,從坐標(x0,y0)到(x1,y1)
* 入口參數:x1 - x的目標坐標
* y1 - y的目標坐標
* delayn - 走線速度
* 出口參數:
* //XY按設定的速度走一直線((x0,y0)-(x1,y1)))
****************************************************************************/
void Line_To_xy(uint32 x1,uint32 y1,uint32 delayn)
{ int32 e,dx,dy;
uint32 i,xdr,ydr;
//確定走線的長度和方向(在這里直接設置步進電機的方向)
if(x1 >= x0)
{dx = x1 - x0; IO0CLR = XDR;xdr = 1;} //X正向 0右1左
else
{dx = x0 - x1; IO0SET = XDR;xdr = 0;} //X反向
if(y1 >= y0)
{dy = y1 - y0; IO0CLR = YDR;ydr = 1;} //Y正向 0下1上
else
{dy = y0 - y1; IO0SET = YDR;ydr = 0;} //Y反向
if(dx >= dy) //x固定走dx步,y根據計算結束再決定是否走步進
{
e = -dx;
for(i = 1; i <= dx; i++)
{
e += 2 * dy;
move_x(xdr,delayn);
if(e >= 0) //判斷Y是否走一步
{
move_y(ydr,delayn);
e = e - 2 * dx;
}
}
}
else //y固定走dy步,x根據計算結束再決定是否步進
{
e = -dy;
for(i = 1; i <= dy; i++)
{
e = e + 2 * dx;
move_y(ydr,delayn);
if(e >= 0) //判斷X是否走一步
{
move_x(xdr,delayn);
e = e - 2 * dy;
}
}
}
}
/****************************************************************************
* 名稱: Accel_To_xy(uint32 x1,uint32 y1,uint32 minaccel,uint32 maxdelay)
* 功能:x和y按加/減速走一條直線,從坐標(x0,y0)到(x1,y1). 加速度曲線為梯形
* 入口參數:x1 - x的目標坐標
* y1 - y的目標坐標
* minaccel - 加速前的初始速度(越大越慢)
* maxdelay - 加速的最高速度(越小越快)
* 出口參數:
* 函數中的變量:
* acount - 加速器指針,即加速器在加速線上的當前位置.
* alen - 加速線的總長度
* shortlen - 1 = 其加速空間小于 "加速段 + 減速段" 的長度
* accelsta - 0 = 速度不變; 0x5A = 加速; 0xA5 = 減速;
* xcount - 加速度計數器,到達加速度后,加/減一次速
* dxdelay - 加速/減速的步數
****************************************************************************/
void Accel_To_xy(uint32 x1,uint32 y1,uint32 minaccel,uint32 maxdelay)
{ int32 e,dx,dy,ndelay;
uint32 i,acount=0,alen,dxdelay;
uint8 xcount = 0,shortlen,accelsta = 0x5a,xdr,ydr; //accelsta: 0=速度不變,5AH = 加速,A5H =減速;
//確定走線的長度和方向(在這里直接設置步進電機的方向)
if(x1 >= x0)
{dx = x1 - x0; IO0CLR = XDR; xdr = 1;} //X正向 0右1左
else
{dx = x0 - x1; IO0SET = XDR; xdr = 0;} //X反向
if(y1 >= y0)
{dy = y1 - y0; IO0CLR = YDR; ydr = 1;} //Y正向 0下1上
else
{dy = y0 - y1; IO0SET = YDR; ydr = 0;} //Y反向
alen = (dx + dy) / (2 * dastep); //整個梯形曲線加減速曲線的總長度
if(minaccel > maxdelay)
{ dxdelay = minaccel - maxdelay; } //加速/減速的步數
else
{ dxdelay = 0; } //無加減速
ndelay = minaccel; //加減速的起始速度
if(alen > dxdelay)
{shortlen = 0; alen = alen * 2;}
else
{shortlen = 1;} //shortlen = 1,表示加速空間小于加,減速量
if(dx >= dy) //x固定走dx步,y根據計算結束再決定是否走步進
{
e = -dx;
for(i = 1; i <= dx; i++)
{
xcount ++; //由于加/減速的總步長為dx+dy,所以X和Y分別每走一步,都要進行加減速度處理
if(xcount >= dastep) //x和y共同走了N步后進行一次加減速處理
{ acount ++;
xcount = 0;
if(accelsta == 0x5a) ndelay --; //加速
else if(accelsta == 0xa5) ndelay ++; //減速
}
e += 2 * dy;
move_x(xdr,ndelay);
if(e >= 0) //判斷Y是否走一步
{
move_y(ydr,ndelay);
xcount++; //由于加/減速的總步長為dx+dy,所以X和Y分別每走一步,都要進行加減速度處理
if(xcount >= dastep) //x和y共同走了N步后進行一次加減速處理
{ acount ++;
xcount = 0;
if(accelsta == 0x5a) ndelay --; //加速
else if(accelsta == 0xa5) ndelay ++; //減速
}
e = e - 2 * dx;
}
if(ndelay < maxdelay) ndelay = maxdelay;
if(shortlen) //加速空間小
{ if(accelsta == 0x5a)
{//判斷加速是否完成,以進入減速
if(acount >= alen)
{accelsta = 0xa5;alen=2 * alen;}
}
else if(accelsta == 0xa5)
{//判斷減速是否完成(減速完成后,以最低速運行剩下的線)
if(acount >= alen)
{accelsta = 0; ndelay = minaccel;}
}
}
else //加速空間大
{
if(accelsta == 0x5a)
{//判斷加速是否完成,以進入最高速
if(acount >= dxdelay)
{ accelsta = 0; }
}
else if(accelsta == 0xa5)
{ //判斷減速是否完成(減速完成后,以最低速運行剩下的線)
if(acount >= alen)
{accelsta = 0; ndelay = minaccel;}
}
else
{//判斷最高速是否完成,以進入減速
if((acount + dxdelay) >= alen)
{accelsta = 0xa5;}
}
}
}
}
else //y固定走dy步,x根據計算結束再決定是否走步進
{
e = -dy;
for(i = 1; i <= dy; i++)
{
xcount++; //由于加/減速的總步長為dx+dy,所以X和Y各走一步,都要計算加速度
if(xcount >= dastep)//x和y共同走了N步后進行一次加減速處理
{ acount ++;
xcount =0;
if(accelsta == 0x5a) ndelay --;
else if(accelsta == 0xa5) ndelay ++;
}
move_y(ydr,ndelay);
e = e + 2 * dx;
if(e >= 0) //判斷X是否走一步
{
move_x(xdr,ndelay);
e = e - 2 * dy;
xcount++; //由于加/減速的總步長為dx+dy,所以X和Y各走一步,都要計算加速度
if(xcount >= dastep)
{ acount ++;
xcount = 0;
if(accelsta == 0x5a) ndelay --;
else if(accelsta == 0xa5) ndelay ++;
}
}
if(ndelay < maxdelay) ndelay = maxdelay;
if(shortlen) //加速空間小
{ if(accelsta == 0x5a)
{//判斷加速是否完成,以進入減速
if(acount >= alen)
{accelsta = 0xa5;alen=2 * alen;}
}
else if(accelsta == 0xa5)
{//判斷減速是否完成(減速完成后,以最低速運行剩下的線)
if(acount >= alen)
{accelsta = 0; ndelay = minaccel;}
}
}
else //加速空間大
{
if(accelsta == 0x5a)
{//判斷加速是否完成,以進入最高速
if(acount >= dxdelay) {accelsta = 0;}
}
else if(accelsta == 0xa5)
{ //判斷減速是否完成(減速完成后,以最低速運行剩下的線)
if(acount >= alen) {accelsta = 0; ndelay = minaccel;}
}
else
{//判斷最高速是否完成,以進入減速
if((acount + dxdelay) >= alen) {accelsta = 0xa5;}
}
}
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -