Сдвиговые регистры, нужна подсказка

Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Аватара пользователя
U235
Встал на лапы
Сообщения: 135
Зарегистрирован: Вт фев 21, 2012 20:42:26
Откуда: Санкт-Петербург, Россия, Земля

Re: Сдвиговые регистры, нужна подсказка

Сообщение U235 »

Аlex писал(а):Я так понял, count у Вас - кол-во передаваемых байт (т.б., грубо говоря, размер массива).
Тогда зачем эти все замудренные вычисления и лишние циклы с переменными и указателями ?

Не байт, а бит. Из-за этого и сложность.
А из наших труб идет необычный дым. Стой! Опасная зона! Работа мозга!...
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Сдвиговые регистры, нужна подсказка

Сообщение Аlex »

U235 писал(а):Не байт, а бит.
А почему тогда читаете из массива побайтно ?

Код: Выделить всё

 temp=*pdata;   // Берём очередной байт


В таком случае, если count будет отличен от 8, у Вас будут передаваться из каждого байта не все биты.
Вы берёте байт, затем передаёте кол-во бит, равное переменной j, в которую Вы пишите число count (кол-во бит).
Аватара пользователя
U235
Встал на лапы
Сообщения: 135
Зарегистрирован: Вт фев 21, 2012 20:42:26
Откуда: Санкт-Петербург, Россия, Земля

Re: Сдвиговые регистры, нужна подсказка

Сообщение U235 »

Вот исправленный вариант. Но Alex прав - он всё равно излишне сложный, ведь число светодиодов как правило кратно восьми.

Код: Выделить всё

void send_data (unsigned char pdata[], unsigned char count)
{
    unsigned char i, j, temp;

    j=0;
       
    for (i=count; i != 0;)
    {
        if (i > 7) j=8;
        else j=i ;
       
        i-=j;
       
        temp=*pdata;
       
        while (j)
        {
            if (t & 0x01) PORTD.0=1;
            else   PORTD.0=0;
   
            # asm("nop");
            PORTD.1=(CLK);
            # asm("nop");
            PORTD.1=~(CLK);
            # asm("nop");

            temp>>=1;
            j--;
        }
        pdata++;
    }

    PORTD.2=(Latch);
    # asm("nop");
    PORTD.2=~(Latch);   
}
А из наших труб идет необычный дым. Стой! Опасная зона! Работа мозга!...
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Сдвиговые регистры, нужна подсказка

Сообщение Аlex »

число светодиодов как правило кратно восьми
По этому, может быть, лучше тогда передавать кол-во байт ? ИМХО, будет логичнее.

Как то примерно так:

Код: Выделить всё

void send_data (unsigned char *pdata, unsigned char count){

while(count--){
char i;
   temp = pdata[count];
   for(i=0;i<8;i++){
      if (temp & 0x80)   PORTD.0 = 1;
      else               PORTD.0 = 0;
      temp << =1;

      PORTD.1=1;
      # asm("nop");
      PORTD.1=0;
      # asm("nop");
   }
}
PORTD.2=1;
# asm("nop");
PORTD.2=0;
}

SergeiSam
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Вс фев 18, 2007 14:09:34
Откуда: Воронеж
Контактная информация:

Re: Сдвиговые регистры, нужна подсказка

Сообщение SergeiSam »

Извините конечно, но попробывать сейчас не могу. Сразу дам еще информацию для размышления.
А если я захочу зажечь еще один светодиод и гнать его тоже, например через 2 не светящихся. Это будет уже возможно или надо еще подумать над кодом? :)
P.s. Попробую все это часа через 2. Заранее спасибо!
Аватара пользователя
U235
Встал на лапы
Сообщения: 135
Зарегистрирован: Вт фев 21, 2012 20:42:26
Откуда: Санкт-Петербург, Россия, Земля

Re: Сдвиговые регистры, нужна подсказка

Сообщение U235 »

Сделайте пару функций - устанавливать и сбрасывать бит по его номеру в массиве.
А из наших труб идет необычный дым. Стой! Опасная зона! Работа мозга!...
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Сдвиговые регистры, нужна подсказка

Сообщение Аlex »

А если я захочу зажечь еще один светодиод и гнать его тоже, например через 2 не светящихся.
Заполняйте массив, как душе угодно, и выводите его наружу.
SergeiSam
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Вс фев 18, 2007 14:09:34
Откуда: Воронеж
Контактная информация:

Re: Сдвиговые регистры, нужна подсказка

Сообщение SergeiSam »

Что-то я попробывал и опять ничего толком не вышло... (((
А можете просто попробывать объяснить весь этот чудодейственный код словами, понятными ))) Я сообразить что-то не могу
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Сдвиговые регистры, нужна подсказка

Сообщение Аlex »

Что конкретно Вы пробовали и что не получилось ? Покажите...

То, что мы приводили выше, - это функции вывода массива на внешние регистры.
Заполняйте массив данными с необходимой периодичностью и , с помощью этой ф-ии, выводите его.
В Вашем случае, размер массива должен быть = 4. Если будете использовать мой код, то в параметр pdata передавайте указатель на массив (он же - его имя), а в count - число 4. Ну и проверьте соответствие ПИНов и устанавливаемые им значения, я писал от балды...
SergeiSam
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Вс фев 18, 2007 14:09:34
Откуда: Воронеж
Контактная информация:

Re: Сдвиговые регистры, нужна подсказка

Сообщение SergeiSam »

Переработал код в такой вид. Да, пробывал и код Аlexа, работает. Это как раз из его сделано.
Вопрос такой теперь стал: Как вывести две переменных? Чтобы в начале например горел светодиод и в конце?
В этом коде сейчас включается 80 светодиод и 73. Я хочу зажечь 73 и 20. Как?

