Вывод переменной в два порта

Alex_Sk
Offline
Зарегистрирован: 06.01.2015

Что то я совсем затупил.

Есть Нано у которой на выходах D5 - D12 собран простой ЦАП на резисторах.

Эти выходы относятся к PORTB и PORTD.

Есть байтовая переменная которую надо вывести в ЦАП.

Если разбить переменную на биты и побитно выводить их в соответствующие разряды портов то все работает. А вот при попытке вывести переменную или в порт пишется не то что должно, или вообще не пишется. Пробовал по разному, но вот такой, к примеру, вариант вроде бы правильный и не работает как надо.


// младший разряд ЦАП в D5 Nano
// старший разряд ЦАП в D12 Nano
// порты настроены на выход
byte out1
PORTB = (PORTB & B11100000) | out1>>3;   // D5-D7
PORTD = (PORTD & B00011111) | out1<<5;   //D8-D12

Что не так?

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

Alex_Sk пишет:

Что не так?

Не так поставлена задача.

1.
Напишите законченный код строк на 10 (больше тут и не надо), который можно запустить. Код должен выводить в порты значение, затем читать уровни на пинах digitaRead'ом (ему плевать, что они "на выход"), и печатать их в монитор порта.

2.
Приведите полный код и копипасту с монитора порта.

3.
Напишите, что Вы ожидали увидеть на пинах и чем это отличается от того, что мы видим в мониторе порта.

Кстати, не удивлюсь, если при выполнении п.п. 2 и 3 Вы сами всё поймёте и снимете вопрос.

В том виде, как Вы написали абсолютно невозможно понять что у Вас не так, т.к. мы не знаем что Вы хотите получить на выходе.

nik182
Offline
Зарегистрирован: 04.05.2015

Не надо out сдвигать. Он и так чудно помещается на своиместа без сдвига.

Alex_Sk
Offline
Зарегистрирован: 06.01.2015
volatile byte U_now;

void setup() {

// Запуск АЦП в непрерывном режиме с прерываниями по готовности результата
  ADCSRB=0;            // Постоянное преобразование (Free Running mode)
  ADMUX=B01100000;     // +5В ИОН, 8-битный результат в регистре ADCH, чтение с пина A0
  ADCSRA=B11101011;    // АЦП включить, преобразование разрешить, автоматический режим, прерывания разрешить, предделитель 8 (9мкс на преобразование)

  Serial.begin(9600);
}

void loop() {
      unsigned long Timer_1 = millis()%1000;
      if ( !Timer_1 ) {
        Serial.print(" U_now ");
        Serial.println(U_now, BIN);
        PORTB = (PORTB & B11100000) | U_now>>3;
        PORTD = (PORTD & B00011111) | U_now<<5;
        Serial.print(" PORTB ");
        Serial.println(PORTB, BIN);
        Serial.print(" PORTD ");
        Serial.println(PORTD, BIN);
        Serial.println();
      }
}

  ISR(ADC_vect) {
     U_now = ADCH;
  } 

АЦП добавлен чтобы создать нагрузку как то приближенную к реальной.

Значения в портах не соответствуют выводимым в них.

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

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

Давайте Вы уберёте ADC, а своё u_now будете, например, из того же монитора порта вводить? Ну или хотя бы прерывания запретите перед строкой 17 и до строки 20.

А то сейчас, никто не может гарантировать, что, например, между строками 17 и 18 (или 18 и 19) Ваше U_now не поменяетеся. Понимаете проблему? Очень весело получится. напечатали в строке 17 одно, а работаем с другим. Или в строке 18 часть битов взяли от одного числа, а в строке 19 - уже от другого.

Alex_Sk
Offline
Зарегистрирован: 06.01.2015
volatile byte U_now;

void setup() {

// Запуск АЦП в непрерывном режиме с прерываниями по готовности результата
  ADCSRB=0;            // Постоянное преобразование (Free Running mode)
  ADMUX=B01100000;     // +5В ИОН, 8-битный результат в регистре ADCH, чтение с пина A0
  ADCSRA=B11101011;    // АЦП включить, преобразование разрешить, автоматический режим, прерывания разрешить, предделитель 8 (9мкс на преобразование)

  Serial.begin(9600);
}

void loop() {
      unsigned long Timer_1 = millis()%1000;
      if ( !Timer_1 ) {
        byte dumb = U_now;
        Serial.print(" U_now ");
        Serial.println(dumb, BIN);
        PORTB = (PORTB & B11100000) | dumb<<5;
        PORTD = (PORTD & B00011111) | dumb>>3;
        Serial.print(" PORTB ");
        Serial.println(PORTB, BIN);
        Serial.print(" PORTD ");
        Serial.println(PORTD, BIN);
        Serial.println();
      }
}

  ISR(ADC_vect) {
     U_now = ADCH;
  } 

На счет того, что U_now может изменяться пока выполняется вывод в порты я уже тоже подумал. Это и было причиной. В этом варианте оно фиксируется в переменной, а уже она потом выводится. И теперь стало работать правильно.

Спасибо!

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

Не за что.

Помните, я Вам говорил: "не удивлюсь, если при выполнении п.п. 2 и 3 Вы сами всё поймёте и снимете вопрос" - тот самый случай.

Это, кстати, общий подход - вычленить "чистую / рафинированную" проблему, отбросив всё лишнее. Пока это делаешь, часто проблема-то и исчезает. Ну и для вопроса на форуме это лучше сделать (выделить читстую проблему). А уж тогда задавать вопрос, если проблема не исчезла. Потому что очень часто, если проблему не выделать, то это значит заставлять заниматься выделением того, кто решил помочь.

Alex_Sk
Offline
Зарегистрирован: 06.01.2015

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