Страница 1 из 2
Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 01:00:07
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);};
}
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 01:34:01
Аlex
У меня получается только 32 светодиода пройти
Может из-за этого
?
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 06:01:11
zero648
И здесь тоже проверка на 32:
Код: Выделить всё
if (x==32) {x=0;};
...
send_data (z<<x);};
Что этот IF делает?
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 18:46:47
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);
Не проходит проверку может? Как правильно написать?
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 19:06:35
Аlex
Может в этом
long int data
?
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 19:13:00
ChipKiller
Если я ставлю число более 32, то у меня вообще перестает все работать...
.. так и должно быть, тип long - это 2**32, так что лучше вместо
send_data (long int data) указатель на строку значений
send_data (char* data)
Alex опередил

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

А что значит звездочка вот тут:
send_data (char* data)
Изменил то, что сказали на char, прога перестала зажигать светодиоды.... ((( Еще идеи или я не туда поставил char?
Приведите мой код, только с исправлениями, пожалуйста! )
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 19:18:38
Ser60
Если у Вас все работает на первых 32 светодиодах, то на расширение этой последовательности до 64, после засылки первых 32 бит данных зашлите в регистры 32 нуля. Таким образом первые 32 бита последовательности перейдут во вторую половину гирлянды, а первая половина ее будет выключена.
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 19:21:40
ChipKiller
* - указатель ...... учить матчасть
Код: Выделить всё
char data_led[8]; // 8*8 = 64
..........
send_data (data_led);
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 19:23:34
SergeiSam
Ser60 писал(а):Если у Вас все работает на первых 32 светодиодах, то на расширение этой последовательности до 64, после засылки первых 32 бит данных зашлите в регистры 32 нуля. Таким образом первые 32 бита последовательности перейдут во вторую половину гирлянды, а первая половина ее будет выключена.
Нет, мне потом понадобится играть ими в любых последовательностях. Т.е. мне надо управлять всеми светодиодами в простом доступе.
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 19:26:11
SergeiSam
ChipKiller писал(а):* - указатель ...... учить матчасть
Код: Выделить всё
char data_led[8]; // 8*8 = 64
..........
send_data (data_led);
Не стреляйте в меня )))
Но я ничего не понял. Это мне куда вставить в программе?
Я так понимаю, что это будет массив?
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 19:28:12
Аlex
Самый простой способ - передать 2 по 32(long)

А самый правильный - создать массив и передавать указатель на него.
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 19:30:11
SergeiSam
А как? Как мне записать сначала 32, а потом еще выдать 32? В коде? Я просто всю голову сломал. весь инет перерыл... и никак..
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 19:33:04
Аlex
Как мне записать сначала 32, а потом еще выдать 32?
Ну Вы же смогли передать 32, почему не сможете ещё 32 передать в ту же функцию ? Кол-во
передаваемых параметров не ограничено.
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 19:35:25
ChipKiller
если именно гнать "бегущий огонь", то все еще проще - отрихтовать проверку
Код: Выделить всё
if ((data&0x80000000)==0x00) {PORTD&=~(DATA);}
else PORTD.0=(DATA);
и long не нужен
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 19:45:32
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);
}
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 19:55:29
SergeiSam
ChipKiller писал(а):если именно гнать "бегущий огонь", то все еще проще - отрихтовать проверку
Код: Выделить всё
if ((data&0x80000000)==0x00) {PORTD&=~(DATA);}
else PORTD.0=(DATA);
и long не нужен
В каком месте и как ее отрихтовать? Я кучу вариантов перепробывал. Так и не вышло...
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 19:56:50
Аlex
С использованием массива функция вывода может выглядеть примерно так
Код: Выделить всё
while (j)
{
.....
.....
Тут нет ничего, изменяющего переменную "j"
.....
.....
}
Что-то не нравится мне эта конструкция

Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 20:02:15
U235
Аlex писал(а):Что-то не нравится мне эта конструкция

Да, там конце цикла не хватает
Не знаю почему, но очень редко получается написать без подобных досадных ошибок

Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 20:13:18
Аlex
Да и это тоже вызывает подозрения
j у Вас всегда =
0. Что до цикла (
j=0; ), что после обработки байта (там будет
j--;). Цикл будет бесконечным
Я так понял,
count у Вас - кол-во передаваемых байт (т.б., грубо говоря, размер массива).
Тогда зачем эти все замудренные вычисления и лишние циклы с переменными и указателями ?
Код: Выделить всё
while(count--){
temp = pdata[count];
/* тут обрабатываем temp побитно */
..
..
..
/******************************/
}