Перейти к содержанию

Attiny13 Softpwm Вспышки


xopkep

Рекомендуемые сообщения

Здравия желаю. Есть вот такой код (честно не помню откуда брал):

#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 9600000UL
#include <util/delay.h>
#include <stdlib.h>

void abc(unsigned char a,unsigned char b,unsigned char c,unsigned char status);

unsigned char e, tonight=0;
unsigned char pwm[3]={0,0,0};//здесь храним значения яркости светодиодов
unsigned char to[3]={0,255,0};//здесь храним цвет, к которому будем стремиться.

int main(void)
{
DDRB |= (1<<0|1<<1|1<<2);
PORTB&= ~(1<<0|1<<1|1<<2);
TCCR0A = 0x00;
TCCR0B = 0x01;//No Prescaling
TIMSK0 = 1<<TOIE0;//Прерывание по переполнению
sei();
while(1){
//идём к цвету
if (pwm[0]<to[0]) pwm[0]++;
if (pwm[0]>to[0]) pwm[0]--;
if (pwm[1]<to[1]) pwm[1]++;
if (pwm[1]>to[1]) pwm[1]--;
if (pwm[2]<to[2]) pwm[2]++;
if (pwm[2]>to[2]) pwm[2]--;
if(pwm[0]==0&&pwm[1]==0&&pwm[2]==0) {//to red from black
to[0]=0; //blue
to[1]=255; //red
to[2]=0; //green
};
if(pwm[0]==0&&pwm[1]==255&&pwm[2]==0) {//to green+blue
to[0]=255; //blue
to[1]=255; //red
to[2]=255; //green
};

if(pwm[0]==255&&pwm[1]==255&&pwm[2]==255) {tonight=1;}

if(pwm[0]==255&&pwm[1]==255&&pwm[2]==255&&tonight==1) {//from green+blue
to[0]=0; //blue
to[1]=255; //red
to[2]=0; //green
};
if(pwm[0]==0&&pwm[1]==255&&pwm[2]==0&&tonight==1) {//from red to black
to[0]=0; //blue
to[1]=0; //red
to[2]=0; //green
};

if(pwm[0]==0&&pwm[1]==0&&pwm[2]==0) {tonight=0;}

_delay_ms(50);
}
}

ISR(TIM0_OVF_vect)
{
if(e==255)
{
e=0;//обнуляем счётчик
PORTB |= (1<<0)|(1<<1)|(1<<2);
}

abc(pwm[0],pwm[1],pwm[2],e);
e++;
}

