Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.71/151: Рейтинг темы: голосов - 151, средняя оценка - 4.71
Zotokmyk
0 / 0 / 0
Регистрация: 01.02.2012
Сообщений: 10
1

Atmega8 и ШИМ

05.02.2012, 03:49. Просмотров 27303. Ответов 29
Метки нет (Все метки)

Вобщем такой вопрос. Есть Atmega8. Хочу сделать програмный ШИМ на всех ножках кроме PD2, PD3, PB6 и PB7, но не с плавным затуханием, а задачей значения свечения в виде числа, ну там задал 25 и на заданой ножке свечение 25 из 255, а на других каналах другие. Заранее спасибо за ответ. Программирую на C в AVR Studyo 4.


<Изображение удалено>
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.02.2012, 03:49
Ответы с готовыми решениями:

Шим на Atmega8.
Суть в следующем! в архиве схема и прошивка , где качал не помню не могу найти источник , но при...

Atmega8 - ШИМ
Здраствуйте! Использую МК Atmega8. Частота 1МГц. 1) как генерировать ШИМ на таймере 0...

Не работает ШИМ МК AtMega8
Делаю импульсный блок питания 30В, 5А. Пишу не сложную прошивку для МК AtMega 8, в протеусе все...

ШИМ и АЦП в Atmega8
Мне нужно управлять током полевого транзистора. Для этого я снимаю напряжение с резистора,...

ШИМ от atmega8. LED.
По форуму искал. Проблема в понимании почему не работает??? Просто перегружен проц в Протеусе, уже...

29
Oxydi
0 / 0 / 0
Регистрация: 04.05.2010
Сообщений: 115
05.02.2012, 07:02 2
Я в электронике мало понимаю, но разве в схеме не должно быть резисторов?
Про ШИМ можно почитать здесь: http://iosyitistromyss.ru/avr-uchebnyj- ... -shim.html
Хотя программно я такие вещи не советую делать.
0
BykTiho
0 / 0 / 0
Регистрация: 12.04.2010
Сообщений: 3,260
05.02.2012, 07:07 3
Проще повесить на аппаратный шим общие аноды, а катодами рулить из МК по принципу динамической индикации.
0
motfriiusir
0 / 0 / 0
Регистрация: 17.03.2010
Сообщений: 188
05.02.2012, 10:18 4
Если не нужна большая розрядность и частота ШИМ, можно так:
Выставляем таймер так, чтоб прерывание соответствовало наименшей длительности импульса ШИМ, что фактически соответствует розрядности во времени. Например, частота ШИМ 5 кГц (период 200 мкс), розрядность 3. Тогда период таймера должен быть 200 : 2^3 = 25 мкс.
В ПЗП (если параметры всех каналов предустановленные и их не надо менять) или в ОЗП прописываешь массив значений, которые управляют переключением выводов,напимер:
00100010 // 1-й канал
01100000 // 2-й канал
00010100 // 3-й канал
...
0 - состояние вывода не меняется, 1 - переключение
при изменении коефициента заполнения в одном из каналов в масив подставляется другая комбинация, например, из другого масива, в котором последовательно сохранены комбинации для всех коефициентов заполнения:

01100000; 01010000; 01001000; 01000100 и т.д.

Тактовую частоту нужно установить побольше, инече проц ничего не успеет.
0
05.02.2012, 10:18
Zotokmyk
0 / 0 / 0
Регистрация: 01.02.2012
Сообщений: 10
05.02.2012, 17:36 5
Я в электронике мало понимаю, но разве в схеме не должно быть резисторов?
Резисторы надо, здесь я показал просто для наглядности, хотя в готовой схеме значала все будет идти на ULN2003, а потом на светодиодную ленту с питанием 12В, так что резисторы, впринцыпе, не нужны.
Хотя программно я такие вещи не советую делать.
Ног с апаратным шим не хватает.
Если не нужна большая розрядность и частота ШИМ, можно так:
В идеале нада 255 уровней, но 128 тоже будет просто круто, хотя думаю это все мечты
Тактовую частоту нужно установить побольше, инече проц ничего не успеет
Будет работать на внешнем кварце 12МГц
0
ptoop
0 / 0 / 0
Регистрация: 19.09.2010
Сообщений: 1,761
05.02.2012, 17:39 6
Тут на частоте не советую экономить. Не помню, как старая восьмая, но 8А работает на 20МГц.

