Нужна помощь со сдвиговым регистром 74HC595 через SPI

mira
Offline
Зарегистрирован: 07.06.2016

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

 

#include <SPI.h>

// Подключение сдвигового регистра 74HC595
// SH_CP - 11 пин 74HC595 на SCK (13 UNO, 52 MEGA)
// DS - 14 пин 74HC595 на MOSI (11 UNO, 51 MEGA)
// Q7'' - 9 пин 74НС595 к DS - 14 пину cледующего регистра 

#define SS_HC595 8  // Пин 12  ST_CP Синронизация ("защелкивание") выходов

#define num_releReg 2 // кол-во регистров
#define pins_releReg num_releReg * 8 // Общее кол-во пинов на всех регистрах
boolean outPins[pins_releReg]; // массив состояний пинов

class MyRegisters {
  public:
    void regWrite (int whichPin, byte wichState);
  
};

MyRegisters releReg;


void setup() {
  Serial.begin(9600);
  SPI.begin();
  pinMode(SS_HC595, OUTPUT);

}

void loop() {
  releReg.regWrite(4,1);

  releReg.regWrite(9,0);
  delay(1000);
 
  releReg.regWrite(4,0);

  releReg.regWrite(9,1);

  delay(1000);  


}

void MyRegisters::regWrite (int whichPin, byte wichState) {
  outPins[whichPin] = wichState;
  unsigned int d = 0;
  byte l = 1;
  for (byte i = 0; i <= 15; i++) {
    d = outPins[i] * l + d;
    l = l * 2;
  }

  digitalWrite(SS_HC595, HIGH); // включаем защелку для записи
  //SPI.transfer(d);
  // для двух регистров
  byte register1 = highByte(d);
  byte register2 = lowByte(d);
  SPI.transfer(highByte(register1));
  SPI.transfer(lowByte(register2));

  digitalWrite(SS_HC595, LOW); // выключаем защелку  
}

Во второй регистр ничего не пишется, хотя если переменной D присвоить значение 0b0000000011111111

то все выходы перейдут в логическую еденицу.

Помогите пожалуйста, что в коде не верно? регистры подключены каскадом по следующей схеме 

http://arduino.ru/Tutorial/registr_74HC595, за исключением 

// SH_CP - 11 пин 74HC595 на SCK (13 UNO, 52 MEGA)

// DS - 14 пин 74HC595 на MOSI (11 UNO, 51 MEGA)

 

Всю голову сломала, не понимаю где ошибка.

Или может есть какая готовая удобная библиотека для работы с этим регистром?

mira
Offline
Зарегистрирован: 07.06.2016

 

Схема всего что собрала

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

И не должно, ибо мудрствуете лукаво :) Будьте проще!

Что у Вас написано в строках 59-60? Какие могут быть lowByte и highByte, если register1 и register2 итак однобайтовые?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Строка 51 - умножаете на 2. Размерность переменной l какая? Что будет, если 15 раз умножить эту переменную на 2? И вообще - зачем такой монструозный код - можно сильно проще, сдвиговыми операциями:

void MyRegisters::regWrite (int whichPin, byte wichState)
{
  if(wichState)
      myState |= (1 << whichPin);
  else
     myState &= ~(1 << whichPin);
}

Заводите одну переменную myState в классе - и всё, заодно память сэкономите. Писать в сдвиговые тоже просто - есть функция shiftOut, она сделает чёрную работу за вас.

mira
Offline
Зарегистрирован: 07.06.2016

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

И не должно, ибо мудрствуете лукаво :) Будьте проще!

Что у Вас написано в строках 59-60? Какие могут быть lowByte и highByte, если register1 и register2 итак однобайтовые?

попробовала сделать int но не помогло.

 

DIYMan пишет:

Строка 51 - умножаете на 2. Размерность переменной l какая? Что будет, если 15 раз умножить эту переменную на 2? И вообще - зачем такой монструозный код - можно сильно проще, сдвиговыми операциями:

void MyRegisters::regWrite (int whichPin, byte wichState)
{
  if(wichState)
      myState |= (1 << whichPin);
  else
     myState &= ~(1 << whichPin);
}

Заводите одну переменную myState в классе - и всё, заодно память сэкономите. Писать в сдвиговые тоже просто - есть функция shiftOut, она сделает чёрную работу за вас.

я потихоньку делаю себе библиотеки и использую их, поэтому начала мудрить с ооп.

изучаю arduino.

у меня на даче изначально хватало 8 реле, но теперь у меня еще и теплица управляется с UNO + Raspberry (majordomo)

Позвольте спросить:  что в Вашем коде myState |= (1 << whichPin); или  myState &= ~(1 << whichPin); 

