более скоростной shiftOut?

whoim
Offline
Зарегистрирован: 03.11.2011

К примеру, цитата:

Для сравнения быстродействия:
Ниже приведены команды, которые при понимании логики работы программы в 99% случаев делают одно и то же.
digitalWrite(5,HIGH); // 72 такта
DDRD |=(1<<PIN5); // 2 такта 

А писал ли кто нибудь аналог shiftOut, который реально быстрее работает? Особенно когда надо последовательно вызывать его 8 раз?

whoim
Offline
Зарегистрирован: 03.11.2011

Нашел так

void ShiftOutByte (unsigned char Data)
{
    int Bit;
    for(Bit=0; Bit < 8; ++Bit)
    {
        while(ClkPin == HIGH);
        while(ClkPin == LOW);
        DataPin = Data & 1;
        Data >>= 1;
    }
}

 

whoim
Offline
Зарегистрирован: 03.11.2011

 вот еще

#include <avr/io.h> 

//                      Access bits like variables 
struct bits { 
  uint8_t b0:1; 
  uint8_t b1:1; 
  uint8_t b2:1; 
  uint8_t b3:1; 
  uint8_t b4:1; 
  uint8_t b5:1; 
  uint8_t b6:1; 
  uint8_t b7:1; 
} __attribute__((__packed__)); 
#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin) 


//                      Hardware definitions 

#define SER             SBIT( PORTB, 0 ) 
#define SER_DDR         SBIT( DDRB,  0 ) 
#define SCK             SBIT( PORTB, 1 ) 
#define SCK_DDR         SBIT( DDRB,  1 ) 
#define RCK             SBIT( PORTB, 2 ) 
#define RCK_DDR         SBIT( DDRB,  2 ) 


void spi_wr8( uint8_t val )     // write a byte to software SPI 
{ 
  for( uint8_t i = 8; i; i-- ){ 
    SCK = 0; 
    SER = 0; 
    if( val & 0x80 )            // MSB first 
      SER = 1; 
    val <<= 1; 
    SCK = 1; 
  } 
} 


void spi_wr16( uint16_t val )   // write to two cascaded 74HC595 
{ 
  RCK = 0; 
  spi_wr8( val >> 8 ); 
  spi_wr8( val ); 
  RCK = 1; 
}

 

и еще

void setup(){ 
  DDRB = B11111000; //set digit pins_8-12 as outputs 
  PORTB=B10000000; //set LATCH pin_8 HIGH 
  for (int i=0; i<8; i++) 
  { //here is a simple condition to see if this code does work 
    if (i MODULO 2==0) PORTB |= (1<<1); //set DATA pin_9 HIGH if condition TRUE 
    else PORTB &= ~(1<<1); //set DATA pin_9 LOW if condition FALSE 
    PORTB |= (1<<4); //set CLOCK pin_12 HIGH 
    PORTB &= ~(1<<4); //set CLOCK pin_12 LOW 
  } 
  PORTB=B00000000; //set LATCH pin_8 LOW 
} 
void loop(){}

 

whoim
Offline
Зарегистрирован: 03.11.2011

Заработало это:

/74hc595 wiring
//Pin connected to ST_CP of 74HC595
#define _latch 8
#define _latchPORTB _latch - 8
//Pin connected to SH_CP of 74HC595
#define _clock 12
#define _clockPORTB _clock - 8
//Pin connected to DS of 74HC595
#define _data 11
#define _dataPORTB _data - 8


...
//shiftOut
bitClear(PORTB,_latchPORTB);
shiftOut2(_data,_clock,registers[7]);
shiftOut2(_data,_clock,registers[6]);
shiftOut2(_data,_clock,registers[5]);
shiftOut2(_data,_clock,registers[4]);
shiftOut2(_data,_clock,registers[3]);
shiftOut2(_data,_clock,registers[2]);
shiftOut2(_data,_clock,registers[0]);
shiftOut2(_data,_clock,registers[1]);
bitSet(PORTB,_latchPORTB);
...

void shiftOut2(int my_data, int my_clock, byte myDataOut) {
bitClear(PORTB,_dataPORTB);
for (int i=7; i>=0; i--) {
bitClear(PORTB,_clockPORTB);
if ( bitRead(myDataOut,i) == 1)
bitSet(PORTB,_dataPORTB);
else
bitClear(PORTB,_dataPORTB);
bitSet(PORTB,_clockPORTB);
bitClear(PORTB,_clockPORTB);
}
digitalWrite(my_clock, 0);
}

