Подскажите по ШИМ
Подскажите по ШИМ
Подскажите как плавно включить а через 10 секунд плавно выключить все светодиоды на порту PORTD.
Сейчас включаю поочередно
void led_on(unsigned int mask){
unsigned char on_time;
for (on_time = 1; on_time < 100; on_time++) {
PORTC &= ~mask; // выключаем светодиод
delay(100-on_time); // отсчитываем время в выключенном состоянии
PORTC |= mask; // включаем светодиод
delay(on_time); // отсчитываем время во включенном состоянии
}
for (mask = 0x01; mask; mask <<= 1)
{
led_on(mask);
delay_ms(100);
}
как переделать под плавное включение всего порта сразу
Сейчас включаю поочередно
void led_on(unsigned int mask){
unsigned char on_time;
for (on_time = 1; on_time < 100; on_time++) {
PORTC &= ~mask; // выключаем светодиод
delay(100-on_time); // отсчитываем время в выключенном состоянии
PORTC |= mask; // включаем светодиод
delay(on_time); // отсчитываем время во включенном состоянии
}
for (mask = 0x01; mask; mask <<= 1)
{
led_on(mask);
delay_ms(100);
}
как переделать под плавное включение всего порта сразу
- Реклама
-
Serhio
- Прорезались зубы
- Сообщения: 249
- Зарегистрирован: Вс авг 15, 2010 20:42:44
- Откуда: Тюмень
- Контактная информация:
Re: Подскажите по ШИМ
Извините, но решил написать здесь. Может есть у кого-нибудь код на асме для Мега8 ШИМ плавное зажигание светодиода? или подскажите пожалуйста алгоритм, чтобы я мог сравнить со своими додумками 
Re: Подскажите по ШИМ
Включить все светодиоды к одной ноге с аппаратной ШИМ через транзистор и резисторы.ururur писал(а):как переделать под плавное включение всего порта сразу
Re: Подскажите по ШИМ
Могу дать на C. Код под мегу 8. Светодиод вешать на ножку PB1Serhio писал(а):Извините, но решил написать здесь. Может есть у кого-нибудь код на асме для Мега8 ШИМ плавное зажигание светодиода? или подскажите пожалуйста алгоритм, чтобы я мог сравнить со своими додумками
Код: Выделить всё
#include <avr/io.h>//библиотека ввода/вывода
//Програма задержки
void wait (unsigned int a)
{
unsigned int i;
for (i=a;i>0;i--);
}
//Програма инициализации ШИМ
void pwm (void)
{
TCCR1A=(1<<COM1A1)|(1<<WGM10);
TCCR1B=(1<<CS10);
OCR1A=0x00; //Начальная яркость нулевая
}
//Основная програма
int main(void)
{
unsigned char i;
DDRB=0x02; //Делаем PB1 на выход
pwm();
while (1)
{
for (i=0;i<255;i++) //Плавно повышаем яркость
{
OCR1A++;
wait(1000); // Ждем
}
for (i=0;i<255;i++) //Плавно понижаем яркость
{
OCR1A--;
wait(1000); Ждем
}
}
return 1;
}-
Serhio
- Прорезались зубы
- Сообщения: 249
- Зарегистрирован: Вс авг 15, 2010 20:42:44
- Откуда: Тюмень
- Контактная информация:
Re: Подскажите по ШИМ
Благодарю 
Подскажите пожалуйста как расчитать время задержки для ШИМ. Есть с обучалки задержка
Delay: out PortB,Temp
ldi Temp1,1
ldi Temp2,1
ldi Temp3,2
Loop: dec Temp1
brne Loop
dec Temp2
brne Loop
dec Temp3
brne Loop
ret
как узнать сколько миллисекунд она длится?
Подскажите пожалуйста как расчитать время задержки для ШИМ. Есть с обучалки задержка
Delay: out PortB,Temp
ldi Temp1,1
ldi Temp2,1
ldi Temp3,2
Loop: dec Temp1
brne Loop
dec Temp2
brne Loop
dec Temp3
brne Loop
ret
как узнать сколько миллисекунд она длится?
- Реклама
Re: Подскажите по ШИМ
Здравствуйте. Написал примитивный код без прерываний для мигания 2х светодиодов, на таймере 1(aTMEGA32A).Свтодиод на канале А плавно гаснит, а на В зажигается. Предделитель поставил 1, период = 0,125мкс, но при задержки в 0,01с(_delay_ms(10)) период составляет 0,01*255+0,000125*255=2,55с. _delay_ms(100) - использую как-бы для "устаявшегося значения", но вопрос ни в этом.
1. Подскажите как реализовать задержку, не используя _delay_ms(10), потому как при этой функции микроконроллер просто отсчитывает время не делая больше ничего?
2. Таймер считает до 255 потому что мы взяли (0<<WGM13)|(1<<WGM12) = WGM1Х - Fast PWM 8 бит?
Затем решил перевести на прерывания, но пока без задержек. Коэф-нт деления поставил 1024, чтобы было видно затухание и зажигание соответственно. Написал код ниже:
2. Но как сделать более плавное затухание и зажигание? Частоту снизить не получится(если только взять внешний кварц с меньшей частотой), т.к. делитель самый высокий 1024.
Помогите разобраться с этими 3мя вопросами. С уважением Дмитрий.
1. Подскажите как реализовать задержку, не используя _delay_ms(10), потому как при этой функции микроконроллер просто отсчитывает время не делая больше ничего?
2. Таймер считает до 255 потому что мы взяли (0<<WGM13)|(1<<WGM12) = WGM1Х - Fast PWM 8 бит?
Код: Выделить всё
#include<avr/io.h>
#include<util/delay.h>
int main(void) {
DDRD=(1<<PD4)|(1<<PD5);//PORTD ненадо настраивать
TCCR1A=(1<<COM1A1)|(1<<COM1A0)|(1<<COM1B1)|(1<<COM1B0)|(0<<WGM11)|(1<<WGM10);
TCCR1B=(0<<WGM13)|(1<<WGM12)|(0<<CS12)|(0<<CS11)|(1<<CS10);
OCR1A = 0;
OCR1B = 255;
asm("cli");//Запрещаем прерывания
while(1) {
OCR1A++;
OCR1B--;
_delay_ms(10);
if(OCR1A==255) {
_delay_ms(100);
OCR1A = 0;
OCR1B = 255;
_delay_ms(100);
}
}
}Код: Выделить всё
#include<avr/io.h>
#include <avr/interrupt.h>
//Прерывание по совпадению канала А. Таймер 1
ISR (TIMER1_COMPA_vect) {
PORTD|=(1<<PD5);
OCR1A++;
}
//Прерывание по совпадению канала B. Таймер 1
ISR (TIMER1_COMPB_vect) {
PORTD|=(1<<PD4);
OCR1B--;
}
//Прерывание по переполнению Таймера 1
ISR (TIMER1_OVF_vect) {
// flz=1;
PORTD&=~(1<<PD5);
PORTD&=~(1<<PD4);
}
int main(void) {
//Главое все эти настройки регистров прописывать в главном теле
DDRD=(1<<PD4)|(1<<PD5);//PORTD ненадо настраивать
PORTD=(0<<PD4)|(0<<PD5);
TCCR1A=(0<<WGM11)|(1<<WGM10);
TCCR1B=(0<<WGM13)|(1<<WGM12)|(1<<CS12)|(0<<CS11)|(1<<CS10);
//Вкл. прер. по совпадению в А, В и переполнению Т1
TIMSK=(1<<OCIE1A)|(1<<OCIE1B)|(1<<TOIE1);
OCR1A=2;
OCR1B=253;
asm("sei");//Разрешаем все прерывания
TCNT1=0;
while(1) {
if(OCR1A==255 || OCR1B==0) {
OCR1A=0;
OCR1B=255;
}
}
}
}Помогите разобраться с этими 3мя вопросами. С уважением Дмитрий.
Re: Подскажите по ШИМ
1. Для этих целей используют таймеры. Если задач немного, то можно для каждой использовать свой таймер. В последних Атмегах их 3. Если задач больше, надо реализовывать конвейер. Об этом хорошо написано на http://easyelectronics.ru/
3. Если не хватает встроенного счетчика, можно устроить свой, подсчитывая число срабатываний таймера. Для этого в обработчике прерывания инкрементируем переменную, а в теле программы проверяем ее значение. Если больше, запускаем обработчик и обнуляем. На инкремент тратится мало тактов, на проверку - тоже. Так что задержек не будет
3. Если не хватает встроенного счетчика, можно устроить свой, подсчитывая число срабатываний таймера. Для этого в обработчике прерывания инкрементируем переменную, а в теле программы проверяем ее значение. Если больше, запускаем обработчик и обнуляем. На инкремент тратится мало тактов, на проверку - тоже. Так что задержек не будет
Re: Подскажите по ШИМ
Пробывал добавить инкремент в обработчик прерываний, для снижения частоты(более долгом затухании и разгорании). Время затухания увелилось вдвое, но мерцание сильное. Надо подумать над плавностью смены сигнала. Хотя при делители 512 мерцания невидно.Orion33 писал(а):3. Если не хватает встроенного счетчика, можно устроить свой, подсчитывая число срабатываний таймера. Для этого в обработчике прерывания инкрементируем переменную, а в теле программы проверяем ее значение. Если больше, запускаем обработчик и обнуляем. На инкремент тратится мало тактов, на проверку - тоже. Так что задержек не будет
Код: Выделить всё
#include<avr/io.h>
#include <avr/interrupt.h>
volatile char flza=0;//Флаг задержек А
volatile char flzb=0;//Флаг задержек В
//Прерывание по совпадению канала А. Таймер 1
ISR (TIMER1_COMPA_vect) {
if(flza==0) {
flza=1;
PORTD|=(1<<PD5);
OCR1A++;
} else {flza=0;}
}
//Прерывание по совпадению канала B. Таймер 1
ISR (TIMER1_COMPB_vect) {
if(flzb==0) {
flzb=1;
PORTD|=(1<<PD4);
OCR1B--;
} else {flzb=0;}
}
//Прерывание по переполнению Таймера 1
ISR (TIMER1_OVF_vect) {
PORTD&=~(1<<PD5);
PORTD&=~(1<<PD4);
}
int main(void) {
DDRD=(1<<PD4)|(1<<PD5);//PORTD ненадо настраивать
PORTD=(0<<PD4)|(0<<PD5);
TCCR1A=(0<<WGM11)|(1<<WGM10);//WGM1Х - Fast PWM 8 бит
TCCR1B=(0<<WGM13)|(1<<WGM12)|(1<<CS12)|(0<<CS11)|(1<<CS10);
TIMSK=(1<<OCIE1A)|(1<<OCIE1B)|(1<<TOIE1);
OCR1A=2;
OCR1B=253;
asm("sei");
TCNT1=0;
while(1) {
if(OCR1A==255 || OCR1B==0) {
OCR1A=0;
OCR1B=255;
}
}
}Re: Подскажите по ШИМ
Решено: надо использовать предделитель 512, а в обработчике прерываний просто добавлять 'конечные автоматы' или промежуточные значения if(flza==0) {..} else { if(flza==1) {flza=2;} else {flza=0;}} Наглядней через switch.
Может кто знает как проще сделать напишите пожалуста.
Может кто знает как проще сделать напишите пожалуста.
Я как раз там статьи и читал про ШИМ, но она на асме, и попробывал написать на Си. Только я не понял про какой 'конвейер' идет речь?Orion33 писал(а):Если задач больше, надо реализовывать конвейер. Об этом хорошо написано на http://easyelectronics.ru/
Re: Подскажите по ШИМ
Там про RTOS есть цикл статей, точно название сейчас не помню. Смысл в том, что единый таймер через определенные промежутки времени опрашивает очередь, выполняет операцию из начала и сдигает очередь. Другие прерывания могут вмешиваться в эту очередь и вставлять свои обработчики согласно приоритету. Сложно, но ИМХО правильное решение. Если один раз разобраться, можно потом просто задачи новые в конвейер добавлять, а ядро останется всегда одним)EmDmAl писал(а):Я как раз там статьи и читал про ШИМ, но она на асме, и попробывал написать на Си. Только я не понял про какой 'конвейер' идет речь?Orion33 писал(а):Если задач больше, надо реализовывать конвейер. Об этом хорошо написано на http://easyelectronics.ru/