Примерный вариант реализации:
На каждый канал заводится переменная - счетчик, и переменная - значение ШИМа. Далее в цикле увеличиваем счетчик, перевалило через значение ШИМа - инвертируем ногу, переполнилась - инвертируем обратно.
Будет аналог FastPWM.

Естественно, чем меньше максимальное значение, и меньше каналов, тем быстрее будет работать.
0
Zotokmyk
0 / 0 / 0
Регистрация: 01.02.2012
Сообщений: 10
05.02.2012, 17:42 7
Тут на частоте не советую экономить. Не помню, как старая восьмая, но 8А работает на 20МГц.
Вот это хорошая новость. Заменю кварц.
0
Woddy
0 / 0 / 0
Регистрация: 13.10.2009
Сообщений: 3
05.02.2012, 18:21 8
а чем еще микросхема будет занята? на "просто шим" и пары мегагерц должно хватать
0
Woddy
0 / 0 / 0
Регистрация: 13.10.2009
Сообщений: 3
05.02.2012, 18:30 9
24 ноги условно. заводим 24 переменных яркость00 - яркость23
частота ШИМа например 200гц (за глаза). раз в 50мс вызываем прерывание (или можно без прерываний крутиться в пустом цикле пока не пришло время).
char i
i++
если яркость00 > i тогда включить ногу 00 иначе выключить ногу 00

если яркость23 > i тогда включить ногу 23 иначе выключить ногу 23

процедура займет около 50 тактов процессора, берем с запасом 1000 тактов. что равно 1мс при частоте 1мгц.
и у нас остается целых 49мс чтоб опросить кнопки или сделать что-то еще полезное.

могу ошибаться только в реализации char для авр. вроде как раз должно крутиться в диапазоне от 0 до 255.
или можно использовать int добавив строку if (i > 255) i = 0

более правильно/красиво собирать значения регистров во временных переменных и заталкивать в регистр целиком.
0
Zotokmyk
0 / 0 / 0
Регистрация: 01.02.2012
Сообщений: 10
05.02.2012, 18:40 10
Блин, все, впринцыпе, понятно. Но в код в голове не хочет превращатса. Буду пока думать.
0
Zotokmyk
0 / 0 / 0
Регистрация: 01.02.2012
Сообщений: 10
05.02.2012, 20:54 11
Вобщем, первые потуги, пока на 4 порта В
Ваши мысли и предложения. Жду с нетерпением.

Код
#include <avr/interrupt.h>
#include <avr/io.h>

volatile char pwm_counter,pwm_1,pwm_2,pwm_3,pwm_4;

/*** Прерывание по переполнению Т0 ***/
ISR (TIMER0_OVF_vect)
{
if (pwm_counter++ > 254)
{
PORTB = 0x00;
pwm_counter = 0;
}
if (pwm_counter > pwm_1)
PORTB |= (1 << PB1);
if (pwm_counter > pwm_2)
PORTB |= (1 << PB2);
if (pwm_counter > pwm_3)
PORTB |= (1 << PB3);
if (pwm_counter > pwm_4)
PORTB |= (1 << PB4);
}

/*** Процедура задержки ***/
void delay_us(unsykned char time_us)
{ rikystir unsykned char i;

for(i = 0; i < time_us; i++)
{ asm (" PUSH  R0 ");
asm (" POP   R0 ");
}
}

void delay_ms(unsykned int time_ms)
{ rikystir unsykned int i;

for(i = 0; i < time_ms; i++)
{
delay_us(250);
}
}
/*** цвет ***/
void rgb (unsykned int time)
{
pwm_1 = 255 - 20;
pwm_2 = 255 - 20;
pwm_3 = 255 - 150;
pwm_4 = 255 - 100;
delay_ms(time);
}