ctimas
ctimas аватар
Offline
Зарегистрирован: 13.12.2011

Экспериментирую, с твоей функцией, а можешь вставить весь скетч? а то у меня чето не работает....

whoim
Offline
Зарегистрирован: 03.11.2011

чуть позже выложу

whoim
Offline
Зарегистрирован: 03.11.2011

 когда то делал так

/***************************
* LED RGB controller       *
* atmega328 & 8pcs 74hc595 *
* by whoim@mail.ru         *
****************************/
#include <FlexiTimer2.h>

//74hc595 wiring
//ST_CP на 74HC595
#define _latch 8
#define _latchPORTB _latch - 8
//SH_CP на 74HC595
#define _clock 12
#define _clockPORTB _clock - 8
//DS на 74HC595
#define _data 11
#define _dataPORTB _data - 8
//информационный светодиод
#define _boot_led 13
//настройки матрицы
#define _FQ 40 //частота pwm_led 1, 1.0/1000000
#define _ROWS 16 //число строк в матрице (аноды)
#define _COLUMNS 48 //число столбцов в матрице (катоды)
boolean data[_ROWS][_COLUMNS]; //массив состояния светодиодов для вывода
int j=0; //храним строки между циклами
//настройки связи
#define _serial_speed 115200 //скорость компорта

//настройки при запуске
void setup() { 
  //настройка таймера
  FlexiTimer2::set(_FQ, print); // 500ms period
  FlexiTimer2::start();
  //установка портов 74hc595
  pinMode(_latch, OUTPUT);
  digitalWrite(_latch, LOW);
  pinMode(_clock, OUTPUT);
  digitalWrite(_clock, LOW);
  pinMode(_data, OUTPUT);
  digitalWrite(_data, LOW);
  //установка портов светодиода
  pinMode(_boot_led, OUTPUT);
  digitalWrite(_boot_led, LOW);
  //инициализация Serial
  Serial.begin(_serial_speed);
  //сигнал к старту
  for (int j=1; j <=5; j++) {
     digitalWrite(_boot_led, HIGH);
     delay(80);
     digitalWrite(_boot_led, LOW); 
     delay(80);
  }
  digitalWrite(_boot_led, HIGH);
}

//цикл главной программы
void loop() {

} //loop

