Страница 2 из 2
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 20:17:59
U235
Аlex писал(а):Я так понял, count у Вас - кол-во передаваемых байт (т.б., грубо говоря, размер массива).
Тогда зачем эти все замудренные вычисления и лишние циклы с переменными и указателями ?
Не байт, а бит. Из-за этого и сложность.
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 20:25:35
Аlex
U235 писал(а):Не байт, а бит.
А почему тогда читаете из массива побайтно ?
В таком случае, если
count будет отличен от
8, у Вас будут передаваться из каждого байта не все биты.
Вы берёте байт, затем передаёте кол-во бит, равное переменной
j, в которую Вы пишите число
count (кол-во бит).
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 20:29:31
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);
}
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 20:34:26
А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;
}
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 21:00:06
SergeiSam
Извините конечно, но попробывать сейчас не могу. Сразу дам еще информацию для размышления.
А если я захочу зажечь еще один светодиод и гнать его тоже, например через 2 не светящихся. Это будет уже возможно или надо еще подумать над кодом?
P.s. Попробую все это часа через 2. Заранее спасибо!
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 21:09:05
U235
Сделайте пару функций - устанавливать и сбрасывать бит по его номеру в массиве.
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Пн авг 13, 2012 22:00:52
Аlex
А если я захочу зажечь еще один светодиод и гнать его тоже, например через 2 не светящихся.
Заполняйте массив, как душе угодно, и выводите его наружу.
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Вт авг 14, 2012 01:50:56
SergeiSam
Что-то я попробывал и опять ничего толком не вышло... (((
А можете просто попробывать объяснить весь этот чудодейственный код словами, понятными ))) Я сообразить что-то не могу
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Вт авг 14, 2012 05:07:27
Аlex
Что конкретно Вы пробовали и что не получилось ? Покажите...
То, что мы приводили выше, - это функции вывода массива на внешние регистры.
Заполняйте массив данными с необходимой периодичностью и , с помощью этой ф-ии, выводите его.
В Вашем случае, размер массива должен быть = 4. Если будете использовать мой код, то в параметр pdata передавайте указатель на массив (он же - его имя), а в count - число 4. Ну и проверьте соответствие ПИНов и устанавливаемые им значения, я писал от балды...
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Ср авг 15, 2012 18:00:51
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();
}
{
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Ср авг 15, 2012 18:49:18
А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);
Ну вот, как то так...

Re: Сдвиговые регистры, нужна подсказка
Добавлено: Ср авг 15, 2012 19:05:23
А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-ый светодиод.
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Чт авг 16, 2012 19:03:59
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;
}
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Вс авг 19, 2012 23:43:48
SergeiSam
Пока всем спасибо за подсказки. Последние два кода Alexa меня порадовали. Я их пытаюсь доработать для себя. Будут вопросы - я отпишусь, пока все ясно!
P.s Так же спасибо всем, кто подсказывал!
Re: Сдвиговые регистры, нужна подсказка
Добавлено: Вт авг 05, 2014 14:47:10
Cyber-master
я так понял все получилось? нужно решение?