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

 
 
> Atmega48 6 ШИМ
kennykiller
сообщение May 3 2012, 07:29
Сообщение #1





Группа: Участник
Сообщений: 10
Регистрация: 9-02-11
Пользователь №: 62 817



В даташшите на МК Atmega48 написано что у него есть 6 ШИМ.
Написал программу для плавного зажигания светодиодов.

вот основной кусок

Код
void pause (unsigned int a)
{
unsigned int i;
for (i=a;i>0;i--);
}

void init_pwm (void)
{

DDRB=0b1110;
DDRD=0b1100000;


TCCR1A=(1<<COM1A1)|(1<<COM1B1)|(1<<WGM10);
TCCR1B=(1<<CS10)|(0<<CS11)|(0<<CS12);

TCCR0A=(1<<COM0A1)|(1<<COM0B1)|(1<<WGM00);
TCCR0B=(1<<CS00)|(0<<CS01)|(0<<CS02);

OCR1A=0x00; //PB1
OCR1B=0x00; //PB2

OCR0A=0x00; //PD6
OCR0B=0x00; //PD5

}


Соответственно получаем 4 ШИМ на выходах PB1, PB2, PD6 и PD5.
Просьба знающих людей ответить на следующие вопросы:

1. Как получить еще 2 ШИМ? Пробовал через TCCR2A и TCCR2B как написано в даташите не получатся, и на каких вообще выходах должны быть эти 2 ШИМа?

2. Почему на выходах PB1 и PB2 напряжение плавно нарастает с 0 до 5 В и остается на 5 В, а на выходах PD6 и PD5 плавно нарастает с 0 до 5 В затем скачком сбрасывается до 0 и снова плавно нарастает. Разве они не должны одинаково работать?


Спасибо огромное за помощь.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Сергей Борщ
сообщение May 3 2012, 08:06
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (kennykiller @ May 3 2012, 10:29) *
вот основной кусок
Из этого куска не видно, где и что вы пишете в регистры OCR.
QUOTE (kennykiller @ May 3 2012, 10:29) *
1. Как получить еще 2 ШИМ? Пробовал через TCCR2A и TCCR2B как написано в даташите не получатся, и на каких вообще выходах должны быть эти 2 ШИМа?
Согласно документации - на выводах PB3 и PD3.
QUOTE (kennykiller @ May 3 2012, 10:29) *
2. Почему на выходах PB1 и PB2 напряжение плавно нарастает с 0 до 5 В и остается на 5 В, а на выходах PD6 и PD5 плавно нарастает с 0 до 5 В затем скачком сбрасывается до 0 и снова плавно нарастает. Разве они не должны одинаково работать?
Кода не видно, вероятно вы наращиваете переменную типа int и не учитываете, что OCR1A, OCR1B - 16-битные регистры, а OCR0A, OCR0B, OCR2A, OCR2B - 8-битные, и в них попадает лишь младший байт. Пишите в OCR1AL, OCR1BL - получите одинаковое поведение.

P.S. ваша функция pause() перестанет работать как только вы включите оптимизацию. Либо добавьте к параметру a квалификатор volatile, либо используйте функции _delay_ms(), _delay_us() из <util/delay.h> если ваш компилятор - avr-gcc, либо __delay_cycles() из <intrinsics.h>, если ваш компилятор - ИАР.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
kennykiller
сообщение May 4 2012, 06:38
Сообщение #3





Группа: Участник
Сообщений: 10
Регистрация: 9-02-11
Пользователь №: 62 817



Спасибо огромнейшее, с обоими вопросами разобрался.
А теперь насчет:
Цитата(Сергей Борщ @ May 3 2012, 12:06) *
P.S. ваша функция pause() перестанет работать как только вы включите оптимизацию. Либо добавьте к параметру a квалификатор volatile, либо используйте функции _delay_ms(), _delay_us() из <util/delay.h> если ваш компилятор - avr-gcc, либо __delay_cycles() из <intrinsics.h>, если ваш компилятор - ИАР.

компилятор avr-gcc, насчет использования функций _delay_ms(), _delay_us() ясно, а вот насчет добавления volatile можно по подробнее, я просто совсем новичок в Си и в программировании, если не сложно киньте пример кода или напишите что в указанном выше исправить. Заранее спасибо.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 4 2012, 10:05
Сообщение #4


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (kennykiller @ May 4 2012, 09:38) *
если не сложно киньте пример кода или напишите что в указанном выше исправить.
Добавлю к вышесказанному, так сказать, объяснение на пальцах. Ваш код задержки с точки зрения компилятора делает только одно - он делает маленькую быструю программу большой и медленной. Но ведь мы же все хотим, чтобы программы не тормозили, влезали на одну дискетку и работали как можно быстрее? Поэтому компилятор очень старается сделать получаемый из вашего исходника код как можно более быстрым и компактным. А этот ваш кусочек кода, получается, пытается сделать хорошую программу плохой! Ваш случай, конечно, самый вырожденный, но представьте такой код: UBRRL = F_CPU / BAUDRATE / 16; Вы просите компилятор сделать деление в вашей программе. Если обе константы F_CPU и BAUDRATE известны компилятору - он может вставить в вашу программу сразу результат деления и программа не будет тратить на это деление время. Она станет быстрее и короче. И ведь вы в самом деле хотите, чтобы в этом месте в программе был результат, а не процесс деления. Компилятор не обладает телепатией и не может решить, в каких местах программы вы хотите все быстро, а в каких вы хотите ее замедлить намеренно. Поэтому он делает программу как можно более быстрой (и короткой) везде. И везде его действия совпадают с вашими желаниями, кроме случая с задержкой. И чтобы обмануть его в случае с задержкой, надо объявить переменную цикла с квалификатором volatile, который говорит компилятору "делай с этой переменной все так, как написано, даже если ты знаешь, какой результат в конце концов окажется в этой переменной".
CODE
void pause (unsigned int a)
{
    volatile unsigned int i;
    for (i=a;i>0;i--)
     ;
}
// или более коротко:
void pause1 (volatile unsigned int a)
{
    for (;a>0;a--)
     ;
}

Т.е. мы указываем ему, что мы действительно хотим чтобы он в эту переменную i записал a, а потом вычитал по единице пока не получится 0. Хотя очевидно, что в конце вычитаний i будет содержать 0. Более того, i не используется, поэтому и ноль-то в ней никому не нужен.
Эта функция pause обладает только одним недостатком - время ее работы будет зависеть от уровня оптимизации и версии компилятора. Библиотечные функции _delay_xx() написаны на инлайн-ассемблере (а в новых версиях вшиты во внутренности компилятора) и их время выполнения не зависит он настроек компилятора.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 30th July 2025 - 05:37
Рейтинг@Mail.ru


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