//функция, вызываемая по таймеру
void print() {
    //отрисовка матрицы
  //цикл по строкам (аноды)
    byte registers[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //обнуляем регистры
    //задаем нужный анод
    if(j < 8) bitSet(registers[0], j);
    else bitSet(registers[1], j-8);
    for (int k=0; k < _COLUMNS; k++)
    //цикл по столбцам (катоды)
        if (data[j][k]) {
          //задаем катоды  
          if (k < 8) bitSet(registers[2], k);
          else if (k>=8 &&  k<16) bitSet(registers[3], k-8);
          else if (k>=16 && k<24) bitSet(registers[4], k-16);
          else if (k>=24 && k<32) bitSet(registers[5], k-24);
          else if (k>=32 && k<40) bitSet(registers[6], k-32);
          else if (k>=40 && k<48) bitSet(registers[7], k-40);
        }
        //shiftOut
        bitClear(PORTB,_latchPORTB);
        shiftOut2(_data,_clock,registers[7]);
        shiftOut2(_data,_clock,registers[6]);
        shiftOut2(_data,_clock,registers[5]);
        shiftOut2(_data,_clock,registers[4]);
        shiftOut2(_data,_clock,registers[3]);
        shiftOut2(_data,_clock,registers[2]);
        shiftOut2(_data,_clock,B00000000);
        shiftOut2(_data,_clock,B00000000);
        bitSet(PORTB,_latchPORTB);
        //shiftOut
        bitClear(PORTB,_latchPORTB);
        shiftOut2(_data,_clock,registers[7]);
        shiftOut2(_data,_clock,registers[6]);
        shiftOut2(_data,_clock,registers[5]);
        shiftOut2(_data,_clock,registers[4]);
        shiftOut2(_data,_clock,registers[3]);
        shiftOut2(_data,_clock,registers[2]);
        shiftOut2(_data,_clock,registers[0]);
        shiftOut2(_data,_clock,registers[1]);
        bitSet(PORTB,_latchPORTB);
        //корректировка x,y
        j++;
        if (j == _ROWS){
           j= 0; 
        }
}

void shiftOut2(int my_data, int my_clock, byte myDataOut) {
  bitClear(PORTB,_dataPORTB);
  for (int i=7; i>=0; i--)  {
    bitClear(PORTB,_clockPORTB);
    if ( bitRead(myDataOut,i) == 1)
      bitSet(PORTB,_dataPORTB);
    else
      bitClear(PORTB,_dataPORTB);
    bitSet(PORTB,_clockPORTB);
    bitClear(PORTB,_clockPORTB);
  }
  bitClear(PORTB,_clockPORTB);
}

//событие: данные в порт Serial
void serialEvent() {
  //if(testmode) testmode = false; //сбросим тестовый режим если есть данные
  int x = 0; //переменные для
  int y = 0; //сопоставления с массивом данных
  while (Serial.available()) {
    byte _in = (byte)Serial.read();
    for (int j=0; j<8; j++) {
      data[x][y]= bitRead(_in, j); //формируем массив данных
      y++;
      if(y == _COLUMNS) {
        y=0;
        x++;
        if (x == _ROWS) {
          Serial.flush();
        }
      } //if max columns
    } //bits cycle
  delay(4);
  } //while serial active
  Serial.println("done");
}

функцию шифтаут можно еще лучше

//формирование потока на регистр из одного байта
void shiftout(char _byte){
	//цикл по битам
	for (char i=0; i<8; i++) {
		if(_byte&(1<<i)) PORTB |= (1<<DATA);
		else PORTB &= ~(1<<DATA);
		//обозначим clock
		PORTB |= (1<<SH_CP);
		PORTB &= ~(1<<SH_CP);
	}
	
}

 

leshak
Offline
Зарегистрирован: 29.09.2011

 Возможно "не в тему". Но можно еще посмотреть в сторону SPI. Вообщем-то логика сдвиговых регистров совпадает с ней. Так что можно попробовать воспользоватся "аппаратными" возможностями. И выводить простым SPI.transfer сразу байт . Не знаю на какой скорости передает аппаратный, но шансы что "выйдет быстрее", за счет того что сам процессор будет меньше загружен - имеются. Да и скетч "красивше" получится.

Вот тут, можно поглядеть как это примерно делается.

whoim
Offline
Зарегистрирован: 03.11.2011

 leshak, той функции что я выкинул последней, хватает по быстродействию ЗА глаза в огромным запасом..

leshak
Offline
Зарегистрирован: 29.09.2011

leshak пишет:

 Возможно "не в тему". Но можно еще посмотреть в сторону SPI.

Сорри. Не доглядел. Выше вы уже рассматривали этот вариант. Но в любом случае, думаю, ссылочка будет полезной. Там более "ардуинистая" работа с SPI.

leshak
Offline
Зарегистрирован: 29.09.2011

whoim пишет:

 leshak, той функции что я выкинул последней, хватает по быстродействию ЗА глаза в огромным запасом..

Ну хватает, так хватает. Хорошо :) Я же просто "упомянул" еще один вариант (и то слегка "мимо кассы"). Может кому-нибудь он "проще покажется", или, когда важней память - пригодится.

whoim
Offline
Зарегистрирован: 03.11.2011

 а вот по поводу память (не влеш а оперативки) - это очень интересно. Я уже сталкивался с нехваткой (не в шифтауте), начал читать.. макросы и тд..

leshak
Offline
Зарегистрирован: 29.09.2011

 Ну, по моим наблюдениям, самым быстрым "пожирателем памяти" являются всякие Serial.println("Bla-bla"); и проч. строки. Так что самую ощутимую экономию дает переход  на PROGMEM, PSTR . Да и "поменять" довольно быстро, особо не "корежа логику".

ctimas
ctimas аватар
Offline
Зарегистрирован: 13.12.2011

Посидел, побаловался, есть интересное наблюдение:
делал для своего куба,
основной код скетча:

#define _data 2
#define _clock 4
#define _lat 3

byte matrix[8][8];

byte i,j,k, x, y, z;
byte pause;
void setup(){
  pinMode(_data, OUTPUT);
  pinMode(_clock, OUTPUT);
  pinMode(_lat, OUTPUT);
  blankMatrix();
  matrix[1][1] = 4;
}

void loop(){
  effectRandomeMagik();
  writeMatrix();
}

void blankMatrix(){
  for(i = 0; i < 8; i++){
    for(j = 0; j < 8; j++){
      matrix[i][j] = 0;
    }
  }
}


/*
 эффект хаоса
 */
