/**Программа ручного и автоматического управления RGB светодиодами.*/ //Подключаем необходимые библиотеки #include "GenericHID.h" #include #include #include #include #include #include //Определяем переменные float red,green,yellow,blue; //Новые цвета unsigned int tred,tgreen,tyellow,tblue; //Исходные цвета //Величина прибавки за шаг float delta_red,delta_green,delta_yellow,delta_blue; unsigned int time; //Длительность шага unsigned int temp1,temp2,temp3,temp4,temp5,temp6; //Режим работы Автомат-1, ручной-2, ЦМУ-3, по времени-4, выкл=0, unsigned char regim; unsigned char result; unsigned char R1,G1,Y1,B1; //Основные цвета unsigned char R2,G2,Y2,B2; unsigned char Rf,Gf,Yf,Bf; //Цвет фона unsigned char dRf,dGf,dYf,dBf; //Для плавного включения фона unsigned char zmax, zmin, tim; //Задержки unsigned int hizat; //Затухание старший байт unsigned char lozat; //Затухание младший байт unsigned int hizatf; //Задержка фона (плавность) старший байт unsigned char lozatf; //Задержка фона (плавность) младший байт /** В связи с тем, что программный генератор случайных чисел при каждом новом запуске генерирует одну и ту же последовательность импульсов, мы ввели процедуру начальной установки этого генератора при помощи простейшего АЦП. Он принимает на входе шумы и наводки и выдает практически случайное число, которым мы и выполним начальную установку функции SRAND. Вкратце принцип работы этого АЦП таков. На один из входов компаратора подается линейно-нарастающее напряжение зарядки конденсатора С5, а второй вход "висит" в воздухе, т.е. на нем имеются наводки.Включается таймер и компаратор. В момент совпадения потенциалов на обоих входах компаратора таймер останавливается и его значение используется для установки SRAND.*/ //Определяем п/п прерывания компаратора. ISR(ANALOG_COMP_vect ) { result = TCNT0; //Загрузка значения таймера 0 TCCR0B = 0; //Остановим таймер CLRBIT(PORTC,PC2); //Запуск разрядки конденсатора srand(result); //Инициализируем функцию SRAND } /**Буфер для хранения HID репорта*/ static uint8_t PrevHIDReportBuffer[GENERIC_REPORT_SIZE]; /**Интерфейс конфигурации*/ USB_ClassInfo_HID_Device_t Generic_HID_Interface = { .Config = { .InterfaceNumber = 0, .ReportINEndpointNumber = GENERIC_IN_EPNUM, .ReportINEndpointSize = GENERIC_EPSIZE, .ReportINEndpointDoubleBank = false, .PrevReportINBuffer = PrevHIDReportBuffer, .PrevReportINBufferSize = sizeof(PrevHIDReportBuffer), }, }; /** П/п Генерация яркости, max 255. Случайным образом выбираем цвета и если они примерно равны генерим снова*/ void generate_tagert_color(void) { do { tred = rand() & 0xFF; tgreen = rand() & 0xFF; tyellow = rand() & 0xFF; tblue = rand() & 0xFF; temp1 = (abs(tred - tgreen)); temp2 = (abs(tred - tyellow)); temp3 = (abs(tred - tblue)); temp4 = (abs(tgreen - tyellow)); temp5 = (abs(tgreen - tblue)); temp6 = (abs(tyellow — tblue)); /**Так как здесь наша программа может "закрутиться" надолго (относительно конечно), то введем проверку "активности шины USB, чтобы не пропустить что нибудь интересное*/ HID_Device_USBTask(&Generic_HID_Interface); USB_USBTask(); } while (( temp1 < 150 ) && (temp2 < 150) && (temp3 < 150) && (temp4 < 150) && (temp5 < 150) && (temp6 < 150)); }; /**задержка delay_ms() на вход принимает только константу*/ void delay(unsigned int delayt) { while (delayt != 0) { /**Если работает автомат, то в период задержки нужно часто опрашивать USB*/ HID_Device_USBTask(&Generic_HID_Interface); USB_USBTask(); _delay_ms(1); delayt--; /**Если вдруг сменился режим то закончим задержку досрочно*/ if(regim==0 || regim==2 || regim==3) { return; } }; }; /** Главная программа */ int main(void) { /** Настройка АЦП и генерация начальной установки SRAND. После срабатывания этого блока будет произведена начальная установка генератора случайных чисел случайным числом (вот такой каламбур).*/ ACSR = 0x0B; // Разрешение работы и прерывания компаратора DDRC=(1< 4)); //Красный if (temp4 == 1) { do { temp4 = rand() & 0x0FFF; } while ((temp4 == 0) || (temp4 > 3276)); tred = ceil((float)(temp4 / 32767) * tred); }; // Зеленый if (temp4 == 2) { do { temp4 = rand() & 0x0FFF; } while ((temp4 == 0) || (temp4 > 3276)); tgreen = ceil((float)(temp4 / 32767) * tgreen); }; // Желтый if (temp4 == 3) { do { temp4 = rand() & 0x0FFF; } while ((temp4 == 0) || (temp4 > 3276)); tyellow = ceil((float)(temp4 / 32767) * tyellow); }; // Синий if (temp4 == 4) { do { temp4 = rand() & 0x0FFF; } while ((temp4 == 0) || (temp4 > 3276)); tblue = ceil((float)(temp4 / 32767) * tblue); }; }; //Находим значение прибавки. доходим до нужного цвета за 255 шагов delta_red = (float)(tred - red) / 255; delta_green = (float)(tgreen - green) / 255; delta_yellow = (float)(tyellow - yellow) / 255; delta_blue = (float)(tblue - blue) / 255; /**Выбор времени задержки. Если от РС нет данных, то устанавливаем задержки по умолчанию, а если есть, то пользуемся принятыми. Этот блок работает в режиме Автомат */ if (zmax==0 || zmin==0) { zmax=39; zmin=5; }; do { time = rand() & 0x00FF; } while ((time < zmin) || (time > zmax)); /**Если включен режим По времени, то установим время изменения цвета, которое пришло из РС */ if (regim==4) time=tim; //Продолжим программу. Установим цвета для вывода и выдадим их do { if (tred != ceil(red)) { red = red + delta_red; }; if (tgreen != ceil(green)) { green = green + delta_green; }; if (tyellow != ceil(yellow)) { yellow = yellow + delta_yellow; }; if (tblue != ceil(blue)) { blue = blue + delta_blue; }; OCR1CL = ceil(blue); OCR1BL = ceil(green); OCR1AL = ceil(red); OCR0B = ceil(yellow); //Чуток ожидаем (это скорость изменения цвета). delay(time); /**Если вдруг включили режим ЦМУ, то досрочно выходим из Автомата. Это сделано для более быстрого переключения режимов.*/ if(regim==3) goto main; } while ((tred != ceil(red)) || (tgreen != ceil(green)) || (tyellow != ceil(yellow)) || (tblue != ceil(blue))); //В режиме Автомат задержим установленные цвета. if (regim==1) delay(time * 255); //В режиме По времени ничего задерживать не нужно. if(regim==4) goto main; }; /**------------ Конец автоматического режима -------------------*/ /**-------------------- Режим ЦМУ -----------------------------*/ if (regim==3) { //Если музыки нет, включить фон if((R1==0) && (G1==0) && (Y1==0) && (B1==0)) goto pause; /**Определим соотношения предыдущей и вновь принятой яркости и примем решение, как нам ее изменить.*/ //Красный канал //Если новое значение больше ранее установленного if (R2R1); }; //Если новое значение меньше ранее установленного if (R2>R1) { do { /**Снижаем яркость до вновь принятой с задержкой.(Параметр затухание)*/ OCR1AL=R2; R2=R2-1; _delay_us(hizat); } while (R2G1); }; if (G2>G1) { do { OCR1BL=G2; G2=G2-1; _delay_us(hizat); } while (G2Y1); }; if (Y2>Y1) { do { OCR0B=Y2; Y2=Y2-1; _delay_us(hizat); } while (Y2B1); }; if (B2>B1) { do { OCR1CL=B2; B2=B2-1; _delay_us(hizat); } while (B2, то снижаем яркость с задержкой*/ { //Красненький if((Rf>0) && (R1=Rf)) { OCR1AL=R1; }; if((Rf>0) && (R1>Rf)) { while(R1>Rf) { OCR1AL=R1; R1=R1-1; _delay_us(hizatf); } }; if((Rf>0) && (R10) && (G1=Gf)) { OCR1BL=G1; }; if((Gf>0) && (G1>Gf)) { while(G1>Gf) { OCR1BL=G1; G1=G1-1; _delay_us(hizatf); } }; if((Gf>0) && (G10) && (Y1=Yf)) { OCR0B=Y1; }; if((Yf>0) && (Y1>Yf)) { while(Y1>Yf) { OCR0B=Y1; Y1=Y1-1; _delay_us(hizatf); } }; if((Yf>0) && (Y10) && (B1=Bf)) { OCR1CL=B1; }; if((Bf>0) && (B1>Bf)) { while(B1>Bf) { OCR1CL=B1; B1=B1-1; _delay_us(hizatf); } }; if((Bf>0) && (B1