Программый ШИМ. Вот хоть убейте не понимаю.

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18675
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Сообщение ARV »

вот вам код программного ШИМ без использования прерываний (что с моей точки зрения - не гуд):

Код: Выделить всё

static void delay(unsigned char d){
// задержка в d микросекунд
   for(; d; d--) delay_us(1);
}

int main(void){
   unsigned char PWM; // коэффициент заполнения ШИМ (от 1 до 254)
   unsigned int counter;

   DDRD = 1; // ШИМить будем на 0 бите порта D

   while(1)
      for(PWM = 1; PWM < 255; PWM++){
         for(counter = 0; counter < 1000; counter++){
            PORTD |= 1;
            delay(255-PWM);
            PORTD &= ~1;
            delay(PWM);
         }
      }
}
светодиод на указанном порту должен плавно разгораться, потом на максимуме яркости тухнуть мгновенно и снова разгораться. разгорание должно занять чуть больше минуты, т.е. оно очень плавное :)
надеюсь, чем регулировать скорость разгорания - разберетесь?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Реклама
Аватара пользователя
poligon
Нашел транзистор. Понюхал.
Сообщения: 160
Зарегистрирован: Вс июн 21, 2009 15:44:57

Сообщение poligon »

Спасибо всем, сейчас попробую
Реклама
Аватара пользователя
mr_smit
Вымогатель припоя
Сообщения: 651
Зарегистрирован: Пн мар 23, 2009 09:25:58
Откуда: Самара

Сообщение mr_smit »

А как аппаратный шим в ATTiny45 использовать?
Нельзя всё знать, достаточно понимать.
Аватара пользователя
stolyars
Родился
Сообщения: 18
Зарегистрирован: Пн сен 21, 2009 10:12:35
Откуда: Днепр

Сообщение stolyars »

Вопрос:нужно 4 канала програмного ШИМ.Частота ШИМ 25-30 кГц.Контроллер Атмега32(8мГц).Я так понял можна на одном таймере сделать?Можно пример кода если можно или пример настройки таймера?Подскажите если не трудно.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Esya
Встал на лапы
Сообщения: 133
Зарегистрирован: Ср фев 20, 2008 03:09:21
Откуда: Украина г.Харьков
Контактная информация:

Сообщение Esya »

вот посмотри здесь http://easyelectronics.ru/avr-uchebnyj- ... -shim.html только на мегу8 апаратный, там есть описание как програмный сделать сам делал 3 канала
Русский человек читает инструкцию тогда, когда точно понял, что поломал.
Реклама
Аватара пользователя
stolyars
Родился
Сообщения: 18
Зарегистрирован: Пн сен 21, 2009 10:12:35
Откуда: Днепр

Сообщение stolyars »

Я читал там.Но все равно не совсем понял как реализовать програмный ШИМ.Буду безмерно благодарен если кто нибудь выложит пример кода на С(а если для Код Вижн вообще супер),заранее спасибо.
Реклама
Аватара пользователя
Esya
Встал на лапы
Сообщения: 133
Зарегистрирован: Ср фев 20, 2008 03:09:21
Откуда: Украина г.Харьков
Контактная информация:

Сообщение Esya »

заводиш таймер на прерывание по переполнению и на сравнение, в регистр для сравнения записуеш число оно и будет определять скважность по прерыванию сравнения обнуляеш какой либо пин а по переполнению выставляеш в 1 , вот и все.
Русский человек читает инструкцию тогда, когда точно понял, что поломал.
Аватара пользователя
andrey_artemov
Встал на лапы
Сообщения: 136
Зарегистрирован: Сб авг 15, 2009 21:26:50
Откуда: Пенза
Контактная информация:

Сообщение andrey_artemov »

Я реализовал на Atmega8 в прерывании таймера 8 канальный программный шим, 0-255 на каждый канал - всё работает в железе и протеусе !!!

У RGB светодиода изменение яркости на 1 единицу на глаз не заметно...

В глобальном массиве shimm_value - хранятся значения ШИМ для каждого канала....

Как раз пример на CodeVision

Код: Выделить всё


#define On            0   // Включено
#define Off           1   // Выключено

#define True          1  // Истина
#define False         0  // Ложь

#define VuhodShimm1   PORTD.0   // Выход ШИМ
#define VuhodShimm2   PORTD.1   // Выход ШИМ
#define VuhodShimm3   PORTD.2   // Выход ШИМ
#define VuhodShimm4   PORTD.3   // Выход ШИМ
#define VuhodShimm5   PORTD.4   // Выход ШИМ
#define VuhodShimm6   PORTD.5   // Выход ШИМ
#define VuhodShimm7   PORTD.6   // Выход ШИМ
#define VuhodShimm8   PORTD.7   // Выход ШИМ

unsigned char shimm_value[8];       // текущее значение шима 0 - 255 на каждый канал 
unsigned char shimm_counter = 0;   // счетчик шима


.....
.....
.....
.....