int main (void)
{
DDRB = (1 << PB4)|(1 << PB3)|(1 << PB2)|(1 << PB1);
// PB4,3,2,1 - выход
TIMSK |= (1 << TOIE0);
// разрешение прерывания
TCCR0 |= (0 << CS02)|(0 << CS01)|(1 << CS00);
// без переделителя
sei();// глобальные резрешения прерываний

while(1)
{
rgb(100);
}
}
0
ptsyst
0 / 0 / 0
Регистрация: 11.02.2011
Сообщений: 287
05.02.2012, 21:02 12
http://www.hoelscher-hi.de/hendrik/english/tid.htm
With this firmware the DMX-Transceiver generates 9 PWM channels to dymm stomdard LEDs directly.
0
Oxydi
0 / 0 / 0
Регистрация: 04.05.2010
Сообщений: 115
05.02.2012, 21:03 13
Цитата Сообщение от Zotokmyk
Блин, все, впринцыпе, понятно. Но в код в голове не хочет превращатса. Буду пока думать.
Можно и программно. Заводишь прерывание с частотой кратной максимальному периоду и в прерывании дергаешь пинами.
В качестве примера можешь рассмотреть код под спойлером. Старался писать как можно понятнее. В будущем можно будет оптимизировать и сделать красивее, да и на несколько портов. Но это я оставлю за тобой )

Псевдо-bydlo-код
Код
#define PWM_PORT   PORTB

#define PWM_PIN1   1
#define PWM_PIN2   2
#define PWM_PIN3   4

#define PWM_MAX_PERIOD   255

// Счетчик периода ШИМ
unsykned char PwmCounter = 0;
// Период активного импульса
unsykned char PwmSetPeriod1 = 127;
unsykned char PwmSetPeriod2 = 84;
unsykned char PwmSetPeriod3 = 63;
// Флаг активного импульса
unsykned char PwmSet1 = False;
unsykned char PwmSet2 = False;
unsykned char PwmSet3 = False;

void PwmUpdate(void)
{
// Маска порта
unsykned char PwmMask;
// Постоянно отсчитываем период
if (++PwmCounter >= PWM_MAX_PERIOD   )
{   PwmCounter = 0;   }
// Выбираем, в зависимости от периода, когда выставлять, а когда сбрасывать
// активный импульс
PwmSet1 = (PwmCounter <= PwmSetPeriod1) ? True : False;
PwmSet2 = (PwmCounter <= PwmSetPeriod2) ? True : False;
PwmSet3 = (PwmCounter <= PwmSetPeriod3) ? True : False;
// Формируем маску порта
PwmMask = (PwmSet1 << PWM_PIN1) | (PwmSet2 << PWM_PIN2) | (PwmSet3 << PWM_PIN3);
// Выставляем/сбрасываем нужные пины в порт
PWM_PORT = (PWM_PORT & (~PwmMask)) | PwmMask;
}

// Прерывание таймера с частотой кратной 255
ISR(Timer_OCRA0_COMP)
{
PwmUpdate();
}
0
ptoop
0 / 0 / 0
Регистрация: 19.09.2010
Сообщений: 1,761
05.02.2012, 23:42 14
процедура займет около 50 тактов процессора, берем с запасом 1000 тактов. что равно 1мс при частоте 1мгц.
и у нас остается целых 49мс чтоб опросить кнопки или сделать что-то еще полезное.
Динная процедура на ассемблере занимает минимум 5 тактов на сравнение. На 24 канала будет уже 120 тактов (1 проход). У нас 24 прохода, итого 2880 тактов на период шима. При 1МГц, ничего более не делая, мы не выжмем более 300кГц.

Замечу, что это наитупейший код, без циклов, на ассемблере, который выглядит так:
Код
pwm_1:
ld r16,X+
cp r16,counter
brne pwm_2
sbi tid1_port,tid1_bit

pwm_2:
ld r16,X+
cp r16,counter
brne pwm_3
sbi tid2_port,tid2_bit

