赞
踩
功能:由软件设定旋转角度实现正反转,根据旋转角度输出对应的脉冲个数。
我是根据正点原子步进电机定位实验写的。
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define F_CPU 16000000UL
#define PRESCALER 8 // 预分频系数
#define PWM_FREQUENCY 1500 // PWM频率(Hz)
#define TOP_VALUE ((F_CPU / PRESCALER / PWM_FREQUENCY) - 1) // 计算TOP值,注意数据类型
//串口初始化
#define MOTO_ENABLE PORTB &= ~(1 << PB4)
#define MOTO_DISABLE PORTB |= (1 << PB4)
#define MOTO_RIGHT PORTB |= (1 << PB6)
#define MOTO_LEFT PORTB &= ~(1 << PB6)
#define MAX_STEP_ANGLE 0.1125 /* 步距角 */
uint8_t g_run_flag;
typedef struct
{
int angle ; /* 存取角度值 */
uint8_t dir; /* 方向 */
uint8_t en; /* 使能 */
volatile uint32_t pulse_count; /* 角度转脉冲的脉冲数 */
volatile int add_pulse_count; /* ???????????? */
} STEPPER_MOTOR;
extern STEPPER_MOTOR g_stepper;
STEPPER_MOTOR g_stepper = {0};
void Io_Init(void)
{
DDRB |= (1 <<PB4) | (1 << PB6); //PB5设置为输出
PORTB &= ~(1 << PB4);
}
//定时器停止函数
void Pwm_Oc1a_Stop(void)
{
TCCR1A = 0;
MOTO_DISABLE;
}
//定时器1快速PWM
void timer1_pwm_init(void) {
DDRB |= (1 << PB5);
PORTB &= ~(1 << PB5);//输出低电平
TCNT1 = 0;
TCCR1B |=(1<<WGM13)|(1<<WGM12);//快速PWM,模式14 手册Page 122页 -> Table 61
TCCR1A |=(1<<WGM11)|(0<<WGM10);
TCCR1A |=(1<<COM1A1)|(0<<COM1A0);//OC1A输出模式,比较匹配时清零OC1A,在TOP时置位OC1A,手册Page 121页 -> Table 59
TCCR1B |= (0<<CS12)|(0<<CS11)|(1<<CS10);//Page124页,Table 62,8分频:8MHz/8=1MHz(1us),即定时器每一步1us
ICR1 = TOP_VALUE;//计数最大TOP值等于ICR1,PWM周期T=(ICR1+1)*1us,频率范围:15Hz(ICR1=0XFFFF) ~ 500KHz(ICR1=1,OCR1A=0) Page 113页-114页
OCR1A = ICR1 / 2;
TIMSK1 |= (1 << OCIE1A);
sei();
}
//角度转脉冲实现
void step_angle2pulse(int angle)
{
if (angle >= 0) //根据角度正负值判断正传还是反转
{
MOTO_RIGHT;
}else
{
angle = -angle; //取绝对值
MOTO_LEFT;
}
g_stepper.pulse_count = angle / MAX_STEP_ANGLE; //角度/步距角得出步数,一个步距角对应一个脉冲
if (g_stepper.pulse_count == 0)
{
Pwm_Oc1a_Stop();
}else
timer1_pwm_init();
}
uint8_t i = 0;
//中断服务函数
SIGNAL(TIMER1_COMPA_vect){
g_run_flag = 1;
g_stepper.pulse_count--;
if (PINB & (1 << PB6) ) //判断pb6电平状态,如果为高电平
{
g_stepper.add_pulse_count++; //脉冲个数累计
}else
{
g_stepper.add_pulse_count--;
}
if (g_stepper.pulse_count <= 0)
{
Pwm_Oc1a_Stop();
g_run_flag = 0;
}
DDRG |= (1 << PG5);
PORTG &= ~(1 << PG5);
}
void main(void){
int angle = 0;
Io_Init();
step_angle2pulse(-360);
while(1){
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。