// Timer 0 overflow interrupt service routine   
// Обработчик прерывания....
interrupt [TIM0_OVF] void timer0_ovf_isr(void) {
// Reinitialize Timer 0 value
TCNT0=0xFE;

 // Реализация программного шима 
   // если счетчик шим больше значение шим то в порт пишем On иначе в порт пишем Off
   // --------------------------------------------------------------------------------//
                                                              
   if(shimm_counter >= shimm_value[0]) {
     VuhodShimm1 = On;
   } else {
     VuhodShimm1 = Off;
   } // if

   if(shimm_counter >= shimm_value[1]) {
     VuhodShimm2 = On;
   } else {
     VuhodShimm2 = Off;
   } // if
   
   if(shimm_counter >= shimm_value[2]) {
     VuhodShimm3 = On;
   } else {
     VuhodShimm3 = Off;
   } // if
   
   if(shimm_counter >= shimm_value[3]) {
     VuhodShimm4 = On;
   } else {
     VuhodShimm4 = Off;
   } // if
   
   if(shimm_counter >= shimm_value[4]) {
     VuhodShimm5 = On;
   } else {
     VuhodShimm5 = Off;
   } // if
   
   if(shimm_counter >= shimm_value[5]) {
     VuhodShimm6 = On;
   } else {
     VuhodShimm6 = Off;
   } // if

   if(shimm_counter >= shimm_value[6]) {
     VuhodShimm7 = On;
   } else {
     VuhodShimm7 = Off;
   } // if

   if(shimm_counter >= shimm_value[7]) {
     VuhodShimm8 = On;
   } else {
     VuhodShimm8 = Off;
   } // if
   

    
   // Прибавим к счётчику единицу
   shimm_counter ++;
   
  // Проверяем, достиг ли счетчик предельного значения, если да, то обнуляем
  if(shimm_counter == 255)  shimm_counter = 0;        

 
}  //   timer0_ovf_isr
Аватара пользователя
stolyars
Родился
Сообщения: 18
Зарегистрирован: Пн сен 21, 2009 10:12:35
Откуда: Днепр

Сообщение stolyars »

andrey_artemov,можно настройку таймера для Вашего кода?Сама идея програмного Шима мне понятна,но что то больше чем 122 Гц у меня частота не получается.А у Вас 8 каналов на какой частоте работают?
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18675
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Сообщение ARV »

в последнем приведенном примере есть одно слабое место: фазы импульсов по каналам будут плавать друг относительно друга. ненамного, конечно, но будут. если такой джиттер не желателен, то лучше завести локальную переменную в обработчике прерываний, ставить в ней биты в зависимости от состояния каналов, а потом сразу эту переменную выводить в порт - тогда ВСЕ каналы будут менять свои уровни синхронно

частота ШИМ определяется по формуле (приблизительно): Fpwm = Ftovf / (Dmax+1), где Ftovf - частота прерываний таймера, а Dmax - максимальное значение счетчика для канала ШИМ. Пример: 8-битный таймер тактируется от 8 МГц без предделителя, прерывание по переполнению, Dmax=255 (1 байт), значит:
Ftovf = 8000000 / 256 = 31250 Гц
Fpwm = 31250 / 256 = 122 Гц

От числа каналов частота ШИМ практически не зависит, но следует учесть, что сам по себе обработчик прерываний отнимает некоторое количество тактов, поэтому просто сокращая Dmax (т.е. уменьшая число градаций ШИМ) все равно нельзя добиться частоты выше некоторого пределного значения, которое зависит от того, насколько оптимальный код обработчика прерывания генерирует компилятор.

не забывайте, что можно "подстроить" частоту встроенного RC-генератора МК и добиться почти удвоения его рабочей частоты - это варинт поднять частоту ШИМ без снижения Dmax
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
urry
Сверлит текстолит когтями
Сообщения: 1262
Зарегистрирован: Пн дек 08, 2008 10:58:48
Откуда: Винница
Контактная информация:

Сообщение urry »

andrey_artemov, это решение "в лоб", отнимающее уйму процессорного времени. Всякого рода световые табло строятся на другом принципе - массив, предназначенный для вывода, разворачивается на 90 градусов. Градацию в 256 уровней получают по всего 8 срабатываниям таймера - 1 срабатывание получают, анализируя старшие разрябы массива и выводят в порт. Второе срабатывание будет через половину периода шим, выводятся разряды массива д6, затем через 3/4 периода - д5 и так далее.
Попробуйте , Вам понравится. :)
Вот мой вариант с пиком, читать, начиная со слов
у меня "текст немножечко по дебильному написан" (С) Добкин.
http://www.remexpert.com/ipb/topic3875s20.html?start=20
Полный текст проги - я делал вращение входного массива во время между выдачей д6 и д5, а время между д7 и д6 отдавал другим задачам, если интересно, поищу.
Аватара пользователя
andrey_artemov
Встал на лапы
Сообщения: 136
Зарегистрирован: Сб авг 15, 2009 21:26:50
Откуда: Пенза
Контактная информация:

Сообщение andrey_artemov »

Уважаемый ARV, просто у меня совпало, что всё выводится в один порт С, но до этого выводились в разные порты - по 2 бита, и поэтому каждый бит пишется отдельно, конечно я согласен, что в данном случае нужно писать в порт сразу один байт соответственно одной командой записи....

urry очень красивое у Вас решение - попробую сделать как у Вас.

stolyars Процессор настроен на внутренний генератор 8 MHZ
Инициализация таймера

Код: Выделить всё


// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
TCCR0=0x03;
TCNT0=0xFE;
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»