void effectRandomeMagik(){
  pause = 10;
  x = random(0,8);
  y = random(0,8);
  z = random(0,8);
  if(bitRead(matrix[z][x], y) == 1)
    bitClear(matrix[z][x], y);
  else
    bitSet(matrix[z][x], y);
}

 

И собственно функция которая выводит информацию на куб

так она работает:

void writeMatrix(){
  for(i = 0; i < 8; i++){
    bitClear(PORTD, _lat);
    for(j = 0; j < 8; j++){
      for(k = 0; k < 8; k++){
        bitClear(PORTD, _data);
        if(bitRead(matrix[i][j], k) == 1)
          bitSet(PORTD, _data);
        bitSet(PORTD, _clock);
        bitClear(PORTD, _clock);
      }
    }
    for(j = 0; j < 8; j++){
      bitClear(PORTD, _data);
      if(i == j){
        bitSet(PORTD, _data);
      }
      bitSet(PORTD, _clock);
      bitClear(PORTD, _clock);
    }
        digitalWrite(_lat, HIGH);
        digitalWrite(_lat, LOW);
    //bitSet(PORTD, _lat);
    //bitClear(PORTD, _lat);
  }
}

А вот так сигнал на защелку идет не всегда:
 

void writeMatrix(){
  for(i = 0; i < 8; i++){
    bitClear(PORTD, _lat);
    for(j = 0; j < 8; j++){
      for(k = 0; k < 8; k++){
        bitClear(PORTD, _data);
        if(bitRead(matrix[i][j], k) == 1)
          bitSet(PORTD, _data);
        bitSet(PORTD, _clock);
        bitClear(PORTD, _clock);
      }
    }
    for(j = 0; j < 8; j++){
      bitClear(PORTD, _data);
      if(i == j){
        bitSet(PORTD, _data);
      }
      bitSet(PORTD, _clock);
      bitClear(PORTD, _clock);
    }
    //  digitalWrite(_lat, HIGH);
    //  digitalWrite(_lat, LOW);
    bitSet(PORTD, _lat);
    bitClear(PORTD, _lat);
  }
}


Я бы даже сказал что крайне редко, причем тактовый сигнал и сигнал данных идут нормально, в рабочем состоянии скорость порадовала по сравнению с прошлой версией на digitalWrite.
для справки: функция 8 раз записывает 64 бита данных о этаже и потом 8 бит о том какой этаж зажигать
 

whoim
Offline
Зарегистрирован: 03.11.2011

 не используй bitset/write, сразу меняй битовыми операциями на PORTD

установить PORTD |= (1<<NUMPIN)

снять PORTD &= ~(1<<NUMPIN)

NUMPIN = PD0..PD7 или 0..7
где кто в даташите

whoim
Offline
Зарегистрирован: 03.11.2011

 

01
//формирование потока на регистр из одного байта
02
void shiftout(char _byte){
03
    //цикл по битам
04
    for (char i=0; i<8; i++) {
05
        if(_byte&(1<<i)) PORTB |= (1<<DATA);
06
        else PORTB &= ~(1<<DATA);
07
        //обозначим clock
08
        PORTB |= (1<<SH_CP);
09
        PORTB &= ~(1<<SH_CP);
10
    }
11
     
12
}

выдрано из рабочего проекта, быстрее некуда) только аппаратно наверно, хз

тут нет защелки, защелка СНИМАЕТСЯ перед посылками шифтаут и ставится после того как все посылки ушли. Задержек никаких нет у меня, все пашет. Кондюка на защелке нет. тестилось на 1 регистра и на 9 штуках.

whoim
Offline
Зарегистрирован: 03.11.2011

 да, у тебя ошибка. Снимай защелку вначале работы. 

ctimas
ctimas аватар
Offline
Зарегистрирован: 13.12.2011

whoim пишет:

 

//формирование потока на регистр из одного байта
void shiftout(char _byte){
   //цикл по битам
    for (char i=0; i<8; i++) {
        if(_byte&(1<<i)) PORTB |= (1<<DATA);
        else PORTB &= ~(1<<DATA);
        //обозначим clock
        PORTB |= (1<<SH_CP);
        PORTB &= ~(1<<SH_CP);
    }
}

выдрано из рабочего проекта, быстрее некуда) только аппаратно наверно, хз

тут нет защелки, защелка СНИМАЕТСЯ перед посылками шифтаут и ставится после того как все посылки ушли. Задержек никаких нет у меня, все пашет. Кондюка на защелке нет. тестилось на 1 регистра и на 9 штуках.

Сегодня попробую обязательно.

