Attiny13+74595 функция записи байта в регистр

madalexfiesta
madalexfiesta аватар
Offline
Зарегистрирован: 30.03.2016

Верна ли функция для работы с 74595?

pin0=защелка, pin4=тактирование,pin3=dataPin

void set74595(byte b){
   //защелку снимаем
  PORTB &= ~(1<<0);
for (uint8_t i = 0; i < 8; i++)  {
  byte c=(b & (1 << (7 - i)));
  if(c==1){
    //если bit1 dataPin в HIGH
     PORTB |=(1<<3);
  }else{
    //иначе в LOW
     PORTB &=~(1<<3);
  }
  //тактирование
  PORTB |=(1<<4);
  PORTB &=~(1<<4);
  } 
  //защелку выставляем
  PORTB |= (1<<0);
}

 

madalexfiesta
madalexfiesta аватар
Offline
Зарегистрирован: 30.03.2016

Просто в Proteus семисигментник показывает хрень какую-то.

dhog1
Offline
Зарегистрирован: 01.03.2016

Ну может быть так?

	void set74595(byte b){
	   //защелку снимаем
	  PORTB &= ~(1<<0);
	for (uint8_t i = 0; i < 8; i++)  {
	  PORTB |=(1<<4);
	  if(b & (1 << (7 - i))){
	    //если bit1 dataPin в HIGH
	     PORTB |=(1<<3);
	  }else{
	    //иначе в LOW
	     PORTB &=~(1<<3);
	  }
	  //тактирование
	  PORTB &=~(1<<4);
	  }
	  //защелку выставляем
	  PORTB |= (1<<0);
	}

 

faeton
faeton аватар
Offline
Зарегистрирован: 21.03.2016

А вот писали бы по-человечески PORTB = PORTB and not(1 shl 4)  и сами понимали бы что написано. :)

dhog1
Offline
Зарегистрирован: 01.03.2016

Там все по-человечески написано, но может не очень "красиво".

Ошибка, конкретная, там где байт с, из которого в цикле "вырезается" бит (тестируется на "1") вовсе не ==1. Он, этот байт, равен степени 2-ки, если какой-то бит в проверяемом байте b не "0". Поэтому его (этот байт с) проверять нужно на "неравенство нулю".

Т.е. вместо if(c==1) написать if(c).

madalexfiesta
madalexfiesta аватар
Offline
Зарегистрирован: 30.03.2016

dhog1 пишет:

Ошибка, конкретная, там где байт с, из которого в цикле "вырезается" бит (тестируется на "1") вовсе не ==1. Он, этот байт, равен степени 2-ки, если какой-то бит в проверяемом байте b не "0". Поэтому его (этот байт с) проверять нужно на "неравенство нулю".

Вот верно сказал, товарищ! Действительно единицей там и не пахнет. Просто не силен  я пока в операциях с битами. Проверил сегодня в Intellig Idea. Действительно выдает циферки типа 100000, 10000, 1000, и только там где 0 - ноль остается нулем).

Просто читая о регистре 74595 я понял что запись идет побитно! Тобишь 100000 никак не один бит, соответственно предположил что формула типа x&(1<<i) "выдергивает" указанный бит(i) из байта(x). Тобишь это либо 1, либо 0.

Каким же образом циферки 1000 и т.п.  работают в формуле:

void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
{
  uint8_t i;

  for (i = 0; i < 8; i++)  {
    if (bitOrder == LSBFIRST)
      digitalWrite(dataPin, !!(val & (1 << i)));
    else  
      digitalWrite(dataPin, !!(val & (1 << (7 - i))));
      
    digitalWrite(clockPin, HIGH);
    digitalWrite(clockPin, LOW);    
  }
}

Насколько я понимаю digitalWrite(pin, x) - x может принимать значение либо 1, либо 0. Разве нет? Объясните пжлст) И да, что за двойное отрицание !!(val....    ?

 

madalexfiesta
madalexfiesta аватар
Offline
Зарегистрирован: 30.03.2016

faeton пишет:

А вот писали бы по-человечески PORTB = PORTB and not(1 shl 4)  и сами понимали бы что написано. :)

Блеснул умом) Это какой язык программирования? Delfi?  Что есть PORTB & !(1<<4)? Что смущает в моем переключении портов?)  Или от того что мы назовем презерватив резиновым изделием №2 что-то измениться в его функциональности?

Меня интересовала как раз проверка, но с этим мы разобрались.

dhog1
Offline
Зарегистрирован: 01.03.2016

(устало) ни с чем мы не разобрались, если у вас вопросы остались.

Самое главное - "читая о сдвиговом регистре 74HC595" ... там запись (обычно) идет байтами. Послали байт, двинули защелкой, чтобы пресловутый байт появился на выходных ножках регистра. Это все. Можно ли послать три бита? Можно. Но с байтом как-то осмысленнее получается.

Вы уперлись в _технику_ посылания байта. Там все просто - принимаете на вход байт, побитно его разбираете. Если текущий бит в единице, выставляете высокий уровень на пине. Вот так:

    (защелку открыть)

    for (i=0; i<8; i++) {

         if ( my_byte & (1<<i) ) _set_high_level;

        else _set_low_level;

     };

     (защелку закрыть)

ну и байт можно разбирать справо-налево (LSB, сначала младший бит) или слева-направо (MSB, сначала старший бит).  Тот бит, который вы пошлете первым, достигнет первым конца сдвигового регистра, его _младшего_ разряда, его "последней" ножки номер 7. Как правильно? Да леший его знает, отслеживайте логику, если взялись за ножки 74HC595 и что-то туда цепляете.

Как выставлять высокий-низкий уровень на ножке MCU? Ну в среде ардуино digitalWrite(номер_ноги, значение), где "значение" или "0" или что-то отличное от "0", а "номер ноги" соответствует распиновке платы ардуино. Например значение "1", соответствует константе HIGH, а может быть и _число_ (байт) "6", что будет принято как "HIGH" (т.е. не "0"). Можете напрямую, например если это ножка порта B номер 3 (отсчет от нуля), то что-то вроде PORTB |= (1<<4).

Вы себя будете чувствовать уверенно, когда разберетесь с этими чертовыми битовыми операциями. И не ругать faeton, который написал (зачем?) всего лишь  PORTB &= ~(1<<4), что у вас в исходном примере наблюдается.

P.S. Насчет двойного !! в примере - ну С знает много гитик, что не понимаю, тем не пользуюсь.