avatar
Хотел замечаний, получи:
Объявляем библиотеки и данные:
Ты в каждой статье их объявляешь. Пора уже вынести куда-нибудь.

//общее количество разрядов индикатора
#define LEDDIGITS 4

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

template <uint8 SegmentCount> class SegmentDisplay
// а потом сделать тайпдеф для своего индикатора:
typedef SegmentDisplay<4> RlnSegmentDisplay


Это хоть и правильно, но сложно и не нужно. Ведь в текущей реализации нельзя использовать несколько индикаторов. В итоге, у тебя два варианта — вынести весь код, который специфичен для твоего индикатора в отдельные методы и в своей реализации переопределять их:

class SegmentIndicatorBase
{
    protected:
        virtual int segmentCount() = 0 const;
        ....
};

class RlnSegmentIndicator : protected SegmentIndicatorBase
{
    protected:
        virtual int segmentCount() { return 4; };
        ....
};


Либо просто забить и прописать 4 константой в классе.

void Init(uint8_t _Base);//функция инициализации
Всегда радовали такие комментарии :)

мне не удалось передать указатель на эту функцию ни изнутри класса, ни снаружи
Указатель на метод класса называется «делегат». Фишка в том, что чтобы вызвать метод класса нужно не просто его вызвать, но еще и передать ему указатель на данные класса. Поэтому твой хак — вполне нормальная штука.

BUTTONSSETUP;

Такого вообще лучше не делать. Совсем не понятно, что это.

uint16_t UIntPow(uint16_t _data, uint8_t _pow){//Возведение целого числа в степень

Ты извини, но функция гениальна. Напиши лучше просто таблицу

Ну, это — для начала :)
avatar
Будет. Реализую знаковый и десятичный вывод на индикатор и будет.
avatar
Мне кажется, что функции типа «вывод информации на индикатор» неплохо бы оформить в качестве библиотеки. Потому, что когда читаешь статью про энкодер, кусок кода для вывода на индикатор как-то не в тему смотрится.

По идее, должно быть что-то типа такого:

#include "RlnElectro.h"

void main()
{
    RlnInit();
    RlnSegmentDisplay_Show(1234);
}
avatar
Таких реле — тьма: начиная от мелочи и кончая контакторами на тыщи ампер. Вот, для примера, даташит на релюшку от OMRON.
avatar
Никогда не видел таких реле
avatar
Это — для всех компиляторов, просто потому, что по другому не сделаешь.
avatar
А это для какого компилятора? Например, между майкрософтовским и GCC есть отличия, которые мешают использовать одинаковые библиотеки на C++.
avatar
Угадал. Молодец, держи плюсик :)
Спасибо тебе добрый человек.
avatar
Сергей, обрати, плз, внимание на формат коммента: после редактирования кнопкой «изменить» в форме вылазит много мусора и после сохранения вылазит в видимость тэг «code»…
avatar
А не связано это с тем, что приоритет операции логического отрицания выше, чем побитовое «и»? Мб скобки переставить:
if (EncPortData[1]&0x01 && !(EncPortData[0]&0x01))//нарастающий фронт по А!
if (EncPortData[1]>>1)&0x01 && !(EncPortData[0]>>1)&0x01)//нарастающий фронт по B!
В первой строчке вообще не понятно зачем скобки вокруг элемента массива…
avatar
Спойлер
Смахивает на помешательство. Пойду ка я отдохну, а то уже void вместо vk.com в командной строке набираю
avatar
реле, катушка которого рассчитана на переменное напряжение 220В, не?
avatar
Код указанный выше. И в нем есть очень неявная ошибка.
Задача кода — устанавливать выход в единицу по фронту сигнала А, а сбрасывать — по фронту сигнала Б.
Два «независимых» условия, каждое смотрит текущее и предыдущее состояния и в стучае фронта — делает свое дело.
Вот только если сначала появляется фронт А, а потом Б — все работает как надо (что идеально работает как раз с упомянутой кнопкой).
Но вот если крутить наоборот, т.е. сначала Б, потом А, то операция (EncPortData[1]>>1) портит данные. Именно этим меня утром и осенило :) Попытался найти подобный случай в Макконнелле(Совершенный код), но нашел только приведенную выше цитату на первой же странице результатов поиска :)
avatar
Что это за реле такое, на катушку которого подается 220В переменки?
avatar
Вчера я его не смог приладить к энкодеру, догадайтесь почему.
Телепаты, ау?

Вопрос знатокам — почему код правильно отрабатывает свое предназначение при вращении энкодера в одну сторону и взрывает мозг в другую?
Какой код? Что за предназначение?
avatar
«Я не тупой» © Гомер Симпсон.

Ложась спать, меня вдруг покоробило «Но я же видел Правильные осциллограммы!»
Утром я буквально вскочил за пол часа до будильника с пониманием того, где закралась проблема. Разумеется, состояние энкодера выводится на семисегментник.

Считывается состояние так:
EncPortData[1]=(ENCODERINPORT>>5)&0x03;//прочли сырое значение


Выводится это состояние так:
PORTC&=~0x30; PORTC|=(EncPortData[1]<<4);


А между ними код, подавляющий дребезг контактов. К слову сказать работающий без сбоев для какой-то там кнопки, где-то на реальной железке. Вчера я его не смог приладить к энкодеру, догадайтесь почему. Код фиксирует фронты по друм линиям. По фронту одной линии сетит, другой — ресетит.
if ((EncPortData[1])&0x01 && !(EncPortData[0])&0x01)//нарастающий фронт по А!
if ((EncPortData[1]>>1) & 0x01 && !(EncPortData[0]>>1) & 0x01)//нарастающий фронт по B!


Вопрос знатокам — почему код правильно отрабатывает свое предназначение при вращении энкодера в одну сторону и взрывает мозг в другую?
avatar
В одну сторону крутишь, выдает последовательность 0/3
в другую сторону крутишь, выдает последовательность 1/2
Тут, правда, с определением направления вращения еще проще — XOR(a,b) и делов.
Взял с полки непаянный — та же хрень.
avatar
А что тогда?
avatar
Забавно. У распаянного на плате энкодера сигнал на выходе — НЕ код Грея.
avatar
Ну если визуально, то можно еще неонку с резистором.