/*
main.c
MCU:atmaga48
auther:chenjun
*/
//一个正弦波的1/4即一整步
#include <iom48v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int
#define CLKHIGH 0x100-25
#define CLKLOW 0x100-50
extern const char CurTab256[]; //={0,4,8,12,16,20,24,28};
extern const char CurTab400[]; //={0,4,8,12,16,20,24,28};
uchar ucPhase; //步进电机相位 最低位为0时A相通电,1时/A相通电,
//B相的相位确定:ucPhaseCount最低位为0,结合A相uiMinCurTotelLong/2决定B相的相位,uiStepCount*ucMinCurLong<uiCurTotelLong/2为/B,否则为B
// ucPhaseCount最低位为1,uiStepCount*ucMinCurLong<uiCurTotelLong/2为B,否则为/B
uchar ucMinNUM; //细分数
uchar ucMinCurLong; //每一细分电流长度
uchar ucCurTotLong; //细分电流总长
uchar ucDirect; //高为正向
uchar ucMinSwitch; //细分档位(拨码状态)
uchar ucACurent; //A相电流输出
uchar ucBCurent; //B相电流输出
uchar ucEn; //使能信号
uchar ucErr; //错误标志
uint ui4CurTotelLong; //4倍细分电流长度总长
uint ui4MinNUM;
uint ui4MinNUM_1;
uint uiStepCount; //步进电机步数计数器
const char *pCurtable;
void AVRInitialize() //初始化
{
PCICR=0b00000101; //DR,OC,EN 引脚电平变化中断控制寄存器
#if(CCW)
PCMSK2=0b01000000; //OC,DR
#else
PCMSK2=0b01010000; //OC,DR
#endif
PCMSK0=0b00000100; //EN
// TIMSK1=0x00; //T/C1 溢出中断使能
// TCCR1A=0b00000000; //CTC MAX=OCR1A
TCCR1B=0b11001111; //输入捕捉噪声抑制器,时钟由T1 引脚输入,上升沿触发,clkI/O/1 ( 无预分频) CTC
#if(CCW)
TIMSK0=0x01; //T/C0 溢出中断使能
TCCR0B=0x07; //时钟由T0 引脚输入,上升沿触发
#endif
ADMUX=0b01100110; //通道选择,左对齐, 参考电压AVCC,AREF引脚外加滤波电容
ADCSRA=0b10000000; //ADC使能
// TIMSK2=0x00; //中断屏蔽
TCCR2B=0b10000010; //预分频 1/8
TCNT2=CLKLOW; //50us
OCR2A=CLKHIGH; //50%
// while((ASSR&0b00010000)==0b00010000); //T/C2 更新中
// while((ASSR&0b00001000)==0b00001000); //输出比较寄存器2 更新中,写OCR2A将引起OCR2UB置位。当OCR2A从暂存寄存器更新完毕后OCR2AUB 由硬件清零
PORTB=0b11110100; //DB7为0,CLK2为0
DDRB=0b00111010; //写1输出
PORTB=0b11110100; //DB7为0
PORTC=0x00; //DB0--DB6为0
DDRC=0xff; //定义PC口为输出
PORTC=0x00;
PORTD=0b11000000;
DDRD=0b10001111; //AL,OC,PU,DR,/BA,BA,/AA,AA
PORTD=0b11000000;
}
void DataCheck()
{
uchar uci;
ucEn=0;
ucACurent=0;
ucBCurent=0;
if((ucMinNUM>200)||(ucMinNUM==0)||((128%ucMinNUM!=0)&&(200%ucMinNUM!=0))
||((ucCurTotLong!=200)&&(ucCurTotLong!=128)))
{
ucMinNUM=1;
ucCurTotLong=128;
}
ucMinCurLong=ucCurTotLong/ucMinNUM;
ui4MinNUM=ucMinNUM<<2;
ui4MinNUM_1=ui4MinNUM-1;
ui4CurTotelLong=ucCurTotLong<<2;
if(uiStepCount>=ui4MinNUM)
{
uiStepCount=0;
}
if((ucDirect!=1)&&(ucDirect!=0))
{
ucDirect=0;
}
if(PIND&0b00010000) //DR
{
uci=1;
}
else
{
uci=0;
}
if(uci!=ucDirect)
{
TCNT1=ui4MinNUM_1-TCNT1;
}
if(ucCurTotLong==128)
{
pCurtable=CurTab256;
}
else
{
pCurtable=CurTab400;
}
}
//选择细分数
uchar SelucMinNUM()
{
uchar i;
i=0;
i=i|(((!PORTB)&0x0c0)>>6);
ADMUX=0b01100110; //通道选择,左对齐, 参考电压AVCC,AREF引脚外加滤波电容
ADCSRA|=0b01000000; //ADSC: ADC 开始转换
while(ADCSRA&0b01000000);
if(ADCH<0x80)
{
i|=0b00000100;
}
ADMUX=0b01100111; //通道选择,左对齐, 参考电压AVCC,AREF引脚外加滤波电容
ADCSRA|=0b01000000; //ADSC: ADC 开始转换
while(ADCSRA&0b01000000);
if(ADCH<0x80)
{
i|=0b00001000;
}
return(i);
}
//查表
void LookTab()
{
uint uii;
uchar uci;
//计算电流
if(ucDirect)
{
uii=uiStepCount;
}
else
{
uii=ui4MinNUM_1-uiStepCount;
}
ucPhase=0;
while(uii>=ucMinNUM)
{
uii-=ucMinNUM;
ucPhase++; //计算相位
}
uci=uii;
uci*=ucMinCurLong; //细分电流表位置
if(ucCurTotLong==128)
{
if((ucPhase==0)||(ucPhase==2))
{
ucACurent=CurTab256[uci];
ucBCurent=CurTab256[uci+ucCurTotLong];
}
else
{
ucACurent=CurTab256[ucCurTotLong+uci];
ucBCurent=CurTab256[uci];
}
}
else
{
if((ucPhase==0)||(ucPhase==2))
{
ucACurent=CurTab400[uci];
ucBCurent=CurTab400[uci+ucCurTotLong];
}
else
{
ucACurent=CurTab400[ucCurTotLong+uci];
ucBCurent=CurTab256[uci];
}
}
if(ucEn==0)
{
ucACurent=ucACurent>>2;
ucBCurent=ucBCurent>>2;
}
}
//电流输出
void OutCurrent()
{
PORTB&=~(1<<PB5); //DAABCS=0; ADCSR &= ~(1<<ADEN);
PORTC=ucACurent;
PORTB&=~(1<<PB4); //WR=0;
_NOP();
PORTB|=(1<<PB4); //WR=1;
PORTB|=(1<<PB5); //DAABCS=1;
PORTC=ucBCurent;
PORTB&=~(1<<PB4); //WR=0;
NOP();
PORTB|=(1<<PB4); //WR=1;
switch(ucPhase)
{
case 0:
PORTD&=~(1<<PD1); //NAA=0;
PORTD&=~(1<<PD2); //BA=0;
PORTD|=(1<<PD0); //AA=1;
PORTD|=(1<<PD3); //NBA=1;
break;
case 1:
PORTD&=~(1<<PD1); //NAA=0;
PORTD&=~(1<<PD3); //NBA=0;
PORTD|=(1<<PD0); //AA=1;
PORTD|=(1<<PD2); //BA=1;
break;
case 2:
PORTD&=~(1<<PD0); //AA=0;
PORTD&=~(1<<PD3); //NBA=0;
PORTD|=(1<<PD1); //NAA=1;
PORTD|=(1<<PD2); //BA=1;
break;
case 3:
PORTD&=~(1<<PD0); //AA=0;
PORTD&=~(1<<PD2); //BA=0;
PORTD|=(1<<PD3); //NBA=1;
PORTD|=(1<<PD1); //NAA=1;
break;
default:
ucErr='T';
break;
}
}
//相位保持
void PhaseInitialize()
{
LookTab();
//输出
OutCurrent();
TCNT1=uiStepCount;
}
void DataSel()
{
if(ucMinSwitch<8)
{
ucMinNUM=(1<<ucMinSwitch);
ucMinCurLong=0x80>>ucMinSwitch; //1,2,4,8,16,32,64,128细分
ui4CurTotelLong=0x200;
}
else
{
switch(ucMinSwitch)
{
case 8: ucMinNUM=5;
break;
case 9: ucMinNUM=10;
break;
case 10: ucMinNUM=20;
break;
case 11: ucMinNUM=25;
break;
case 12: ucMinNUM=40;
break;
case 13: ucMinNUM=50;
break;
case 14: ucMinNUM=100;
break;
case 15: ucMinNUM=200;
break;
defaut: ucMinNUM=200;
break;
}
ucMinCurLong=200/ucMinNUM;
ui4CurTotelLong=800;
}
ui4MinNUM=ucMinNUM<<2;
ui4MinNUM_1=ui4MinNUM-1;
OCR1A=ui4MinNUM_1;
}
//****************************主程序****************************//
void main()
{
uint i;
uchar uci;
for(i=0;i<60000;i++)
{
}
AVRInitialize(); //I/O口及中断初始化
DataCheck();
PhaseInitialize();
ucMinNUM=SelucMinNUM(); //选择细分数
DataSel();
TCCR2A=0b11000011; //比较匹配发生时OC2A置位 快速 PWM
TIMSK2=0b00000001; //T/C2 溢出中断使能 0b00000001
SREG=0x80; //开全局中断
while(1)
{
uci=SelucMinNUM();
if(ucMinSwitch!=uci)
{
SREG&=0x7f; //关全局中断
ucMinSwitch=uci;
DataSel();
SREG|=0x80; //开全局中断
}
}
}
//使能信号
#pragma interrupt_handler EN_INT:3
void EN_INT(void)
{
if(PCMSK0|0b00000100)
{
if(PORTB&0b00000100)
{
ucEn=1;
TCCR1B|=0b00000111; //计数器1计数
}
else
{
ucEn=0;
TCCR1B&=0b11111000; //计数器1停止
}
}
PCMSK0=0xff;
}
//方向中断处理和过流信号
#pragma interrupt_handler DROC_INT:5
void DROC_INT(void)
{
//方向中断处理
if(PCMSK2|0b00010000)
{
if(PIND&0b00010000)
{
ucDirect=1;
}
else
{
ucDirect=0;
}
if(TCNT1!=0)
{
TCNT1=ui4MinNUM_1-TCNT1;
}
}
//过流
if(PCMSK2|0b01000000)
{
if((PIND&0b01000000)==0)
{
PORTD&=~(1<<PD7);
ucACurent=0;
ucBCurent=0;
TCCR1B&=0b11111000; //计数器1停止
TCCR2B&=0b11111000; //计数器2停止
ucErr='T';
OutCurrent();
}
/* else
{
PORTD|=(1<<PD7);
}*/
}
PCMSK2=0x0ff;
}
/*#pragma interrupt_handler CLK2_INT:7 //定时器/ 计数器2 溢出中断
void CLK2_INT(void)
{
_NOP();
ucErr='T';
}
*/
#pragma interrupt_handler CLK2_OV:10 //定时器/ 计数器2 溢出中断
void CLK2_OV(void)
{
uint ui,uj;
TCNT2=CLKLOW+TCNT2; //50us
// if(uiStepCount!=TCNT1)
{
uiStepCount=TCNT1;
LookTab();
OutCurrent();
}
}
没有合适的资源?快使用搜索试试~ 我知道了~
两相步进电机驱动程序及原理图
共55个文件
o:6个
s:6个
c:6个
5星 · 超过95%的资源 需积分: 50 420 下载量 188 浏览量
2008-10-24
06:54:57
上传
评论 27
收藏 99KB RAR 举报
温馨提示
两相步进电机驱动,最大电流可达8A,可设置最大细分数128,最快响应速度200K,采用atmega48控制。
资源推荐
资源详情
资源评论
收起资源包目录
step2406.rar (55个子文件)
step2406
CurTab200.c 940B
step2406.hex 7KB
iom48v.h 15KB
CurTab400.dp2 0B
step.aps 2KB
CurTab400.s 3KB
CurTab200.o 1KB
main.c 8KB
macros.h 1KB
step2406.mak 782B
CurTab200.i 0B
CurTab128._c 48B
step.aws 106B
CurTab256.lis 5KB
CurTab128.dp2 0B
step2406.prj 890B
CurTab400.i 0B
CurTab128.i 0B
2406.Sch 99KB
mainbak.s 24KB
step2406.mp 3KB
CurTab256.s 2KB
main._s 25KB
STEP2406.SRC 117B
CurTab128.o 828B
CurTab400.lis 8KB
step2406_cof.aws 247B
main._c 8KB
CurTab200._c 930B
CurTab128.s 1KB
main.dp2 57B
main.lis 60KB
CurTab128.c 617B
CurTab200.s 2KB
CurTab256.dp2 0B
CurTab200.lis 4KB
main.s 24KB
CurTab200.dp2 0B
step2406.lk 33B
CurTab256.i 0B
step2406.cof 7KB
step2406.dbg 5KB
step2406_cof.aps 3KB
main.o 16KB
step2406.lst 35KB
CurTab256.c 1KB
CurTab400.o 2KB
CurTab400.c 2KB
default
dep
main.o.d 0B
CurTab128.o.d 29B
CurTab128.o 2KB
Makefile 2KB
CurTab256.o 1KB
CurTab128.lis 3KB
main(080829).c 8KB
共 55 条
- 1
chenjun7531
- 粉丝: 2
- 资源: 4
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
- 3
- 4
前往页