Easyelectronics.ru

Электроника для всех
Текущее время: 08 мар 2021, 08:40

Часовой пояс: UTC + 5 часов



JLCPCB – Прототипы печатных плат за $2/5шт. два слоя. $5/5шт. четыре слоя
Крупнейший производитель печатных плат и прототипов. Более 600000 клиентов и свыше 10000 заказов в день!
Получите скидку на почтовую отправку при первом заказе в JLCPCB!

Начать новую тему Ответить на тему  [ Сообщений: 10 ] 
Автор Сообщение
 Заголовок сообщения: Таймеры,PWM,прерывания
СообщениеДобавлено: 19 фев 2010, 16:36 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 26 янв 2010, 21:31
Сообщения: 33
Откуда: Днепропетровск
Здравствуйте всем!Начал учить микроконтроллеры.Начал с Atmega32.Хочу сделать реобас для компа.4 канала ШИМ аппаратных задействованы.Работают(в Протеусе пока).
Добавил динамическую индикацию для 7 сегментников(Функция вывода вызывается в основном цикле программы) но как то медленно она работает(тактирование Атмеги 8 мГц).Тоесть думаю надо ее вызывать через прерывания?так же необходимо подсчитывать колличество оборотов с 4 каналов(тож думаю без прерываний не обойтись).На ШИМ настроены все 4 таймера.Вопрос :как задействовать прерывания если все таймеры настроены на ШИМ?Может как то по другому можна?Пытаюсь писать на С в Код Вижн.Каой вообше алгоритм работы подобных устройств?

тут проекты для Протеуса и код вижна.
Буду рад за любую подсказку...


Вложения:
projects.rar [63.11 Кб]
Скачиваний: 213
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Таймеры,PWM,прерывания
СообщениеДобавлено: 19 фев 2010, 17:06 
Супермодератор
Аватара пользователя

Зарегистрирован: 28 янв 2010, 05:47
Сообщения: 1027
Откуда: Винница
Для ШИМа можно использовать 1 таймер в режиме прерывания по совпадению. Например Т1, по 2 канала ШИМ на 1 прерывание. Сначала в регистр сравнения пихаешь меньше из 2 значений, по прерыванию выставляешь 1 на нужной ноге и пихаешь большее значение (или ничего не пихаешь если они равны). По переполнению выставляешь везде 0 и опять пихаешь меньшее и т.д.
Тогда на 2 оставшихся таймерах делаешь динамическую индикацию (хотя можно и на этом же, по переполнению переключать разряды - зависит от частоты ШИМа).
А считать обороты... Ну можно использовать 3 внешних прерывания и 1 канал АЦП, например :)

_________________
Show


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Таймеры,PWM,прерывания
СообщениеДобавлено: 19 фев 2010, 21:06 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 26 янв 2010, 21:31
Сообщения: 33
Откуда: Днепропетровск
xrayman писал(а):
Для ШИМа можно использовать 1 таймер в режиме прерывания по совпадению. Например Т1, по 2 канала ШИМ на 1 прерывание. Сначала в регистр сравнения пихаешь меньше из 2 значений, по прерыванию выставляешь 1 на нужной ноге и пихаешь большее значение (или ничего не пихаешь если они равны). По переполнению выставляешь везде 0 и опять пихаешь меньшее и т.д.
Тогда на 2 оставшихся таймерах делаешь динамическую индикацию (хотя можно и на этом же, по переполнению переключать разряды - зависит от частоты ШИМа).
А считать обороты... Ну можно использовать 3 внешних прерывания и 1 канал АЦП, например :)


А можно по подробнее пожалуйста?если не затруднит.Или пример кода если можно?Я понял это будет програмный ШИМ?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Таймеры,PWM,прерывания
СообщениеДобавлено: 19 фев 2010, 22:29 
Супермодератор
Аватара пользователя

Зарегистрирован: 28 янв 2010, 05:47
Сообщения: 1027
Откуда: Винница
stolyars писал(а):
А можно по подробнее пожалуйста?если не затруднит.Или пример кода если можно?Я понял это будет програмный ШИМ?


Программный. Нуачо? Для управления вентиляторами (а я так понял, управлять будешь ими) такой точности даже много будет :)

А подробнее... Есть в 32 меге таймер1, тот который 16-битный, у него есть 2 независимых модуля сравнения. Т.е. текущее значение счетного регистра таймера сравнивается со значением регистра модуля сравения. И если эти значения равны - выскакивает прерывание (а так как модуля два - прерывания тоже 2, независимых друг от друга). При этом, по достижению счетным регистром значения 65536, выскакивает еще прерывание по переполнению.