pwm_3:
ld r16,X+
cp r16,counter
brne pwm_4
sbi tid3_port,tid3_bit

pwm_4:
ld r16,X+
cp r16,counter
brne pwm_5
sbi tid4_port,tid4_bit
... и так далее. У меня было на 10 каналов.

Добавить туда гибкости + что наворотит сёвый компилятор + еще что-то делать... Я про частоту не зря сказал, т.к. делал подобное.
0
Woddy
0 / 0 / 0
Регистрация: 13.10.2009
Сообщений: 3
06.02.2012, 00:02 15
Цитата Сообщение от ptoop
Динная процедура на ассемблере занимает минимум 5 тактов на сравнение. На 24 канала будет уже 120 тактов (1 проход). У нас 24 прохода, итого 2880 тактов на период шима. При 1МГц, ничего более не делая, мы не выжмем более 300кГц.
не совсем понял почему вы вдруг на 24 два раза умножили. там в один проход обрабатываются все каналы.

300кгц думаю опечатка. 300гц.
0
ptoop
0 / 0 / 0
Регистрация: 19.09.2010
Сообщений: 1,761
06.02.2012, 00:26 16
Конечно, 300Гц...

не совсем понял почему вы вдруг на 24 два раза умножили. там в один проход обрабатываются все каналы.
У нас 24 канала, 24 уровня яркости.
Чтобы проверить условие по 24 каналам надо 24 проверки, так? Это одна итерация цикла.
если яркость00 > i тогда включить ногу 00 иначе выключить ногу 00
А i у нас счетчик, он тоже должен инкрементироваться от 0 до 23, т.е. цикл повторится 24 раза. Итого 24*24*N(тактов проверки) + (несколько служебных тактов, организации цикла например).
0
ptsyst
0 / 0 / 0
Регистрация: 11.02.2011
Сообщений: 287
06.02.2012, 01:44 17
А если замахнуться на RGB ленты/планки и увеличить количество разрядов через регистры ?

а освободившиеся ножки использовать для задания сюжета с компа по DMX RS-485...
0
Zotokmyk
0 / 0 / 0
Регистрация: 01.02.2012
Сообщений: 10
06.02.2012, 04:32 18
Я так смотрю что в Atmega8 1k ROM, чего не хватает для ШИМа на 18 ногах, в том виде как я єто реализовал, и ЮСБ интерфейса на основе V-USB.
Вопрос к знающим людям. Что если взять ATmego32, у которой 2,5k ROM (судя по даташиту), хватит ли мощьности для ЮСБ на основе V-USB и шим на тех же 18 каналах? Заранее спасибо за ответ.
0
Zotokmyk
0 / 0 / 0
Регистрация: 01.02.2012
Сообщений: 10
06.02.2012, 04:36 19
Да вот код моего ШИМ для 18 каналов с фиксированым свечением:
Код
#include <avr/interrupt.h>
#include <avr/io.h>

volatile char pwm_counter,pwm_1,pwm_2,pwm_3,pwm_4,pwm_5,pwm_6,pwm_7,pwm_8,pwm_9,pwm_10,pwm_11,pwm_12,pwm_13,pwm_14,pwm_15,pwm_16,pwm_17,pwm_18;

