Указатели указатели указатели (помогите разобраться)

fusic
Offline
Зарегистрирован: 08.02.2017

Доброго дня !

Задача следующая:

использую Mega 2560

работаю с PWM-ами

нужно их постоянно обновлять

имеется массив из 15-ти байт

эти 15 байт надо переложить в 15ть регистров OCR

пытаюсь делать это в цикле

для этого создаю вот такой массив

unsigned int *OCR[15] = {(unsigned int*)&OCR3B, (unsigned int*)&OCR3C, (unsigned int*)&OCR0B, (unsigned int*)&OCR3A,

                         (unsigned int*)&OCR4A, (unsigned int*)&OCR4B, (unsigned int*)&OCR4C, (unsigned int*)&OCR2B,

                         (unsigned int*)&OCR2A, (unsigned int*)&OCR1A, (unsigned int*)&OCR1B, (unsigned int*)&OCR1C,

                         (unsigned int*)&OCR5C, (unsigned int*)&OCR5B, (unsigned int*)&OCR5A};

 

далее в цикле работаю

for (byte w = 0; w < 15; w++) {

    if (PWM[w] !=  BA[w]) { *OCR[w] = PWM[w]; };

    if (PWM[w] >= PWMMin) {PWMzero = false;}; 

  }

...вроде всё нормально работает но иногда какие-то глюки как будто новое значение ШИМа залетает не в тот OCR

+ уверен что дело именно в этих кусках кода т.к. если делать всё без цикла то проблема исчезает

- думаю что не правильно работаю с указателями НО что именно ????

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Тут сразу несколько ошибок. Во-первых, Вы смешали в один массив разные данные. Например, OCR3B - 16-ти разрядный, а OCR0B - восьмиразрядный.

Вот вторых, Вы их описани как указатели на int и тем самым потеряли то, что они на самомд деле регистры, а это важно, т.к. запись/чтение 16-тиразрядные регистры осуществляется не как попало, а в строго определённом порядке (даташит - 17.3). Целые же компилятор может писать как попало.

Так что попробыйте сгачала описать их все однородно, причём правильно, сохраняя тот факт, что они регистры, а не просто целые. Думаю, должно помочь. Если нет, то там посмотрим.

fusic
Offline
Зарегистрирован: 08.02.2017

про 16ти разрядные....8ми разрядные

все эти регистры я вытащил из тела analogWrite(pin, 0...255) и по сути просто избавился от перебора case, проведя инициализацию заранее

void PWM_init() {
  pinMode(2, OUTPUT);   TCCR3A |= (1 << COM3B1);
  pinMode(3, OUTPUT);   TCCR3A |= (1 << COM3C1);
  pinMode(4, OUTPUT);   TCCR0A |= (1 << COM0B1);
  pinMode(5, OUTPUT);   TCCR3A |= (1 << COM3A1);
  pinMode(6, OUTPUT);   TCCR4A |= (1 << COM4A1);
  pinMode(7, OUTPUT);   TCCR4A |= (1 << COM4B1);
  pinMode(8, OUTPUT);   TCCR4A |= (1 << COM4C1);
  pinMode(9, OUTPUT);   TCCR2A |= (1 << COM2B1);
  pinMode(10, OUTPUT);  TCCR2A |= (1 << COM2A1);
  pinMode(11, OUTPUT);  TCCR1A |= (1 << COM1A1);
  pinMode(12, OUTPUT);  TCCR1A |= (1 << COM1B1);   
  pinMode(13, OUTPUT);  TCCR1A |= (1 << COM1C1);
  pinMode(44, OUTPUT);  TCCR5A |= (1 << COM5C1);
  pinMode(45, OUTPUT);  TCCR5A |= (1 << COM5B1);
  pinMode(46, OUTPUT);  TCCR5A |= (1 << COM5A1);
};

да мне и не нужны 16ти разрядные ШИМы

fusic
Offline
Зарегистрирован: 08.02.2017

про смешение в одном массиве ....

это же адреса регистров и они все одинаковой разрядности (адреса)

или я вообще не туда :(

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

fusic пишет:

да мне и не нужны 16ти разрядные ШИМы

Это Ваши проблемы. Писать в них всё равно нужно правильно, ссылку на раздел даташита я давал. 

fusic
Offline
Зарегистрирован: 08.02.2017

Вы кодом помочь можете ?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Я? Пока нет, сейчас хоккей начинается.

fusic
Offline
Зарегистрирован: 08.02.2017

мне не срочно

если найдёте время...)))...буду признателен

b707
Offline
Зарегистрирован: 26.05.2017

fusic пишет:

мне не срочно

если найдёте время...)))...буду признателен

думаю вы не поняли. Это была ирония. Здесь код за других писать не принято.

Вам надо разобраться. что такое регистры и чем они отличаются от обычных переменных. Информацию вам дали.

А если это для вас сложно - тогда не лезьте "улучшать" AnalogWrite() - пользуйтесь кодом с case

fusic
Offline
Зарегистрирован: 08.02.2017