Идея такая: каждый модуль сравнения будет отвечать за два канала ШИМ.
Рассмотрим один из этих модулей:
По переполнению таймера, на ноги, на которые выводится ШИМ выставляем "0" и в регистр сравнения пихаем значение, на котором один из двух каналов ШИМ надо включить, вернее меньшее из двух значений. Ждем пока сработает прерывание по совпадению. В прерывании выставляем на соответствующую ногу "1" и в регистр сравнения пихаем значение второго канала ШИМ. Ждем пока опять сработает прерывание по переполнению. В прерывании выставляем "1" на ногу второго канала ШИМ. После этого спокойно ждем переполнения таймера, в котором все повторяется.

В принципе все просто, если понятна суть :)
Код:
//на какие ноги будем выводить ШИМ
#define portPWM1 PORTx1.y1
#define portPWM2 PORTx2.y2
#define portPWM3 PORTx3.y3
#define portPWM4 PORTx4.y4

#define high(x) (char)(x>>8)
#define low(x) (char)x

interrupt [TIM1_OVF] void timer1_ovf_isr(void) //переполнение таймера 1
{
   portPWM1=portPWM2=portPWM3=portPWM4=0; //выставляем на ноги "0"
   if(valuePWM1<valuePWM2) // ищем меньшее значение ШИМа
   {
      OCR1AH=high(valuePWM1); //если меньше в первом канале
      OCR1AL=low(valuePWM1); //записываем его с регистр сравнения
      valueNext1=valuePWM2; //запоминаем значение второго канала
      portNext1=2; //запоминаем, что на первом прерывании у нас должен включиться первый канал, а на втором - второй
   }
   else //иначе, если значение второго ШИМа меньше или равно первому
   {
      OCR1AH=high(valuePWM2); //выставляем его в регистр сравнения
      OCR1AL=low(valuePWM2);
      valueNext1=valuePWM1; //запоминаем значение первого канала ШИМ
      if(valuePWM1==valuePWM2)portNext1=0; //смотрим, если значения каналов равны - включать их одновременно
      else portNext1=1; //если не равны, сначала второй, потом первый
   }
}

interrupt [TIM1_COMPA] void timer1_compa_isr(void) //прерывание по совпадению
{
   OCR1AH=high(valueNext1); //записываем в регистр сравнение запомненное значение
   OCR1AL=low(valueNext1); //для следующего канала
   switch(portNext1) //смотрим где мы должны выставить "1"
   {
      0: portPWM1=portPWM2=1; break; //значения ШИМов были равны - зажигаем обе ноги
      1: portPWM2=1; break; //в переменной хранится значение ноги, которую надо зажечь
      2: portPWM1=1; break; //на втором прерывании, по-этому зажигаем другую.
   }
   portNext1=0; //ну собственно чтобы не париться говорим что значения ШИМа равны и при следующем прерывании включатся обе ноги. Не надо запоминать что мы включили в первый раз.
}

Код не проверял, вроде должно как-то работать :) Для двух других каналов все то же самое, только переменные другие.

_________________
Show


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Таймеры,PWM,прерывания
СообщениеДобавлено: 19 фев 2010, 22:40 
Супермодератор
Аватара пользователя

Зарегистрирован: 28 янв 2010, 05:47
Сообщения: 1027
Откуда: Винница
P.S.
На самом деле это все извращения. Для твоего применения можно сделать проще.
Допустим переменная x - счетчик. По переполнению таймера увеличиваем х на 1. Если х равно нужному значению ШИМа - выводим на нужную ногу 1. Когда х переполняется - выводим на нужную ногу 0.
Берется массив, каждый элемент которого - один канал ШИМ, и гоняется по этому алгоритму. Для управления вентиляторами самое то. Тем более можно задействовать любой таймер, а не обязательно таймер1, он все-таки 16-битный, может пригодица для чего-нибудь более интересного :)

_________________
Show


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Таймеры,PWM,прерывания
СообщениеДобавлено: 19 фев 2010, 23:35 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 26 янв 2010, 21:31
Сообщения: 33
Откуда: Днепропетровск
спасибо за подсказку.Буду разбираться.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Таймеры,PWM,прерывания
СообщениеДобавлено: 21 фев 2010, 11:42 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 26 янв 2010, 21:31
Сообщения: 33
Откуда: Днепропетровск
Попробовал так:


