Замена analogWrite на Arduino Nano. Массивы функций.
Доброго времени суток!
Да, может уже надоело по ШИМ, но я хочу закончить этот ШИМ для себя и оставить немного полезностей.
В первой части программного ШИМа, уважаемый @Begemot911 подкинул одну занимательную статейку (если интересно - ссылку найдете там же), а именно про то, что analogWrite довольно медленный в силу своей универсальности, и для того что бы его ускорить, нужно просто ручками вписать в нужный таймер в нужный регистр сравнения значение скважности (в таймер, или подключить вывод нужного таймера, - не знаю как это правильно сказать). Да, это действительно ускоряет результат, но нужно знать какой таймер, какой регистр, какой бит порта, и пока analogWrite все это определит и получается задержка.
Так же в статейке написано как "подключить таймер", и как "записать значение в регистр", по сути это просто скопировано из исходника.
Я тут же решил проверить, как это работает в реалиях,.. и да... это работает, если все нужные данные известны. И вот мне пришла в голову мысль, - а если написать заранее все функции записи в каждый таймер/регистр, и запилить их указатели в один массив. Казалось бы затея простая, но гугл сказал - "давай ты сам", возможно, я гуглить разучился.
Спустя полчаса-час мучений и баданий с Arduino IDE, его компилятор сказал, что он понял чего я хочу, и скомпилировал код.
Что получилось на практике - Если записать сначала скважность хотя бы 1, то потом, записав 0 - на выходе все-равно есть сигнал. Вообщем перед записью значений 0 и 255 надо бы еще и ШИМ выключить (в статейке про это сказано, что типа нефиг писать 0 и 255) - да, логично, но я чот подумал что если в порт на этот пин записать 0 или 1, то ШИМ сам отключится - *индейская народная изба*. Ладно, берем все необходимое, и пишем код:

Взять код можно на github.com
Как работает котэ:
Дефайны - просто определяют cbi и sbi, ничего интересно, все это знают.
Есть 6 функций, каждая и которых отвечает за свой пин (3, 5, 6, 9, 10, 11), по порядку. Алгоритм функции таков: сначала порт переводится в режим OUTPUT, затем, если задаваемое значение скважности 0 или 255, то отключается режим ШИМ, и в порт пина записывается 0 или 1, иначе, включается ШИМ на нужное значение скважности. В общем и целом, вся логика сделана такая же как и у analogWrite, только без всех проверок и прочих определений, все только по факту.
Далее определяем массив из указателей на эти функции. Делается это так:
void ( * название_массива_функции[])(типы_условных_параметров) = {&название_функции_1, &название_функции_2 ... и т.д.}
Как я понял, можно использовать функции с разными параметрами, но тут я не нашёл ответа как, понял только, что если будет функция без параметров в массиве функций с параметрами, то ничего страшного, а вот если разное количество параметров, разного типа - то ответа я не нашёл.
Конечно же, если у вас не Nano, а что-то более жирное, то можно добавить свои функции
И получаем вот такую удобную конструкцию.
Например надо на все пины ШИМ, подать какие-либо значения скважности
Определяем значения скважности в массив
byte valueMass[]=;
и банальным FORэм передаем все значения в функции
for(byte i=0;i<6;i++) analogFastWrite[i](valueMass[i]);
Вот и всё!
Я думаю что существует способ обойтись без FOR и передать значения как-то напрямик, но я пока не нашёл как. Если кто знает, напишите в комментариях, очень требуется.
Наверняка кому-нибудь пригодится, если не вариация замены analogWrite, то пример как сделать массив из указателей на функции в Arduino IDE.
Комментарии