Есть такой код на attiny13 Код (C++): if (!digitalRead(pin)) { // проверяем старт бит (low) delayMicroseconds(80); // ждём половину времени 80 мкс if (!digitalRead(pin)) { // если всё ещё старт бит (low) int8_t bitCount = 0; // счётчик битов uint8_t byteCount = 0; // счётчик байтов while (1) { delayMicroseconds(156); // ждём бит 156 мкс uint8_t bit = digitalRead(pin); // читаем if (bitCount < 8) { // передача битов даты bitWrite(buf[byteCount], bitCount, bit); // пишем в буфер } else if (bitCount == 8) { // стоп бит (high) if (!bit) return 0; // ошибка стоп бита. Завершаем byteCount++; // счётчик собранных байтов } else if (bitCount == 9) { // старт бит (low) if (bit) return byteCount; // не дождались старт бита. Конец приёма, возврат количества if (byteCount >= size) return 0; // буфер переполнен. Завершаем bitCount = -1; // костыль } bitCount++; // следующий бит } } он работает но стопит основную программу а в ней программный шим из-за чего светодиоды моргают когда этот кусок кода работает.Если заменить delayMicroseconds на Код (C++): uint32_t _tmr2; if (micros() - _tmr1 >= 80) { _tmr1 = micros(); то код не работает.В чем может быть проблема
Этот блок полностью не работает, при изменении любой задержки на micros(), типа если изменить первую задержку до while то код ломается, из-за этого и спросил как это можно исправить.Ну или есть другой способ передавать число(1-100) с esp8266(или arduino nano но лучше esp) в attiny13(1 пин) без задержки
в не верном алгоритме. Программа должна выглядеть примерно так: Код (C++): function1(); function2(); function3(); Внутри самих функций вызываем таймер и проверяем, закончился ли интервал Код (C++): if (timer1.Q) { //.... } Выполнили простейшую операцию и перешли к следующему таймеру или функции. Если код критичен к интервалам, то полезно с таймера выводить остаток. Если этот остаток меньше, чем полный цикл всей программы (вычисляется на лету или экспериментально), то "добиваем" этот интервал нопами внутри функции. Разумеется, что внутри функций не должно быть никаких долгоиграющих циклов. С таким подходом уже можно попытаться минимизировать энергопотребление путём увода МК в какой-либо режим сна. Я неоднократно показывал, как это делается.
В аттину13 мало таймеров и решить эту проблему на них не получится.Из-за этого и спросил как это можно исправить на micros().
Код (C++): #include "GBUSmini.h" // библиотека приема данных #include "FastIO.h" #define max1 200 //здесь указывается максимальная яркость #define max2 180 #define max3 150 #define max4 120 #define min1 100 //здесь указывается минимальная яркость #define min2 100 #define min3 100 #define min4 100 #define step1 1 //здесь указывается шаг увеличения #define step2 1 #define step3 1 #define step4 1 #define chnout1 0 // пины выходов #define chnout2 2 #define chnout3 4 #define chnout4 3 #define chn1 1 //здесь указывается какие каналы у нас на плате #define chn2 2 #define chn3 3 #define chn4 4 volatile byte duty1; // переменные ШИМ сигнала volatile byte duty2; volatile byte duty3; volatile byte duty4; volatile byte dutyn1; // переменные нового ШИМ сигнала volatile byte dutyn2; volatile byte dutyn3; volatile byte dutyn4; boolean flag1 = false; boolean flag2 = false; boolean flag3 = false; boolean flag4 = false; #define MY_PERIOD 15 // период в мс uint32_t tmr1; // переменная таймера #define RX_PIN 1 // пин byte data[2]; // приёмный буфер (байты) void setup() { pinMode(chnout1, OUTPUT); // Все каналы ШИМ устанавливаются как выходы pinMode(chnout2, OUTPUT); pinMode(chnout3, OUTPUT); pinMode(chnout4, OUTPUT); pinMode(RX_PIN, INPUT_PULLUP); duty1 = min1; duty2 = min2; duty3 = min3; duty4 = min4; } int data1 = 0; void loop() { // ждём приём if (GBUS_read_raw(RX_PIN, data, sizeof(data))) { data1 = data[0]; switch (data1) { case chn1: flag1 = !flag1; break; case chn2: flag2 = !flag2; break; case chn3: flag3 = !flag3; break; case chn4: flag4 = !flag4; break; } } if (millis() - tmr1 >= MY_PERIOD) { // ищем разницу tmr1 = millis(); if (flag1) { if (duty1 < max1) { duty1 = duty1 + step1; } } else { if (duty1 != min1) { duty1 = duty1 - step1; } } if (flag2) { if (duty2 < max2) { duty2 = duty2 + step2; } } else { if (duty2 != min2) { duty2 = duty2 - step2; } } if (flag3) { if (duty3 < max3) { duty3 = duty3 + step3; } } else { if (duty3 != min3) { duty3 = duty3 - step3; } } if (flag4) { if (duty4 < max4) { duty4 = duty4 + step4; } } else { if (duty4 != min4) { duty4 = duty4 - step4; } } } pwmTick(); } void pwmTick() { static volatile uint8_t counter = 0; // Счетчик if (counter == 0) { if (duty1 > min1) fastWrite(chnout1, HIGH); if (duty2 > min2) fastWrite(chnout2, HIGH); if (duty3 > min3) fastWrite(chnout3, HIGH); if (duty4 > min4) fastWrite(chnout4, HIGH); dutyn1 = duty1; dutyn2 = duty2; dutyn3 = duty3; dutyn4 = duty4; } if (counter == dutyn1) fastWrite(chnout1, LOW); // Проверяем все каналы на совпадение счетчика со значением заполнения if (counter == dutyn2) fastWrite(chnout2, LOW); // При совпадении переводим канал в состояние LOW if (counter == dutyn3) fastWrite(chnout3, LOW); if (counter == dutyn4) fastWrite(chnout4, LOW); counter++; // Инкремент счетчика } вот основная программа, GBUS_read_raw - этот тот кусок кода в начале
таймеры, разумеется, программные. Внутренний счётчик у всех таймеров либо дуриновский micros или свой, с меньшей разрядностью. Тик таймеров в зависимости от необходимой точности. 156мс легко сдвинуть в сторону 155мс и тогда тик будет 5мс. Тик накидываем в прерывании от аппаратного таймера. Если прерывания нет или ещё какая причина, то тик накидываем при вызове обработчика таймера или каждый раз перед обработчиком. Тут какой-то единой позиции нет - каждый решает сам, как ему потребно)))