void abc(unsigned char a,unsigned char b,unsigned char c,unsigned char status) {
if((status==a)) PORTB&= ~(1<<0);
if((status==) PORTB&= ~(1<<1);
if((status==c)) PORTB&= ~(1<<2);
}

Проблема в том, что во время затуханий\нарастаний по коду, случаются вспышки любого случайного цвета до максимальной яркости. После вспышки цикл продолжается нормально. За одно затухание\нарастание может быть до двух вспышек. Прошу подсказать откуда они берутся.

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

void abc(unsigned char a,unsigned char b,unsigned char c,unsigned char status) {
if((status==a)) PORTB&= ~(1<<0);
if((status==) PORTB&= ~(1<<1);
if((status==c)) PORTB&= ~(1<<2);
}

Сначала исправьте ошибки (чтобы хотя бы компилировалось) и форматирование.

Кроме того, переменную e лучше объявить локальной статической.

Переменные, которые используются и в прерывании, и в основной программе объявить как volatile.

В процедуре сравнения с порогами использовать использовать отношения больше/меньше, но не равно. Иначе есть шанс что при изменении переменной, прерывание проскочит значение.

Но самое главное - форматирование и орфографические ошибки.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Но самое главное - форматирование и орфографические ошибки.

#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 9600000UL
#include <util/delay.h>
#include <stdlib.h>

void abc(unsigned char a,unsigned char b,unsigned char c,unsigned char status);

unsigned char tonight=0;
volatile unsigned char pwm[3]={0,0,0};//здесь храним значения яркости светодиодов
unsigned char to[3]={0,255,0};//здесь храним цвет, к которому будем стремиться.

int main(void)
{
//порты PB0-2 как выходы, выключены
DDRB |= (1<<0|1<<1|1<<2);
PORTB&= ~(1<<0|1<<1|1<<2);
//Инициализация таймера
TCCR0A = 0x00;
TCCR0B = 0x01;//No Prescaling
TIMSK0 = 1<<TOIE0;//Прерывание по переполнению
sei();//Глобальное разрешение прерываний

while(1){
if (pwm[0]<to[0]) pwm[0]++;
if (pwm[0]>to[0]) pwm[0]--;
if (pwm[1]<to[1]) pwm[1]++;
if (pwm[1]>to[1]) pwm[1]--;
if (pwm[2]<to[2]) pwm[2]++;
if (pwm[2]>to[2]) pwm[2]--;
if(pwm[0]<=0&&pwm[1]<=0&&pwm[2]<=0) {//to red from black
to[0]=0; //blue
to[1]=255; //red
to[2]=0; //green
};
if(pwm[0]<=0&&pwm[1]>=255&&pwm[2]<=0) {//to green+blue
to[0]=255; //blue
to[1]=255; //red
to[2]=255; //green
};

if(pwm[0]>=255&&pwm[1]>=255&&pwm[2]>=255) {tonight=1;}

if(pwm[0]>=255&&pwm[1]>=255&&pwm[2]>=255&&tonight==1) {//from green+blue
to[0]=0; //blue
to[1]=255; //red
to[2]=0; //green
};
if(pwm[0]<=0&&pwm[1]>=255&&pwm[2]<=0&&tonight==1) {//from red to black
to[0]=0; //blue
to[1]=0; //red
to[2]=0; //green
};

if(pwm[0]<=0&&pwm[1]<=0&&pwm[2]<=0) {tonight=0;}

_delay_ms(50);
}
}

ISR(TIM0_OVF_vect)
{
static unsigned char e = 0;
if( e == 255)
{
e=0;
PORTB |= (1<<0)|(1<<1)|(1<<2);
}
abc(pwm[0],pwm[1],pwm[2],e);
++e;
}

void abc(unsigned char a,unsigned char b,unsigned char c,unsigned char status) {
if((status==a)) PORTB&= ~(1<<0);
if((status==) PORTB&= ~(1<<1);
if((status==c)) PORTB&= ~(1<<2);
}

Рекомендации выполнил: e локальная статическая, pwm[3] объявлена volatile, ну и == заменены на <= и >=.

Форматирование сбилось на форуме (можно смотреть здесь). Орфографическая ошибка - досадное недоразумение.

Вспышки все равно в наличии :(

Изменено пользователем xopkep
Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Потому что не выполнили. Форматирования как не было так и нет, программа как не могла скомпилироваться, так и не может.

Раз форматирование сбилось, стоило его поправить. Орфографическая ошибка - заглавная буква В в функции сравнения, вместо строчной b - язык Си чувствителен к регистру.

Ну и процедура сравнения - void abc(unsigned char a, unsigned char b, unsigned char c, unsigned char status); У вас там проверка на равенство. Если между прерываниями величина любой из переменных "перескочит" через значение status, такое сравнение не сработает, соответственно и диод не погаснет.

//как-то так. Не думаю, что вынесение сравнений в отдельную процедуру оправдано
ISR(TIM0_OVF_vect){
 static unsigned char time=0; //стоит сделать эту переменную невидимой снаружи.
 // Можно сразу проверить на ноль, может оптимизатор сообразит не делать лишнюю проверку.
 // Ручное обнуление тоже не нужно, при переполнении оно произойдет автоматически.
 if( ++time ){
   if( time >= pwm[0] )PORTB &=~(1<<0);
   if( time >= pwm[1] )PORTB &=~(1<<1);
   if( time >= pwm[2] )PORTB &=~(1<<2);
 }else{
   PORTB |= (1<<0 | 1<<1 | 1<<2);
 }
}
//ну или если считаете, что лучше исправить процедуру
void abc( unsigned char a, unsigned char b, unsigned char c, unsigned char status ){
 if( status >= a ) PORTB &=~ (1<<0);
 if( status >= b ) PORTB &=~ (1<<1);
 if( status >= c ) PORTB &=~ (1<<2);
}

Примерно это я имел в виду.

Изменено пользователем COKPOWEHEU

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

Потому что не выполнили. Форматирования как не было так и нет, программа как не могла скомпилироваться, так и не может.

Раз форматирование сбилось, стоило его поправить. Орфографическая ошибка - заглавная буква В в функции сравнения, вместо строчной b - язык Си чувствителен к регистру.

Публикуя предыдущий пост, я убедился в правильности кода и его компилируемости, но на всякий случай привел вот эту ссылку...

Спасибо огромное!

if( status >= a ) PORTB &=~ (1<<0);

вместо

if( status == a ) PORTB &=~ (1<<0);

действительно решает проблему вспышек!

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...