Код: Выделить всё

  void send_data  (){
char i;
      temp = pdata; 
     for(i=0;i<80;i++){ 

      if (temp & 0x80)   PORTD.0 = 1;
      else               PORTD.0 = 0;
      temp<<=1;

      PORTD.1=1;
      # asm("nop");
      PORTD.1=0;
      # asm("nop");
  }

PORTD.2=1;
# asm("nop");
PORTD.2=0;
}

void main(void)

pdata=0b10000001;
  while (1){
 if (!PINB.0) {
    send_data();
      }
{
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Сдвиговые регистры, нужна подсказка

Сообщение Аlex »

Код: Выделить всё

#define DATA_PIN        PORTD.0
#define CLK_PIN         PORTD.1
#define LATCH_PIN       PORTD.2


unsigned char buf[8];


/*****************************************************************/
void send_data (unsigned char *pdata, unsigned char count){

while(count--){
unsigned char i;
unsigned char temp = pdata[count];
    for(i=0;i<8;i++){
        if (temp & 0x80)   DATA_PIN = 1;
        else               CLK_PIN = 0;
    temp<<=1;

      CLK_PIN=1;
      Nop();
      CLK_PIN=0;
      Nop();
   }
}
LATCH_PIN=1;
Nop();
LATCH_PIN=0;
}
/*****************************************************************/


Пример использования:

Код: Выделить всё

buf[0] = 0b10000000;    // 1-ый регистр
buf[1] = 0b00000000;    // 2-ой регистр
buf[2] = 0b00000010;    // 3-ий регистр
buf[3] = 0b01000000;    // 4-ый регистр
buf[4] = 0b00000000;    // 5-ый регистр
buf[5] = 0b00001000;    // 6-ой регистр
buf[6] = 0b01000000;    // 7-ой регистр
buf[7] = 0b00000000;    // 8-ой регистр

send_data(buf, 8);
Ну вот, как то так... :write:
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Сдвиговые регистры, нужна подсказка

Сообщение Аlex »

Если включать и выключать побитно, то можно сделать так:

Код: Выделить всё

#define SET_BIT(bit_num)  (buf[(bit_num)/8] | (1<<(bit_num%8)))
#define CLR_BIT(bit_num)  (buf[(bit_num)/8] & ~(1<<(bit_num%8)))

.......................
.......................
.......................


SET_BIT(25);    // Включить 25-ый светодиод.
CLR_BIT(50);    // Выключить 50-ый светодиод.

Аватара пользователя
YS
Друг Кота
Сообщения: 7518
Зарегистрирован: Вс мар 29, 2009 22:09:05
Контактная информация:

Re: Сдвиговые регистры, нужна подсказка

Сообщение YS »

Господи, как все страшно. :)

Как заставить один светодиод зажигаться по очереди на всех 64 светодиодах?


Если задача только такая - достаточно один раз записать единицу, а потом только дергать SH_CP/ST_CP регистров. Если они соединены последовательно, единица будет двигаться сама.

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

***

Первое - эффективный код загрузки одного байта:

Код: Выделить всё

void ShiftData(uint8_t b)
{
  uint8_t mask;

  for (mask=0x80; mask; mask=(mask >> 1))
  {
    REG_PORT&=~REG_SHCP;

    if (b & mask)
    {
      REG_PORT|=REG_DSER;
    }
    else
    {
       REG_PORT&=~REG_DSER;
    }

    REG_PORT|=REG_SHCP;
  }
}

void SetData(void)
{
  REG_PORT&=~REG_STCP;
  REG_PORT|=REG_STCP;
}


Второе - макросы установки бита в буфере.

Код: Выделить всё

#define set_bit_by_num(BUF,BIT)    ((BUF)[(BIT) / 8]|=(1<<((BIT) % 8)))
#define clear_bit_by_num(BUF,BIT)    ((BUF)[(BIT) / 8]&=~(1<<((BIT) % 8)))


Надо 64 бита? Заводим массив на 8 байт.

Код: Выделить всё

uint8_t led_buffer[8];

void RefreshBuffer(void)
{
  uint8_t i;

  for (i=0; i<8; i++)
  {
    ShiftData(led_buffer[i]);
  }

  SetData();
}


Ну и вперед...

Код: Выделить всё

uint8_t i=0;

while (1)
{
  set_bit_by_num(led_buffer,i);
  RefreshBuffer();
  _delay_ms(100);
  clear_bit_by_num(led_buffer,i);
  RefreshBuffer();
  _delay_ms(100);

  i++;
 
  if (i>7)
    i=0;
}
Разница между теорией и практикой на практике гораздо больше, чем в теории.
SergeiSam
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Вс фев 18, 2007 14:09:34
Откуда: Воронеж
Контактная информация:

Re: Сдвиговые регистры, нужна подсказка

Сообщение SergeiSam »

Пока всем спасибо за подсказки. Последние два кода Alexa меня порадовали. Я их пытаюсь доработать для себя. Будут вопросы - я отпишусь, пока все ясно!
P.s Так же спасибо всем, кто подсказывал!
Аватара пользователя
Cyber-master
Нашел транзистор. Понюхал.
Сообщения: 193
Зарегистрирован: Пн апр 15, 2013 21:25:00
Откуда: Россия, Киров
Контактная информация:

Re: Сдвиговые регистры, нужна подсказка

Сообщение Cyber-master »

я так понял все получилось? нужно решение?
Придумать бы, ЧТО создавать, остальное - дело техники
Ответить

Вернуться в «Периферия»