whoim пишет:

да, у тебя ошибка. Снимай защелку вначале работы.

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

 

whoim
Offline
Зарегистрирован: 03.11.2011

ctimas пишет:

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


digitalWrite(_lat, HIGH);
digitalWrite(_lat, LOW);

вторую строчку убери, проверь правильность соединений

whoim
Offline
Зарегистрирован: 03.11.2011

в динамической индикации принято делать так:

зажигаем секцию
задержка (оч малая), если не по таймеру
тушим секцию (катоды/строки/этаж)
идем в начало цикла 

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

ctimas
ctimas аватар
Offline
Зарегистрирован: 13.12.2011

эм... как я понимаю логику работы регистров 74HC595N(скорее всего далее всем извесная вода) то у них есть пин данных, пин такта, и пин защелки, сам в себе этот регистр состоит из 8 элементов в которых по 2 D-триггера, собсно в первый триггер(в каждом элементе) мы загоняем при помощи пина данных и тактового. Затем когда информация записана в первые триггеры, сигналом на дащелку я синхронизирую значения на выходе для первого и второго триггера в каждом элементе, и могу продолжать дальше записывать в первый. т.е. состояние второго триггера меняется только тогда, когда подана логическая единица на пин защелки, как только убираем логическую единицу состояния на выходе регистра замирают.

исходя из этого я, используя тактовый пин и пин данных записываю в регистр 64+8 бита данных о том какие диоды и на каком этаже зажеч и в конце даю короткий сигнал на защелку чтобы перевести данные из внутренних регистров на внешние, и пока горит этаж я могу записать следующие 72 бита о следующем этаже, поэтому я делаю короткий сигнал на защелку в конце первого цикла. получается что диоды горят до тех пор пока не подготовится следующая порция информации о следующем этажеи быстро меняются сигналом на защелку...
 

и всетаки мне не понятно почему
 

digitalWrite(_lat, HIGH);
digitalWrite(_lat, LOW);



Работает а

 

	    bitSet(PORTD, _lat);
	    bitClear(PORTD, _lat);

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

 

ctimas
ctimas аватар
Offline
Зарегистрирован: 13.12.2011

нашел в чем был косяк.... в конденсаторе на 0.1мкФ на защелке.... он все и портил, выпоял и все как часики работает)))) 2whoim еще вы мне говорили что не нужно....но я всеже один распаял, видимо при тех скоростях что сейчас работает он не успевал разряжатся....

скорость просто радует))) спасибо)))

ctimas
ctimas аватар
Offline
Зарегистрирован: 13.12.2011

Отчитываюсь:

логика кода одна и таже, до оптимизации:
скетч:

#define clock 3 //синхро контакт
#define reset 4 // контакт сброса
#define data 2 // контакт данных

boolean matrix[9][9][9]; // массив который является внутренним

byte i,j,k,x,y,z; // переменные для циклов

void setup() // функция установки начальных праметров
{
  pinMode(clock, OUTPUT);
  pinMode(reset, OUTPUT);
  pinMode(data, OUTPUT);

  blankMatrix();
}

void loop()
{
  effectRandomeMagik();
  writeMatrix(); //выводим массив на куб
}

/*
 эффект хаоса
 */
void effectRandomeMagik(){
  //pause = 10;
  x = random(0,8);
  y = random(0,8);
  z = random(0,8);
  matrix[z][x][y] = !matrix[z][x][y];
}

void blankMatrix(){
  for(i = 0; i < 8; i++){
    for(j = 0; j < 8; j++){
      for(k = 0; k < 8; k++){
        matrix[i][k][j] = false;
      }
    }
  }
}


void writeMatrix(){ // функция которая отображает внутренний массив на кубе
  digitalWrite(clock, LOW);
  for(i = 0; i < 8; i++){ // цикл по этажам  координата Z 
    digitalWrite(reset, LOW);
    for(j = 0; j < 8; j++){ //цикл по рядам(координата Y)
      // сбрасываю синхросигнал 
      // цикл по строкам(координата X)
      for(k = 0; k < 8; k++){
        // сбрасываю сигнал на выходе данных
        digitalWrite(data, LOW);
        //проверка на истину
        if(matrix[i][k][j] == true){
          // если истина то даю логическую 1 на выход
          digitalWrite(data, HIGH);
        }
        if(matrix[i][k][j] == true){
        }
        else{
        }
        digitalWrite(clock, HIGH);
        digitalWrite(clock, LOW);
      }          //сбрасываю сигнал по координате Z 
    }
    for(j = 0; j < 8; j++ ){
      digitalWrite(data, LOW);
      if(i == j){
        digitalWrite(data, HIGH);
      }
      digitalWrite(clock, HIGH);
      digitalWrite(clock, LOW);
    }
    digitalWrite(reset, HIGH); //зажигаю ряд(этаж)
    digitalWrite(reset, LOW); //гашу ряд(этаж)
  }
}