прошу не ругать я учу ардуино по гуглу и в Си я полный ноль. Но я легко обучаемая и память у меня хорошая :)

mira
Offline
Зарегистрирован: 07.06.2016

Ребят давайте напишем совместно универсальную классную библиотеку для этих регистров. Ведь для гуру делов на 20 минут.

допустим иницализация kakoeto_slovo (num_pin, num_reg);

num_pin - указываем номер пина для защелки на регистрах

num_reg - количество наших регистров в каскаде.

вызов kakoeto_slovo.regRwite(1,true/false)  - будет означать аналогично digitalWrite(1,HIGH/false) только выхода для регистра, а не ардуино.

Ведь иметь такую библиотеку на вооружении можно значительно расширить возможности любимого ардуино. 

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

mira пишет:

Ребят давайте напишем совместно универсальную классную библиотеку для этих регистров. Ведь для гуру делов на 20 минут.

Дык сколько ж можно - их уже девать некуда :)

Вот, например, до 8 регистров - http://playground.arduino.cc/Main/ShiftOutX 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

mira пишет:

Ребят давайте напишем совместно универсальную классную библиотеку для этих регистров. Ведь для гуру делов на 20 минут.

Зачем??? Если там всего кода - пара строк для работы с этими регистрами. Про shiftOut я вам уже писал, к слову. Зачем велосипед на велосипеде, если велосипед уже встроен в IDE?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

mira пишет:

Позвольте спросить:  что в Вашем коде myState |= (1 << whichPin); или  myState &= ~(1 << whichPin); 

Первая часть - устанавливает N-ный бит, вторая - снимает его. Можно вместо этого пользовать стандартные для Arduino IDE bitWrite, bitRead и иже с ними - посмотрите в документации, там всё описано. И тогда не придётся зачем-то для каждого бита держать аж целый байт в массиве значений, как это пытаетесь сделать вы.

Пробуйте, обязательно пробуйте: опыт - залог успеха. 

mira
Offline
Зарегистрирован: 07.06.2016

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

mira пишет:

Ребят давайте напишем совместно универсальную классную библиотеку для этих регистров. Ведь для гуру делов на 20 минут.

Дык сколько ж можно - их уже девать некуда :)

Вот, например, до 8 регистров - http://playground.arduino.cc/Main/ShiftOutX 

Сколько можно? покажите хотябы 3 если их так много. а не пишите пустые слова и не работающие ссылки.

 

Регистры подключены через SPI и использовать функцию ShiftOut это уже костыль.

Я же хотела записывать через  SPI.transfer.  для 1 регистра получается, но не для 2-ух. 

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

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

mira пишет:

Сколько можно? покажите хотябы 3 если их так много. а не пишите пустые слова и не работающие ссылки.

Что, случайно попавший в ссылку пробельчик не судьба убрать? Ну, ладно, сам убрал - http://playground.arduino.cc/Main/ShiftOutX

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

mira пишет:

Сколько можно? покажите хотябы 3 если их так много. а не пишите пустые слова и не работающие ссылки.

Регистры подключены через SPI и использовать функцию ShiftOut это уже костыль.

Я же хотела записывать через  SPI.transfer.  для 1 регистра получается, но не для 2-ух. 

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

Мы чего это вдруг хамить начинаем? Не умеем пользоваться интернетом и увидеть, что в ссылку лишний пробел в конце попал? Дело-то житейское. По остальному - вам уже указали на первые серьёзные огрехи вашего кода (оставим shiftOut в покое, фиг с ним). Исправляйте эти огрехи - а потом уже поговорим, раз такая манера общения с вашей стороны началась. Я вам указал, что у вас, как минимум, переполнение переменной из-за бездумного умножения в цикле. 

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

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013
#define LATCH      10
#define DAT        11
#define CLK        13

#define LATCH_On          PORTB = 1<<2
#define LATCH_Off         PORTB = 0<<2

#define SPI_OFF   SPCR = 0;
#define SPI_ON    SPCR = _BV(MSTR) | _BV(SPE);
#define SPI_WAIT  while (!(SPSR & _BV(SPIF)));

void setup(){
  pinMode(LATCH, OUTPUT);
  pinMode(DAT, OUTPUT);
  pinMode(CLK, OUTPUT);
  SPSR |= 1;	// 2x clock
}

void loop(){
  while(1){
    LATCH_Off;
    for(byte i=0; i<40; i++){
      spi_write(0xBA);
    }
    LATCH_On;
  }
}

void spi_write(byte c){
  SPI_ON;
  SPDR = c;
  SPI_WAIT;
  SPI_OFF;
}