Считывание в прерывании

Добрый вечер.
НЕ могу никак сообразить , вроде все правильно и все должно работать , но что-то не то

тайминги

Спойлер


код

Спойлер

#include <util/atomic.h>
#define CLR(x,y) (x&=(~(1<<y)))
#define SET(x,y) (x|=(1<<y))
#define CLK_PIN PD2
#define SDO_PIN PD3


volatile uint16_t touch; 
uint16_t touchc;         
void setup() {
  Serial.begin(9600);
  pinMode(CLK_PIN, OUTPUT);
  pinMode(SDO_PIN, INPUT_PULLUP);
  EIMSK = (0 << INT3);
  EIFR = (1 << INTF3);
  EICRA = (1 << ISC31) | (1 << ISC30); 
  EIMSK = (1 << INT3); 
  sei();
}

void loop() {
  ATOMIC_BLOCK(ATOMIC_FORCEON) {
    touchc = touch;
  }
  if (touchc) {
       for (byte b=0; b<=15; b++) {
      if ((touchc>> b) & 1) {
        Serial.print(touch,HEX);      
      }
      
    }Serial.print(touch,HEX); 
   }
}

ISR(INT3_vect) {
  touch = 0;
  delayMicroseconds(100);
  for (byte i=0; i<=15; i++) {
    SET(PORTD, CLK_PIN);
    delayMicroseconds(50);
    touch |= (PORTD & (1 << PD3) ) ;
    CLR(PORTD, CLK_PIN);
    delayMicroseconds(50);
    }   
}

touch всегда равна 0 , ослик на PD3 показывает только первый импульс 93us , PD2 показывает всего 1 импульс вместо 16… не пойму почему он не дергает ногой , разве 50 микросекунд для него сильно быстро ?
ATMEGA 2560

Скажите плиз , где я опять торможу

Аксиома - > код в прерывании должен быть максимально коротким и тем более никаких delay.
Итог - переписывать все.
ЗЫ. А у вас какое образование? Мне кажется вы очень далеки от программирования :thinking: не всем оно даётся…

В pinMode надо передавать номер пина в Ардуино (от 0 до 69)
В SET надо передавать номер пина в порту (от 0 до 7)
И если в UNO они совпадают для порта D, то для 2560 по моему не совпадают.

У меня девайс не заработал , поэтому сделал отдельно не заморачиваясь пока на оптимальность …Сперва надо добиться чтоб он работал

Не могу понять, что делает стр.41?

  DDRD |= (1 << PD2);
  DDRD &= ~(1 << PD3);
  PORTD |= (1 << PD3);

исправил, но ситуация не поменялась

Собирает 2 байта значений из состояния бита PD3 (SDO) , которое там должно появляться по мере дергания клоком 16 раз

PIND - читаем байт порта

Да , Вы правы

Спойлер
#include <util/atomic.h>
#define CLR(x, y) (x &= (~(1 << y)))
#define SET(x, y) (x |= (1 << y))



volatile uint16_t touch;
uint16_t touchc;
void setup() {
  Serial.begin(9600);
  DDRD |= (1 << PD2);
  DDRD &= ~(1 << PD3);
  PORTD |= (1 << PD3);

  EIMSK &= ~(1 << INT3);
  EIFR = (1 << INTF3);
  EICRA |= (1 << ISC31) | (1 << ISC30);
  EIMSK = (1 << INT3);
  sei();
}

void loop() {
  ATOMIC_BLOCK(ATOMIC_FORCEON) {
    touchc = touch;
  }
  if (touchc) {
    for (byte b = 0; b <= 15; b++) {
      if ((touchc >> b) & 1) {
   //     Serial.print(touch, HEX);
      }
    }
    Serial.print(touch, HEX);
  }
}

ISR(INT3_vect) {
  touch = 0;
  delayMicroseconds(100);
  for (byte i = 0; i <= 15; i++) {
    SET(PORTD,PD2);
    delayMicroseconds(50);
 
    touch =((touch<<1)+((PIND >> PD3) & 1));
    CLR(PORTD, PD2);
    delayMicroseconds(50);
  }
}

Но это ничего не изменило

В цикле :
if(PIND & (1 << PD3)){
touch |= ((unsigned int)1 << i);
}

Да ,спасибо после изменения ослик нормально показывает…

А , нет изменило , все работает , яя просто еще не ту переменную в сериал выводил…
Спасибо

не сильно длинно ?




ISR(INT3_vect) {
  flg |= 1;
}
1 лайк

В приведенном в начале коде вы делаете нечто похожее на Soft Serial, В Soft Serial обработка приема байта ведется в прерывании. Просто надо учитывать в остальном коде эту особенность. Тем более, что вы писали, что это временное решение, на время экспериментов.
В прерывании может быть что угодно, если это не приводит к ошибкам работы остального кода.

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

ну в принципе можно и не в прерывании (имхо) если сделать ее атомарной, хотя я посчитал задержки , для моего кода даже на атомарность можно не заморачиваться…

Да, с флагом лучше. Я когда писал свой комментарий уже забыл исходный код, что вы сами формируете CLK, и что там допуск на времена огромный. Так что действительно в прерывании это делать нет смысла.

ну , не совсем …:slight_smile: надо уложиться в 32 ms . Но по меркам 2560 с минимум прерываний ,да довольно большой…