3.7.1 控制系统硬件
基于 ATmega48 单片机的两相混合式步进电动机角度细分控制电路原理图如图 345 所示。
单片机的 T1 定时器产生一个恒频脉冲信号 CLK,作为 D 触发器 74ALS74 和 8 位串行 D/A 转
换器 Max522 的时钟; 单片机实现脉冲分配, 并由 PB3、 PB4 口输出两相绕组的导通控制信号;
同时, 单片机根据指令要求输出各相绕组的给定电流, 并由 Max522 转换为模拟信号 Ig1、 Ig2,
通过恒频斩波实现步进电动机的角度细分控制。
电流采样信号 FB1 和 FB2 首先经阻容滤波后,与由 R17 和 R18(或 R22 和 R23)分压得 到的给定电压进行比较,实现硬件电流保护;然后利用运算放大器 LM324 对每相绕组的电流 采样值进行放大,放大后的电流信号与 Max522 输出的电流给定信号 Ig1(或 Ig2)一起送入 LM339 比较器进行比较,实现斩波控制。
显示电路由 SN74HC595 和 LG2641 组成。SN74HC595 为 8 位移位寄存器,QAQH 为并 行数据输出,SER 为串行数据输入,RCLK 为输出寄存器时钟,SRCLK 为串行数据时钟。在 SRCLK 上升沿,SER 的数据被锁存到 SN74HC595 寄存器中,随着 SRCLK 时钟的推进,8 位 数据依次被送到 SN74HC595 中,由于 SN74HC595 是带输出锁存的,只有在 RCLK 上升时,
新的 8 位数据才会更新到 QAQH 中。
(a)单片机与 D 触发器和 D/A 转换器
图 345 基于 ATmega48 单片机的两相混合式步进电动机控制系统原理图
(b)显示电路
(c)A 相驱动和保护电路
图 345 基于 ATmega48 单片机的两相混合式步进电动机控制系统原理图(续图)
(d)B 相驱动和保护电路
图 345 基于 ATmega48 单片机的两相混合式步进电动机控制系统原理图(续图)
LG3641AH 为 4 位 8 段共阳极数码管,COM1~COM4 引脚电平为高时,对应的数码管才 亮。为了简化电路,此处采用动态显示。在每一瞬间,SN74HC595 并行输出口输出相应的 8 位数码管段码,而位选则控制 I/O 口输出该显示位的选通电平,保证该位显示相应字符。
四位数码管从左到右依次显示:模式(1、2) 、正反转(0、1) 、角度细分等级(1、2、3) 、 速度等级(0~8) ,其中模式 1 为角度细分控制,模式 2 是速度控制。
按键的功能分配如下:
S1开始/停止;S4正转/反转;S5复位;S3模式 1 选择,在模式 1 下,S2 键角度细分加,
S3角度细分减;S4模式 2 选择,在模式 2 下,S2速度加,S3速度减。
3.7.2 控制软件例程
/**************************************************************/
/*功能:基于 ATmega48 单片机的两相混合式步进电动机角度细分控制*/
/*文件名:step_motor.c;开发环境:ICCAVR */
/*编制:大连理工大学电气工程学院大学生创新实践小组 */
/*完成日期:2008 年 9 月 */
/**************************************************************/
#include <iom48v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int uint t[4]={17,16,15,14};
uint Table[]=
temp>>=1; //第 7 位控制位 temp&=0x40;
PORTD&=0xbf;
control=0x1a; //送 B 寄存器(01) given=temp1;
temp1+=0xff/n;
DAconver(control,given);
control=0x00; //两通道打开 given=0xff;
DAconver(control,given);
PORTB|=0x18; //PB3、PB4 输入高电平,传递到 D 口中 PORTD&=0xdf;
PORTD|=0x20; //产生一个时钟 CLK 的上升沿 }
} break;
case 1: {
temp1=0xff;
for(i=1;i<=n;i++) { //产生 AQ(10) BQ(1) 2
control=0x19; //送 A 寄存器(10) given=temp1;
temp1=0xff/n;
DAconver(control,given);
control=0x1a; //送 B 寄存器(1) given=0xff;
DAconver(control,given);
control=0x00; //两通道打开 given=0xff;
DAconver(control,given);
PORTB|=0x18; //PB3、PB4 输入高电平,传递到 D 口中 PORTD&=0xdf;
PORTD|=0x20; //产生一个时钟 CLK 的上升沿 }
}break;
case 2:{
temp1=0;
for(i=1;i<=n;i++) {
control=0x19; //产生/AQ(01) BQ(1) 3 given=temp1;
PORTB&=0xf7; //PB3 输入低电平,传递到 A D 口中 PORTB|=0x10; //PB4 输入高电平,传递到 B D 口中 PORTD&=0xdf;
PORTD|=0x20; //产生一个时钟 CLK 的上升沿 }
}break;
case 3: { temp1=0xff;
for(i=1;i<=n;i++){
control=0x19; //产生 /AQ(1) BQ(10) 4 given=0xff;
DAconver(control,given);
PORTB&=0xf7; //PB3 输入低电平,传递到 A D 口中 PORTB|=0x10; //PB4 输入高电平,传递到 B D 口中 PORTD&=0xdf;
PORTD|=0x20; //产生一个时钟 CLK 的上升沿 }
}break;
case 4: { temp1=0;
for(i=1;i<=n;i++){
control=0x19; //产生 /AQ(1) /BQ(01) 5 given=0xff;
PORTD|=0x20; //产生一个时钟 CLK 的上升沿 }
}break;
case 5: { temp1=0xff;
for(i=1;i<=n;i++) {
control=0x19;//产生 /AQ(10) /BQ(1) 6 given=temp1;
PORTD|=0x20; //产生一个时钟 CLK 的上升沿 }
}break;
case 6:{
temp1=0;
for(i=1;i<=n;i++){
control=0x19; //产生 AQ(01) /BQ(1) 7 given=temp1;
PORTD|=0x20; //产生一个时钟 CLK 的上升沿 }
}break;
case 7:{
temp1=0xff;
for(i=1;i<=n;i++){
control=0x19; //产生 AQ(1) /BQ(10) 8 given=0xff;
PORTD|=0x20; //产生一个时钟 CLK 的上升沿 }
if(j==0) PORTB|=0x01; //4 位数码管的最低位 COM1 if(j==1) PORTB|=0x02; //4 位数码管的第二位 COM2
if(j==2) PORTC|=0x10; //4 位数码管的第三位 COM3 if(j==3) PORTC|=0x20; //4 位数码管的第四位 COM4 }
/************************显示子程序****************************/
void Display(uint *t) {
uint i,j,sel;
for(j=0;j<4;j++) {
for(i=1;i<=8;i++){ //输入八位数据,即八位段码 sel=Table[t[j]];
sel>>=(i1);
sel&=0x01; //保留最低位 PORTD&=0xfe; //最低位 PD0 清零 PORTD|=sel; //给 PD0 输入值 PORTC&=0xfe; //使 PC0 为低电平
PORTC|=0x01; //使 PC0 为高电平,由此产生一个上升沿 }
PORTC&=0xfd;
PORTC|=0x02; //PC1 产生一个上升沿,输出数据 ledbit(j); //位选通
DelayMs (3); //延时 PORTC&=0xcf;
PORTB&=0xfc; //清除位选通信号 }
TCCR1B = 0x00; //stop T1 显示中断 TCNT1H=0xff;
TCNT1L=0x1f;
TCCR1B=0x03;
TIMSK1=0x01;
SREG=0x80;
while(1) {
if((PIND&0x04)==0) {t[3]=1;t[2]=0;t[1]=1;t[0]=3;break;} //S3 键:模式 1 角度细分 if((PIND&0x08)==0) {t[3]=2;t[2]=0;t[1]=1;t[0]=0;break;} //S4 键:模式 2 速度控制 }
TCCR0B = 0x00; //stop T0 加速中断 TCNT0 = 0xff;
TCCR0B=0x06;
TIMSK0=0x01;
MCUCR = 0x00; //INT0 减速中断 EICRA = 0x0A; //extended ext ints //下降沿 EIMSK = 0x03;
while(1) {
subdividing(R,t[1]);
if(t[2]==0) R++;
else R;
if(t[1]!=3) t[1]++;
} else {
if(t[0]!=8) t[0]++;
}
if(t[1]!=1) t[1];
} else {
if(t[0]!=0) t[0];
} }
#pragma interrupt_handler int1_isr:3