реклама на сайте
подробности

 
 
> Генератор прямоугольных импульсов на AVR
PhX
сообщение Nov 11 2008, 04:21
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 473
Регистрация: 10-09-06
Из: Тольятти. Самарская обл.
Пользователь №: 20 249



Добрый день, необходимо управлять скоростью вращения шагового двигателя, для этого на плату управления двигателем нужно подавать прямоугольные импульсы с платы микроконтроллера.
Для начала написал это:
Код
#include <avr/io.h>
#include <avr/interrupt.h>

#define Frq 20 //Частота импульсов Гц


// Конфигурирование Timer1
void Timer1_init(void)
{
  TCCR1B |= 0x04; //Частота счета таймера Sclk/256
  TCCR1B |= 0x08; //Вкл CTC
  TCCR1A |= 0x40; //Активировать выход OC1A
  OCR1A = F_CPU/(256*Frq); //Определяем соответствующее значение для Frq
}

void Inter_init(void)
{
  TIMSK = 0x00; //Запрещаем все прерывания
  GIMSK = 0x00; //Запрет внешних прерываний
  cli(); //Общее запрещение прерываний;
}  

// Конфигурирование портов В/В
void Ports_init(void)
{
  DDRB = 0x0F; // PB1 Выход
}

int main (void)
{
  Ports_init();
  Timer1_init();
  Inter_init();
  while(1) {}  
  return 1;
}

Это работает нормально.
Теперь хочу плавно регулировать частоту:
Код
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define Frq 20 //Частота импульсов Гц

//Функция задания частоты
void SetSpeed(const unsigned int w)
{
  OCR1A = (F_CPU/w)>>8;
}

// Конфигурирование Timer1
void Timer1_init(void)
{
  TCCR1B |= 0x04; //Частота счета таймера Sclk/256
  TCCR1B |= 0x08; //Вкл CTC
  TCCR1A |= 0x40; //Активировать выход OC1A
  OCR1A = F_CPU/(256*Frq); //Определяем соответствующее значение для Frq
}

void Inter_init(void)
{
  TIMSK = 0x00; //Запрещаем все прерывания
  GIMSK = 0x00; //Запрет внешних прерываний
  cli(); //Общее запрещение прерываний;
}  

// Конфигурирование портов В/В
void Ports_init(void)
{
  DDRB = 0x0F; // PB1 Выход
}

int main (void)
{
  unsigned int i;
  Ports_init();
  Timer1_init();
  Inter_init();
  while(1)
  {
    while (i<5000)
    {
        SetSpeed(i); i++;
        _delay_ms(10);
    }
    _delay_ms(1000);
    while (i>2)
    {
        SetSpeed(i); i--;
        _delay_ms(10);
    }
  }  
  return 1;
}

Это работает весьма странно... Иногда нормально, а иногда импульсы прекращаются и на ноге OC1A устанавливается 0 или 1. 07.gif Прерывания вроде бы отключены.


--------------------
Если все, то не я...
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
sansnotfor
сообщение Nov 12 2008, 10:11
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 24-10-08
Пользователь №: 41 157



тоже нужно было генерить меандр, а генератора под рукой не было... вот что пришлось сваять.

Код
.....
unsigned char state_encoder=0;
unsigned int timer_tmp=4000; //начальное значение для OCR1A

void timer_init(void)
{
  TIMSK=(1<<TOIE0)|(1<<OCIE1A);
  TCNT0=TCNT0_const;
  TCCR0=TCCR0_const;  

  TCNT1=0;
  TCCR1A=(0<<COM1A1)|(1<<COM1A0)|(0<<WGM11)|(0<<WGM10);
  TCCR1B=(0<<WGM13)|(0<<WGM12)|(0<<CS12)|(0<<CS11)|(1<<CS10);
  OCR1A=timer_tmp;  
}


....

int main( void )
{
port_init();
Init_Encoder();
timer_init();
asm("sei");  


while(1)
{
if((state_encoder)!=0)
{
   if (state_encoder==0x01) {timer_tmp-=10;}
   else
   {
     if (state_encoder==0xff) {timer_tmp+=10;}
   }
   state_encoder=0;
}
}  


return 0;
}


//опрос энкодера
#pragma vector=TIMER0_OVF_vect
__interrupt void timer0_ovf_my(void)
{
  TCNT0=TCNT0_const;
  state_encoder=Read_Encoder();
  
}


#pragma vector=TIMER1_COMPA_vect
__interrupt void timer1_compa_my(void)
{
  TCNT1=0;
  OCR1A=timer_tmp;  
}


значение для timer_tmp устанавливается энкодером в основном цикле программы, а обновление OCR1A происходит в прерывании таймера1. прямоугольный сигнал генерится на выводе PD5(OC1A)
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 13:33
Рейтинг@Mail.ru


Страница сгенерированна за 0.01389 секунд с 7
ELECTRONIX ©2004-2016