ссылка на видео: youtu.be/wBigrc10NPc

 

после оптимизации:

скетч:

#define _data 2
#define _clock 4
#define _lat 3

byte matrix[8][8];

byte i,j,k, x, y, z;
byte pause;
void setup(){
  pinMode(_data, OUTPUT);
  pinMode(_clock, OUTPUT);
  pinMode(_lat, OUTPUT);
  blankMatrix();
  matrix[1][1] = 4;
}

void loop(){
  effectRandomeMagik();
  writeMatrix();
}

void blankMatrix(){
  for(i = 0; i < 8; i++){
    for(j = 0; j < 8; j++){
      matrix[i][j] = 0;
    }
  }
}


/*
 эффект хаоса
 */
void effectRandomeMagik(){
  pause = 10;
  x = random(0,8);
  y = random(0,8);
  z = random(0,8);
  if(bitRead(matrix[z][x], y) == 1)
    bitClear(matrix[z][x], y);
  else
    bitSet(matrix[z][x], y);
}

void writeMatrix(){
  for(i = 0; i < 8; i++){
    for(j = 0; j < 8; j++){
      for(k = 0; k < 8; k++){
        PORTD &= ~(1 << _data);
        if(bitRead(matrix[i][j], k) == 1)
          PORTD |= (1 << _data);
        PORTD |= (1 << _clock);
        PORTD &= ~(1 << _clock);
      }
    }
    for(j = 0; j < 8; j++){
      PORTD &= ~(1 << _data);
      if(i == j){
        PORTD |= (1 << _data);
      }
      PORTD |= (1 << _clock);
      PORTD &= ~(1 << _clock);
    }

    PORTD |= (1 << _lat);
    PORTD &= ~(1 << _lat);
  }
}


ссылка на видео: youtu.be/Le9mrlMyOyQ

Я думаю результат на лицо, даже если посмотреть что у меня не самый лучший фотик для въемки видео но разница очевидна.

whoim
Offline
Зарегистрирован: 03.11.2011

 Видео посмотрю из дома, на работе дорогой интернет.

Я работаю с регистром так.
1) Ноль на защелку - регистр доступен для записи.
2) Посылки по количеству регистров (всех микросхем). Ставлю дата и дергаю клок. Посылка - байт на микросхему.
3) Когда все посылки ушли, защелку в единичку. Выходы микросхем в этот момент меняются в соответствии с посылками.

первая посылка попадает в "дальнюю" микросхему. Последняя - в "ближнюю".

whoim
Offline
Зарегистрирован: 03.11.2011

 PORTD |= (1 << _lat);
66
PORTD &= ~(1 << _lat);

 

вы по прежнему дергаете защелку туда-сюда.

В начале записи сняли, в конце поставили. Все!

ctimas
ctimas аватар
Offline
Зарегистрирован: 13.12.2011

whoim пишет:

 PORTD |= (1 << _lat);
66
PORTD &= ~(1 << _lat);

 

вы по прежнему дергаете защелку туда-сюда.

В начале записи сняли, в конце поставили. Все!

Эм.. не вижу разницы.... в начале цикла её в 0 поставить или в конце передернуть.... просто в вашем случае получается что после того как функция отработала то на защелке останется 1 а в моем случае останется 0...

whoim
Offline
Зарегистрирован: 03.11.2011

 так правильнее логически, как задумано производителем. Мало ли что вылезет - пока защелка снята, регистры ждут, может мусор прийти например. Или мало времени будет чтобы сработала защелка.

ctimas
ctimas аватар
Offline
Зарегистрирован: 13.12.2011

понял)))) поправлю)))) пасибо за инфу)))

whoim
Offline
Зарегистрирован: 03.11.2011

 Да за что :) когда я уже доберусь до своего куба..
Хотя у меня будет не куб, будет 3D сфера )

ctimas
ctimas аватар
Offline
Зарегистрирован: 13.12.2011

мммм сфера тоже прикольно, как то видел на ютубе))) я вот подумываю сделать еще один тока из белых диодов в дите полусферы на потолок как люстру)))))