Код:
/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.9 Professional
Automatic Program Generator
© Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date    : 20.02.2010
Author  : F4CG                           
Company : F4CG                           
Comments:


Chip type           : ATmega32
Program type        : Application
Clock frequency     : 8,000000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 512
*****************************************************/

#include <mega32.h>
#include<delay.h>
unsigned char pwm_sel=0,pwm=0;

    unsigned char mass_pwm[]={0x00,0x00,0x00,0x00};
void init_port()
{
     PORTB=0x00;
     DDRB=0x1F;

     PORTC=0x00;
     DDRC=0x0F;

     PORTD=0x07;
     DDRD=0x00;
}
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{

pwm++;
  if(mass_pwm[0]<=pwm)
   {
    PORTB.0=0;
   }
  else
   {
    PORTB.0=1;
   }
  if(mass_pwm[1]<=pwm)
   {
    PORTB.1=0;
   }
  else
   {
    PORTB.1=1;
   }
  if(mass_pwm[2]<=pwm)
   {
    PORTB.2=0;
   }
  else
   {
    PORTB.2=1;
   }
  if(mass_pwm[3]<=pwm)
   {
    PORTB.3=0;
   }
  else
   {
    PORTB.3=1;
   }

  if(pwm==255)
   {
    pwm=0;
   }
}




void main(void)
{
 
init_port();


TCCR0=0x01;
TCNT0=0x00;
OCR0=0x00;
TIMSK=0x01;

#asm("sei")

while (1)
      {
   
       if(PIND.0==0)
        {
         delay_ms(50);
         if(PIND.0==0)
          {
            mass_pwm[pwm_sel]+=2;
          }
        }
       if(PIND.1==0)
        {
         delay_ms(50);
        if(PIND.1==0)
         {
          mass_pwm[pwm_sel]-=2;
         }
        }
       if(PIND.2==0)
        {
          delay_ms(100);
         if(PIND.2==0)
          {
           pwm_sel++;
          if(pwm_sel==5)
           {
            pwm_sel=0;
           }
          }
         }
     };
}



все работает вроде.

Изображение


Есть вопрос:на скрине видно что частота равна 122Гц.Так и должно быть?Или я таймер настроил неправильно?Или вообще идею не так понял?Срабатывание прерывания настраивал в мастере кодвижна на срабатывание каждую 1 мс.файлы проектов в код вижн и Протеус в аттаче.Вообщем помогайте пожалуйста.Во всех подобных устройствах найденными мною на просторах сети рабочая частота ШИМ более 12кГц.А тут 122 Гц.как то мало вроде.Или это протеус глючит?


Вложения:
pwm.rar [51.19 Кб]
Скачиваний: 182
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Таймеры,PWM,прерывания
СообщениеДобавлено: 22 фев 2010, 14:57 
Супермодератор
Аватара пользователя

Зарегистрирован: 28 янв 2010, 05:47
Сообщения: 1027
Откуда: Винница
Ну правильно, 8 МГц тактовая, 256 тиков до переполнения таймера, 256 градаций ШИМа: 8000000/256/256=122,0703125 Гц. Чтобы получить выше частоту надо уменьшать разрядность ШИМа и количество тиков до переполнения таймера. Вентиляторами оно управлять будет и на такой частоте, оно и на 24 Гц нормально управляло у меня на тини 15.
Вообще умные люди советуют брать частоту ШИМа 20КГц и выше, т.е. за пределами слышимого диапазона, но для такой частоты ШИМ должен быть аппаратным, программно такого не получишь. Так что смотри сам - или занимать все таймеры под аппаратный ШИМ (можно взять мк типа меги 48, там на каждый таймер по 2 канала ШИМ - один таймер свободный будет) или пробовать такой.

_________________
Show


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Таймеры,PWM,прерывания
СообщениеДобавлено: 22 фев 2010, 16:39 
Старожил
Аватара пользователя

Зарегистрирован: 27 янв 2010, 12:18
Сообщения: 1259
Откуда: Moscow
Только ШИМ, ИМХО, нужно переписать на двойную буферизацию - в таком виде он очень медленный - жрёт кучу времени в прерывании.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Таймеры,PWM,прерывания
СообщениеДобавлено: 22 фев 2010, 20:44 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 26 янв 2010, 21:31
Сообщения: 33
Откуда: Днепропетровск
Понятно.Буду копать в сторону Меги 48...Всем спасибо!


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 10 ] 


Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB