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

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

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

Сообщение SergeiSam »

Всем доброго времени суток.
Пытаюсь сделать бегущий огонёк, или просто вывод на светодиоды.
Задача такова: есть 8 сдвиговых регистров 74HC595 (8 - это не предел, хочу 20 поставить), соединенных цепочкой, к ним подключены 64 светодиода. Мк - Атмега8.
Как заставить один светодиод зажигаться по очереди на всех 64 светодиодах????
У меня получается только 32 светодиода пройти (по одному зажигать), дальше цепочка почему-то дублируется (вспыхивает еще один светодиод и бежит уже с №33 по 64).

Если можно, то приведите кусок кода. Пишу в CVAVR.
Файл прошивки и протеуса пригалаю для наглядности. Кнопка S1 должна быть нажата.
p.s. В протеусе все страшно ))

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

 
    #define DATA 1  // Подключаем к порту PD0 ножку данных сдвигового регистра
    #define CLK 0    // Подключаем к порту PD1 ножку тактовых импульсов сдвигового регистра
    #define Latch 0  // Подключаем к порту PD2 ножку защёлки сдвигового регистра   
long int z, a, x=0;

void send_data (long int data){
    unsigned char i=0;
       
      for (i=0;i<32;i++){ 
     // Выставляем данные на PD0   
          if ((data&0x80000000)==0x00) {PORTD&=~(DATA);}
              else   PORTD.0=(DATA);         
   
        # asm("nop");
         PORTD.1=(CLK); // Импульс на CLK
        # asm("nop");
         PORTD.1=~(CLK);
        # asm("nop");
         data=(data<<1);   
                  }
         PORTD.2=(Latch); // Импульс на Latch clock
   # asm("nop");
    PORTD.2=~(Latch);   
       }

void main(void)
{
while (!PINB.1) {
      x++;
      if (x==32) {x=0;};
     z=0b00000001;
    delay_ms (40);
     send_data (z<<x);};
}

Вложения
Sdvigovie_registri.rar
(20.8 КБ) 201 скачивание
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

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

У меня получается только 32 светодиода пройти
Может из-за этого

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

for (i=0;i<32;i++)
?
Аватара пользователя
zero648
Вымогатель припоя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

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

Сообщение zero648 »

И здесь тоже проверка на 32:

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

      if (x==32) {x=0;};
...
     send_data (z<<x);};

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

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

Сообщение SergeiSam »

if (x==32) {x=0;};
...
send_data (z<<x);};

Этот if обнуляет значение переменной Х, которая сдвигает бит. Ну что бы огонек бежал.


for (i=0;i<32;i++)
Вот тут я думаю вся проблема. Я привел рабочий код для 32 светодиодов.
Если я ставлю число более 32, то у меня вообще перестает все работать....

if (x==32) {x=0;};
...
send_data (z<<x);};
Меняю тут числа, ставлю больше, то также счет идет (например до 32), а потом светодиод погасает, и видно, что он перечисляет дальше (задержка получается).

Может проблема вот в этом куске кода:
if ((data&0x80000000)==0x00) {PORTD&=~(DATA);}
else PORTD.0=(DATA);
Не проходит проверку может? Как правильно написать?
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

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

Может в этом
long int data
?
Аватара пользователя
ChipKiller
Сверлит текстолит когтями
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

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

Сообщение ChipKiller »

Если я ставлю число более 32, то у меня вообще перестает все работать...
.. так и должно быть, тип long - это 2**32, так что лучше вместо send_data (long int data) указатель на строку значений send_data (char* data)
Alex опередил :)
SergeiSam
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Вс фев 18, 2007 14:09:34
Откуда: Воронеж
Контактная информация:

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

Сообщение SergeiSam »

ChipKiller писал(а):
Если я ставлю число более 32, то у меня вообще перестает все работать...
.. так и должно быть, тип long - это 2**32, так что лучше вместо send_data (long int data) указатель на строку значений send_data (char* data)
Alex опередил :)


А что значит звездочка вот тут: send_data (char* data)