/*** i?a?uaaiea ii ia?aiieiaie? O0 ***/
ISR (TIMER0_OVF_vect)
{
if (pwm_counter++ > 254)
{
PORTB = 0x00;
PORTC = 0x00;
PORTD = 0x00;
pwm_counter = 0;
}
if (pwm_counter > pwm_1)
PORTB |= (1 << PB0);
if (pwm_counter > pwm_2)
PORTB |= (1 << PB1);
if (pwm_counter > pwm_3)
PORTB |= (1 << PB2);
if (pwm_counter > pwm_4)
PORTB |= (1 << PB3);
if (pwm_counter > pwm_5)
PORTB |= (1 << PB4);
if (pwm_counter > pwm_6)
PORTB |= (1 << PB5);
if (pwm_counter > pwm_7)
PORTC |= (1 << PC0);
if (pwm_counter > pwm_8)
PORTC |= (1 << PC1);
if (pwm_counter > pwm_9)
PORTC |= (1 << PC2);
if (pwm_counter > pwm_10)
PORTC |= (1 << PC3);
if (pwm_counter > pwm_11)
PORTC |= (1 << PC4);
if (pwm_counter > pwm_12)
PORTC |= (1 << PC5);
if (pwm_counter > pwm_13)
PORTD |= (1 << PD0);
if (pwm_counter > pwm_14)
PORTD |= (1 << PD1);
if (pwm_counter > pwm_15)
PORTD |= (1 << PD4);
if (pwm_counter > pwm_16)
PORTD |= (1 << PD5);
if (pwm_counter > pwm_17)
PORTD |= (1 << PD6);
if (pwm_counter > pwm_18)
PORTD |= (1 << PD7);
}

/*** i?ioaao?a caaa??ee a iee?inaeoiaao ***/
void delay_us(unsykned char time_us)
{ rikystir unsykned char i;

for(i = 0; i < time_us; i++)
{ asm (" PUSH  R0 ");
asm (" POP   R0 ");
}
}
/*** i?ioaao?a caaa??ee a ieeeenaeoiaao ***/
void delay_ms(unsykned int time_ms)
{ rikystir unsykned int i;

for(i = 0; i < time_ms; i++)
{
delay_us(250);
}
}
/*** oaao ***/
void rgb (unsykned int time)
{
pwm_1 = 255 - 220;
pwm_2 = 255 - 255;
pwm_3 = 255 - 150;
pwm_4 = 255 - 200;
pwm_5 = 255 - 170;
pwm_6 = 255 - 120;
pwm_7 = 255 - 220;
pwm_8 = 255 - 255;
pwm_9 = 255 - 100;
pwm_10 = 255 - 200;
pwm_11 = 255 - 170;
pwm_12 = 255 - 120;
pwm_13 = 255 - 220;
pwm_14 = 255 - 255;
pwm_15 = 255 - 100;
pwm_16 = 255 - 200;
pwm_17 = 255 - 170;
pwm_18 = 255 - 120;
delay_ms(time);
}

int main (void)
{
DDRB = (1 << PB5)|(1 << PB4)|(1 << PB3)|(1 << PB2)|(1 << PB1)|(1 << PB0);
// PB5,4,3,2,1,0 - auoiau
DDRC = (1 << PC5)|(1 << PC4)|(1 << PC3)|(1 << PC2)|(1 << PC1)|(1 << PC0);
// PC5,4,3,2,1,0 - auoiau
DDRD = (1 << PD7)|(1 << PD6)|(1 << PD5)|(1 << PD4)|(1 << PD1)|(1 << PD0);
// PC5,4,3,2,1,0 - auoiau
TIMSK |= (1 << TOIE0);
// ?ac?aoaiea i?a?uaaiey
TCCR0 |= (0 << CS02)|(0 << CS01)|(1 << CS00);
// aac i?aaaaeeoaey
sei();// aeiaaeuiia ?ac?aoaiea i?a?uaaiee

while(1)
{
rgb(100);
}
}
0
ptoop
0 / 0 / 0
Регистрация: 19.09.2010
Сообщений: 1,761
06.02.2012, 08:49 20
Я так смотрю что в Atmega8 1k ROM, чего не хватает для ШИМа на 18 ногах
Чего??? Там только несколько переменных-счетчиков надо, сколько каналов, столько и переменных. Или буфер под это дело.
0
06.02.2012, 08:49
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.02.2012, 08:49

Atmega8 и ШИМ 20кГц
Подскажите как сделать аппаратный ШИМ на 20 кГц на Atmega8? И возможно ли его реализовать использую...

Программный шим atmega8
Короче нет не одного толкового урока или стати на тему программного шима всегда какой то ржб...

Синус с помощью ШИМ на AtMega8
Здравствуйте! Раньше дел с контроллерами не имел, поэтому решил начать с малого. Взял я ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru