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

 
 
> Генератор прямоугольных импульсов на 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
Ответов
МП41
сообщение Nov 12 2008, 14:11
Сообщение #2


4 синих кубика
****

Группа: Участник
Сообщений: 526
Регистрация: 19-09-08
Из: полупроводника, металла и стекла
Пользователь №: 40 326



При записи в регистры Таймера1, например, в OCR1A, есть ньюансы. Эти ньюансы описаны в даташите, указан порядок заполнения старшего и младшего байтов регистра, правда это для ассемблера, а Си вроде как должен знать эту особенность (так написано). Я на асме писал в регистры не в том порядке и долго не мог добиться, чтобы срабатывало прерывание по совпадению, хотя в AVRStudio всё пошагово отрабатывалось как надо. Кстати, в Proteus'е тоже ерунду показывало, точно как на макете было, покуда не учёл этот ньюанс. Казалось бы мелочь, а времени потерял вагон.


--------------------
p-n-p-p-n-p-n-n-p-n-p структура однако очень эффективна
Go to the top of the page
 
+Quote Post
PhX
сообщение Nov 12 2008, 15:12
Сообщение #3


Местный
***

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



Вообщем GDI был прав, но почему-то поправил пост... 05.gif Постеснялся наверное...
Код
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define Frq 10 //×åñòîòà ïåðåêëþ÷åíèÿ Ãö

void SetSpeed(uint16_t w)
{
    uint8_t sreg;
    sreg = SREG;
    cli();
    OCR1A = (F_CPU>>3)/w;
    SREG = sreg;
}
// Êîíôèãóðèðîâàíèå Timer1
void Timer1_init(void)
{
  TCCR1B |= 0x02; //×àñòîòà ñ÷åòà òàéìåðà Sclk/256
  TCCR1B |= 0x18; //Âêë fast PWM
  TCCR1A |= 0x03; //ñ 50% ïðîäîëæèòåëüíîñòüþ öèêëà
  TCCR1A |= 0x40; //Àêòèâèðîâàòü âûõîä OC1A
  OCR1A = (F_CPU>>3)/Frq; //Îïðåäåëÿåì ñîîòâåòñòâóþùåå çíà÷åíèå äëÿ Frq
}

void Inter_init(void)
{
  TIMSK = 0x00; //Çàïðåùàåì âñå ïðåðûâàíèÿ
  GIMSK = 0x00; //Çàïðåò âíåøíèõ ïðåðûâàíèé
  cli(); //Îáùåå çàïðåùåíèå ïðåðûâàíèé;
}  

// Êîíôèãóðèðîâàíèå ïîðòîâ Â/Â
void Ports_init(void)
{
  DDRB = 0x0F; // PB1 Âûõîä
}

int main(void)
{
  uint16_t i=10;
  Ports_init();
  Timer1_init();
  Inter_init();
  while(1)
  {
      for (i=10; i<10000; i=i+10)
      {
      SetSpeed(i);
      _delay_ms(20);
      }
      for (; i>10; i=i-10)
    {
      SetSpeed(i);
      _delay_ms(20);
    }
  }  
  return 1;
}

А вот решение проблемы:
Эскизы прикрепленных изображений
Прикрепленное изображение
 


--------------------
Если все, то не я...
Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 01:12
Рейтинг@Mail.ru


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