Изменил то, что сказали на char, прога перестала зажигать светодиоды.... ((( Еще идеи или я не туда поставил char?
Приведите мой код, только с исправлениями, пожалуйста! )
Последний раз редактировалось SergeiSam Пн авг 13, 2012 19:21:30, всего редактировалось 1 раз.
Аватара пользователя
Ser60
Друг Кота
Сообщения: 3780
Зарегистрирован: Ср дек 24, 2008 09:58:58

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

Сообщение Ser60 »

Если у Вас все работает на первых 32 светодиодах, то на расширение этой последовательности до 64, после засылки первых 32 бит данных зашлите в регистры 32 нуля. Таким образом первые 32 бита последовательности перейдут во вторую половину гирлянды, а первая половина ее будет выключена.
Аватара пользователя
ChipKiller
Сверлит текстолит когтями
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

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

Сообщение ChipKiller »

* - указатель ...... учить матчасть :kill:

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

char data_led[8]; // 8*8 = 64
..........
send_data (data_led);
SergeiSam
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Вс фев 18, 2007 14:09:34
Откуда: Воронеж
Контактная информация:

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

Сообщение SergeiSam »

Ser60 писал(а):Если у Вас все работает на первых 32 светодиодах, то на расширение этой последовательности до 64, после засылки первых 32 бит данных зашлите в регистры 32 нуля. Таким образом первые 32 бита последовательности перейдут во вторую половину гирлянды, а первая половина ее будет выключена.


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

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

Сообщение SergeiSam »

ChipKiller писал(а):* - указатель ...... учить матчасть :kill:

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

char data_led[8]; // 8*8 = 64
..........
send_data (data_led);


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

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

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

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

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

Сообщение SergeiSam »

А как? Как мне записать сначала 32, а потом еще выдать 32? В коде? Я просто всю голову сломал. весь инет перерыл... и никак..
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

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

Как мне записать сначала 32, а потом еще выдать 32?
Ну Вы же смогли передать 32, почему не сможете ещё 32 передать в ту же функцию ? Кол-во передаваемых параметров не ограничено.
Аватара пользователя
ChipKiller
Сверлит текстолит когтями
Сообщения: 1163
Зарегистрирован: Ср янв 05, 2011 16:25:15

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

Сообщение ChipKiller »

если именно гнать "бегущий огонь", то все еще проще - отрихтовать проверку

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

 if ((data&0x80000000)==0x00) {PORTD&=~(DATA);}
              else   PORTD.0=(DATA);           
и long не нужен
Аватара пользователя
U235
Встал на лапы
Сообщения: 135
Зарегистрирован: Вт фев 21, 2012 20:42:26
Откуда: Санкт-Петербург, Россия, Земля

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

Сообщение U235 »

С использованием массива функция вывода может выглядеть примерно так

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

/*  pdata - указатель на первый байт
    count - количество выводимых бит
    Функция первым выводит младший бит первого байта */
void send_data (unsigned char pdata[], unsigned char count)
{
    unsigned char i, j, temp;
   
    j=0;

    for (i=count; i != 0; i-=j)
    {
        if (count > 7) j=8;
        else j=count;
       
        temp=*pdata;   // Берём очередной байт
       
        while (j)
        {
            //  Проверка самого младшего бита
            if (temp & 0x01) PORTD.0=1;
            else   PORTD.0=0;
   
            # asm("nop");
            PORTD.1=(CLK); // Импульс на CLK
            # asm("nop");
            PORTD.1=~(CLK);
            # asm("nop");

            temp>>=1;
        }
        pdata++;    // Увеличиваем указатель для следующего байта
    }

    PORTD.2=(Latch); // Импульс на Latch clock
    # asm("nop");
    PORTD.2=~(Latch);   
}
А из наших труб идет необычный дым. Стой! Опасная зона! Работа мозга!...
SergeiSam
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Вс фев 18, 2007 14:09:34
Откуда: Воронеж
Контактная информация:

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

Сообщение SergeiSam »

ChipKiller писал(а):если именно гнать "бегущий огонь", то все еще проще - отрихтовать проверку

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

 if ((data&0x80000000)==0x00) {PORTD&=~(DATA);}
              else   PORTD.0=(DATA);           
и long не нужен

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

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

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

С использованием массива функция вывода может выглядеть примерно так

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

        while (j)
        {
        .....
        .....
        Тут нет ничего, изменяющего переменную "j"
        .....
        .....
        }
Что-то не нравится мне эта конструкция :roll:
Аватара пользователя
U235
Встал на лапы
Сообщения: 135
Зарегистрирован: Вт фев 21, 2012 20:42:26
Откуда: Санкт-Петербург, Россия, Земля

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

Сообщение U235 »

Аlex писал(а):Что-то не нравится мне эта конструкция :roll:


Да, там конце цикла не хватает

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

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

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

Да и это тоже вызывает подозрения

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

    for (i=count; i != 0; i-=j)
    {


    }
j у Вас всегда = 0. Что до цикла ( j=0; ), что после обработки байта (там будет j--;). Цикл будет бесконечным :roll:


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

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

while(count--){

   temp = pdata[count];

   /* тут обрабатываем  temp побитно */
   ....................
   ....................
   ....................
   /******************************/
}
Ответить

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