а вот такой код 

OCR3B = 0x0033;

компилятор сам "превратит" в правильную последовательность записи сначала старшего байта потом младшего ?

 

fusic
Offline
Зарегистрирован: 08.02.2017

[/quote]

А если это для вас сложно - тогда не лезьте "улучшать" AnalogWrite() - пользуйтесь кодом с case

[/quote]

нет времени порожняк гонять (много бесполезных команд)

fusic
Offline
Зарегистрирован: 08.02.2017

дайте хоть пример как правильно писать в РЕГИСТР через указатель ?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

fusic пишет:

а вот такой код 

OCR3B = 0x0033;

компилятор сам "превратит" в правильную последовательность записи сначала старшего байта потом младшего ?

Таки, да.

fusic
Offline
Зарегистрирован: 08.02.2017

ЕвгенийП пишет:

fusic пишет:

а вот такой код 

OCR3B = 0x0033;

компилятор сам "превратит" в правильную последовательность записи сначала старшего байта потом младшего ?

Таки, да.

...а то же самое через указатель как реализовать ?

b707
Offline
Зарегистрирован: 26.05.2017

fusic пишет:

нет времени порожняк гонять (много бесполезных команд)

вы чего пытаетесь добиться-то? Улучшить Вайринг?  или построить конкретный проект?

Каждый конкретный пин PWM завязан на свой таймер и свой регистр. Если Вы не пишете свою "лучщую библиотеку на все времена" - значит у вас каждый пин несет свою нагрузку и никакого switch-case там и в помине нет и никакого выбора из 15 пинов через массив нафик не нужно.

fusic
Offline
Зарегистрирован: 08.02.2017

b707 пишет:

fusic пишет:

нет времени порожняк гонять (много бесполезных команд)

вы чего пытаетесь добиться-то? Улучшить Вайринг?  или построить конкретный проект?

Каждый конкретный пин PWM завязан на свой таймер и свой регистр. Если Вы не пишете свою "лучщую библиотеку на все времена" - значит у вас каждый пин несет свою нагрузку и никакого switch-case там и в помине нет и никакого выбора из 15 пинов через массив нафик не нужно.

 

...ооооо....значит ли это что компилятор не включит в результирующий код все эти case для каждого шима ?

b707
Offline
Зарегистрирован: 26.05.2017

fusic пишет:

...ооооо....значит ли это что компилятор не включит в результирующий код все эти case для каждого шима ?

зависит от того, как вы их пропишете. Если у вас пин - константа или задан дефайном, оптимизатор, скорее всего, выкинет все ветки switch. кроме нужной.

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

fusic
Offline
Зарегистрирован: 08.02.2017

b707 пишет:

fusic пишет:

...ооооо....значит ли это что компилятор не включит в результирующий код все эти case для каждого шима ?

зависит от того, как вы их пропишете. Если у вас пин - константа или задан дефайном, оптимизатор, скорее всего, выкинет все ветки switch. кроме нужной.

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

да...сейчас так и сделано...для каждого шима отдельная строка под конкретный регистр

попробовал заменять запись в регистр стандртной analogWrite (сначала один выход потом 2 и т.д.) и похоже компилятор действительно выкидывает лишние case (судя по размеру занимаемой скетчем)

похоже вопрос снят

 

fusic
Offline
Зарегистрирован: 08.02.2017

однако всё же призамене, во всех 15ти строках, записи в регист на analogWrite, размер скетчя вырос на 430 байт

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

fusic пишет:

...а то же самое через указатель как реализовать ?

Не знаю, т.к. не знаю, чего именно Вы хотите добиться.

Только это не самая первая Ваша проблема. Первая проблема - смесь 8-ми и 16-битных регистров.

Вы ведь всё преобразуете к указателю на int. Значит любая запись будет производиться в ДВА байта! Итак Вы пишете ДВА байта по адресу, где живёт 8-битный регистр. Куда пишется второй байт? Напрягитесь! Правильно, в соседний регистр. Вы понимаете, что там начинается?

fusic
Offline
Зарегистрирован: 08.02.2017

...там начинается другой шим

и с учетом этого не стоит этот огород городить

b707
Offline
Зарегистрирован: 26.05.2017

fusic пишет:

однако всё же призамене, во всех 15ти строках, записи в регист на analogWrite, размер скетчя вырос на 430 байт

я вам уже третий раз говорю -не обязательно использовать analogWrite. Пишите через регистры напрямую. Только не надо городить свитч-кейс или массив ссылок - пишите каждый канал отдельно.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Если все же хочется упаковывать управления пинами в классах,то использовать лямда функции .

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

qwone пишет:

Если все же хочется упаковывать управления пинами в классах,то использовать лямда функции .

Зачем?

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

ЕвгенийП пишет:

qwone пишет:

Если все же хочется упаковывать управления пинами в классах,то использовать лямда функции .

Зачем?

Просто Пух, после автоматов, до них добрался. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

DetSimen пишет:

Просто Пух, после автоматов, до них добрался. 

А! Понятно :)