Страница 1 из 2
Код бегущей строки WH0802
Добавлено: Чт окт 25, 2012 17:50:07
m210
Всем привет! Помогите дописать код до конца. Пытаюсь сделать код бегущей строки, при которой, дойдя до последнего символа в массиве, строка начинает идти в обратную сторону, потом наоборот. В итоге я почти реализовал такую штуковину, но при обратном движении происходит какая то ахинея.
Для эксперимента вывожу слово "Initialization..."
При движении справа-налево никаких нареканий нет, все ок...как только слово начинает идти в обратную сторону, дисплей в 0й и 1й ячейке дублирует букву, естественно эти дублеры сохраняются в массиве и при втором цикле вместо надписи "Initiali
zation..." выводится "IInitiali
ztion...", на третьем круге "IIInitia
lition..." и т.д.
Выкладываю код реализации этой нелогичности
Код: Выделить всё
char text[40] = { "Initialization..." };
if(scroll == 0) //движение справа-налево
{
text[17]=text[0];
for(i=0; i<17; i++)
{
text[i]=text[i+1];
}
}
else //движение в обратную сторону
{
text[0]=text[16];
for(i=17; i>0; i--)
{
text[i]=text[i-1];
}
}
if(scroll_time<8) { scroll_time = scroll_time++; } else { scroll_time = 0; scroll=scroll++; if(scroll>1) scroll = 0; } //при перемещении на 8 ячеек (wh0802) меняется направление движения бегущей строки
lcd_gotoxy(0,0);
lcd_puts(text);
Соответственно ошибка сидит где-то в теле цикла после else, при этом можно заметить, что в первом условии идет запись в 17ю ячейку массива, а во втором условии в 16ю, но как бы это было бы нелогично, но подругому работает еще хуже. Тоже самое с самим циклом, первый цикл работает от 0 до 16, второй цикл от 17 до 1, при задании условия от 16 до -1 становится еще хуже
Re: Код бегущей строки WH0802
Добавлено: Чт окт 25, 2012 18:09:45
phanis
Можно использовать временный буфер char text_temp[40] например, т.е менять все в нем, не писать в исходный массив char
text[40] = { "Initialization..." };
Спойлер
Код: Выделить всё
char text[40] = { "Initialization..." };
char text_temp[40];
if(scroll == 0) //движение справа-налево
{
text_temp[17]=text[0];
for(i=0; i<17; i++)
{
text_temp[i]=text[i+1];
}
}
else //движение в обратную сторону
{
text_temp[0]=text[16];
for(i=17; i>0; i--)
{
text_temp[i]=text[i-1];
}
}
if(scroll_time<8) { scroll_time = scroll_time++; } else { scroll_time = 0; scroll=scroll++; if(scroll>1) scroll = 0; } //при перемещении на 8 ячеек (wh0802) меняется направление движения бегущей строки
lcd_gotoxy(0,0);
lcd_puts(text_temp);
Еще можно предложить передавать lcd_puts(text+смещение указателя);
Спойлер
Код: Выделить всё
char text[40] = { "Initialization..." };
char smechenie=0;
if(scroll == 0) //движение справа-налево
{
smechenie++;
}
else //движение в обратную сторону
{
if(smechenie > 0 ) smechenie--;
}
if(scroll_time<8) { scroll_time = scroll_time++; } else { scroll_time = 0; scroll=scroll++; if(scroll>1) scroll = 0; } //при перемещении на 8 ячеек (wh0802) меняется направление движения бегущей строки
lcd_gotoxy(0,0);
lcd_puts(text_temp+smechenie);
или смотреть в эту сторону
char text[40] = { "Initialization..." };
char smechenie;
smechenie = scroll_time;
smechenie ^= ((scroll_time&0x80)>>3) * 0x07;
smechenie &= 0x07;
lcd_gotoxy(0,0);
lcd_puts(text+smechenie);
scroll_time++;
Re: Код бегущей строки WH0802
Добавлено: Чт окт 25, 2012 20:06:06
m210
Спасибо за примеры кода, но в первом случае бегущая строка как таковой не работает, смещается на 1 индекс и останавливается,потом в обратную сторону также. Тоже пробовал использовать временный массив, но и запоролся на этой проблеме. По второму коду надо додумывать, чтобы текст выводился на дисплей, но с с++ у меня огромные проблемы

Знаю его очень плохо
Кстати наверно важное уточнение,кодирую в CodeVision

Re: Код бегущей строки WH0802
Добавлено: Пт окт 26, 2012 05:31:33
m210
но в первом случае бегущая строка как таковой не работает, смещается на 1 индекс и останавливается,потом в обратную сторону также
Так собственно почему она не работает в таком варианте?
Re: Код бегущей строки WH0802
Добавлено: Пт окт 26, 2012 10:27:04
phanis
Если соберете проект в архив с протеусом исходниками, и выложите здесь, тогда будет легче найти ошибку. Возможно еще какие то проблемы, очистку экрана, обновление экрана не нужно делать после каждого чиха? Вверху ошибся третий вариант lcd_puts(text_temp+smechenie); исправил на lcd_puts(text+smechenie);
Вот еще вариант
Спойлер
Код: Выделить всё
char text[40] = { "Initialization..." };
flash char smechenie[16]={0,1,2,3,4,5,6,7,8,7,6,5,4,3,2,1};
lcd_gotoxy(0,0);
lcd_puts((text+smechenie[(scroll_time & 0x0f)]));
scroll_time++;
Re: Код бегущей строки WH0802
Добавлено: Пт окт 26, 2012 11:07:38
m210
Ок , проект выложу, когда вернусь с работы:)
Re: Код бегущей строки WH0802
Добавлено: Сб окт 27, 2012 09:32:51
phanis
Вроде понял что нужно было. выводит всю строку влево затем возвращает ее вправо . пример
Спойлер
Код: Выделить всё
flash char text[] = {"Initialization..0123456789"}; // текст можно до247 символов
char text_temp[16];
for(i=0; i<8; i++) text_temp[i]=text[(i+ scroll_time)];
if(scroll)scroll_time--; //движение в обратную сторону
else scroll_time++; //движение справа-налево
if ((scroll_time==0)||(scroll_time+8>=(sizeof(text)-1)) ) scroll^=1;
lcd_gotoxy(0,0);
lcd_puts(text_temp);
Re: Код бегущей строки WH0802
Добавлено: Сб окт 27, 2012 15:14:26
m210
Огромное спасибо! Теперь работает!

Только вместо flash char text[] = {"Initialization..0123456789"}
указал char text[] = {"Initialization..0123456789"}, иначе компилируется с ошибкой.
Еще вопрос - есть способ указывать текст в массиве в теле программы? чтобы использовать только переменные text[], а не задавать вначале программы массивы с разными текстами?
Re: Код бегущей строки WH0802
Добавлено: Сб окт 27, 2012 16:12:47
phanis
Странно
flash char text[] = {"Initialization.."}; у мну компилируется без ошибок, при этом текст будет хранится только во флеш мк, а так char text[] = {"Initialization.."}; и во флеш и в озу. Версия на которой проверял cvavr 2.05 . Объявлять нужно в начале например так
Спойлер
Код: Выделить всё
/*************************************/
#include <mega8.h>
#include <lcd.h>
#include <delay.h>
#asm
.equ __lcd_port=0x12; PORTD /* ЖКИ дисплей подключили к порту I/O D */
#endasm
flash char text[] = {"Initialization.."};
#define symb_len 4
char text_temp[symb_len*2];
char scroll_time,i,scroll;
void main(void) /* Основная функция "main", с которой начинается выполнение всей программой процедуры */
{
lcd_init(16);
lcd_clear();
while(1)
{
delay_ms(150);
for(i=0; i<symb_len; i++) text_temp[i]=text[(i+ scroll_time)];
if(scroll)scroll_time--; //движение в обратную сторону
else scroll_time++; //движение справа-налево
if ((scroll_time==0)||(scroll_time+symb_len>=(sizeof(text)-1)) ) scroll^=1;
lcd_clear();
lcd_gotoxy(0,0);
lcd_puts(text_temp);
}
}
По поводу вопроса не совсем понял. Нужен пример.
Re: Код бегущей строки WH0802
Добавлено: Сб окт 27, 2012 17:31:35
m210
По поводу вопроса не совсем понял. Нужен пример.
Ну вот хотел сделать финт, чтобы не писать все эти циклы и условия по 10 раз...не получилось
Код: Выделить всё
void put_scrolltext (char text[])
{
for(i=0; i<8; i++) text_temp[i]=text[(i+ scroll_time)];
if(scroll)scroll_time--; //движение в обратную сторону
else scroll_time++; //движение справа-налево
if ((scroll_time==0)||(scroll_time+8>=(sizeof(text)-1)) ) scroll^=1;
lcd_gotoxy(0,0);
lcd_puts(text_temp);
}
и чтобы потом вводить put_scrolltext("Intialization");
или типа того...бегущая строка всегда у меня будет в первой строке, поэтому lcd_gotoxy и lcd_puts тоже добавил туда, иначе не знаю как из этого void'а потом получать значение text_temp
Re: Код бегущей строки WH0802
Добавлено: Сб окт 27, 2012 20:08:14
phanis
Вот пример набросок, нужно доделывать
Спойлер
Код: Выделить всё
/*************************************/
#include <mega8.h>
#include <lcd.h>
#include <delay.h>
#asm
.equ __lcd_port=0x12; PORTD /* ЖКИ дисплей подключили к порту I/O D */
#endasm
char text_temp[16];
void put_scrolltext (flash char *text,char len);
void main(void) /* Основная функция "main", с которой начинается выполнение всей программой процедуры */
{
lcd_init(16);
lcd_clear();
while(1)
{
put_scrolltext("Intialization..",15);
delay_ms(1000);
put_scrolltext("Example_1",9);
delay_ms(1000);
put_scrolltext("Example_2",9);
delay_ms(1000);
put_scrolltext("Example_3",9);
delay_ms(1000);
}
}
void put_scrolltext (flash char *text,char len)
{
static char scroll_time;
static char i;
static char scroll;
static char stat;
static char recur;
recur=scroll_time=scroll=stat=0;
while(recur++<100)
{
for(i=0; i<8; i++) text_temp[i]=text[(i+ scroll_time)];
if(stat) stat=2;
if(scroll)
{
scroll_time--; //движение в обратную сторону
if (scroll_time==0) stat=1;
}
else
{
scroll_time++; //движение справа-налево
}
if ((scroll_time==0)||(scroll_time+8>= len) )
{
scroll^=1;
}
lcd_gotoxy(0,0);
lcd_puts(text_temp);
delay_ms(200);
if(stat==2) break;
}
}
Re: Код бегущей строки WH0802
Добавлено: Вс окт 28, 2012 10:13:19
m210
Еще раз спасибо, теперь казалось бы все

Поставил пару + к рейтингу
Код немного переписал, т.к. мне не надо выводить в одном окне все подряд, переделал вот так, и по проще
Код: Выделить всё
void put_scrolltext (flash char *text,char len)
{
static char scroll_time;
static char i;
static char scroll;
static char recur;
recur=scroll_time=scroll=0;
while(recur++<40)
{
for(i=0; i<8; i++) text_temp[i]=text[(i+ scroll_time)];
if(scroll) scroll_time--; //движение в обратную сторону
else scroll_time++; //движение справа-налево
if ((scroll_time==0)||(scroll_time+8>= len) ) { scroll^=1; }
lcd_gotoxy(0,0);
lcd_puts(text_temp);
delay_ms(200);
}
}
Информацию на дисплей вывожу таким образом
Код: Выделить всё
switch(menu)
{
case 0:
put_scrolltext("text1");
bla-bla-bla
break;
case 1:
put_scrolltext("text2");
bla-bla-bla
break;
и.т.д.
}
Запускаю прогамму пока только в Протеусе, а там очень заметно, что код довольно медлительный, поэтому уменьшил цикл recur до 40, все равно до 100 символов у меня текста не будет, и до 40 то вряд ли дойдет, все-таки не тот дисплей для этого

Надо будет собрать макетку, посмотреть, что получается по скорости в реальном устройстве. Надеюсь морганий заметно не будет, при очистке дисплея а нижней строке, т.к. получается сперва выполняется цикл верхней строки, и после окончания работы цикла верхней, начинает выводиться инфа в нижней строке.
Re: Код бегущей строки WH0802
Добавлено: Вс окт 28, 2012 10:58:46
phanis
Если длина текста меньше или равно 8 символов зачем ее гонять вле/право?
можно же просто выводить текст
Re: Код бегущей строки WH0802
Добавлено: Вс окт 28, 2012 11:04:22
m210
конечно она больше 8, но не больше 20-30 символов...никак не 100
Название подпункта меню у меня больше...например первый пунт меню будет называться "Напряжение борт.сети" - 20символов
ниже будут показания, которые меньше 8 символов и я их соответственно вывожу через putsf, но это значение, например, 12.0В, выводится не сразу, а после того, как завершится верхний цикл
Re: Код бегущей строки WH0802
Добавлено: Вс окт 28, 2012 11:31:39
phanis
передавать нужно строку с ее длиной put_scrolltext (
" текст более 8 символов",
количество символов в тексте )
попробую сделать без указания длины текста, а пока придется вернуть исходную функцию
Спойлер
Код: Выделить всё
void put_scrolltext (flash char *text,char len)
{
static char scroll_time;
static char i;
static char scroll;
static char stat;
static char recur;
recur=scroll_time=scroll=stat=0;
while(recur++<100)
{
for(i=0; i<8; i++) text_temp[i]=text[(i+ scroll_time)];
if(stat) stat=2;
if(scroll)
{
scroll_time--; //движение в обратную сторону
if (scroll_time==0) stat=1;
}
else
{
scroll_time++; //движение справа-налево
}
if ((scroll_time==0)||(scroll_time+8>= len) )
{
scroll^=1;
}
lcd_gotoxy(0,0);
lcd_puts(text_temp);
delay_ms(200);
if(stat==2) break;
}
}
Re: Код бегущей строки WH0802
Добавлено: Вс окт 28, 2012 11:39:40
m210
Ну да, просто забыл указать это в моем примере
и придется вернуть исходную функцию
Зачем? если все работает и с тем примером, который я выложил ранее?
Собственно не понял, зачем нужна переменная stat, поэтому убрал ее из кода, все работает и без нее
Указание длины можно и оставить, особо не напрягает
Re: Код бегущей строки WH0802
Добавлено: Вс окт 28, 2012 11:53:04
phanis
без указания длины
Спойлер
Код: Выделить всё
/*************************************/
#include <mega8.h>
#include <lcd.h>
#include <delay.h>
#asm
.equ __lcd_port=0x12; PORTD /* ЖКИ дисплей подключили к порту I/O D */
#endasm
char text_temp[16];
void put_scrolltext (flash char *text);
void main(void) /* Основная функция "main", с которой начинается выполнение всей программой процедуры */
{
lcd_init(16);
lcd_clear();
while(1)
{
put_scrolltext("Intialization..");
delay_ms(1000);
put_scrolltext("Exampl");
delay_ms(1000);
put_scrolltext("Example_2");
delay_ms(1000);
put_scrolltext("Example_3");
delay_ms(1000);
}
}
void put_scrolltext (flash char *text)
{
static char scroll_time;
static char i;
static char scroll;
static char stat;
static char recur;
char len=0;
while (*(text+len)) len++;
if(len>8)
{
recur=scroll_time=scroll=stat=0;
while(recur++<100)
{
for(i=0; i<8; i++) text_temp[i]=text[(i+ scroll_time)];
if(stat) stat=2;
if(scroll)
{
scroll_time--; //движение в обратную сторону
if (scroll_time==0) stat=1;
}
else
{
scroll_time++; //движение справа-налево
}
if ((scroll_time==0)||(scroll_time+8>= len) )
{
scroll^=1;
}
lcd_gotoxy(0,0);
lcd_puts(text_temp);
delay_ms(200);
if(stat==2) break;
}
}
else
{
lcd_gotoxy(0,0);
lcd_putsf(text);
}
}
stat нужен для того чтобы один раз текст прошел в л/п и вылетел и цикла.
без stat
Спойлер
Код: Выделить всё
/*************************************/
#include <mega8.h>
#include <lcd.h>
#include <delay.h>
#asm
.equ __lcd_port=0x12; PORTD /* ЖКИ дисплей подключили к порту I/O D */
#endasm
char text_temp[16];
void put_scrolltext (flash char *text);
void main(void) /* Основная функция "main", с которой начинается выполнение всей программой процедуры */
{
lcd_init(16);
lcd_clear();
while(1)
{
put_scrolltext("Intialization..");
delay_ms(1000);
put_scrolltext("Exampl");
delay_ms(1000);
put_scrolltext("Example_2");
delay_ms(1000);
put_scrolltext("Example_3");
delay_ms(1000);
}
}
void put_scrolltext (flash char *text)
{
char scroll_time;
char i;
char scroll;
char recur;
char len=0;
while (*(text+len)) len++;
if(len>8)
{
recur=scroll_time=scroll=0;
while(recur++<=((len-8)*2))
{
for(i=0; i<8; i++) text_temp[i]=text[(i+ scroll_time)];
if(scroll)scroll_time--; //движение в обратную сторону
else scroll_time++; //движение справа-налево
if ((scroll_time==0)||(scroll_time+8>= len) ) scroll^=1;
lcd_gotoxy(0,0);
lcd_puts(text_temp);
delay_ms(200);
}
}
else
{
lcd_gotoxy(0,0);
lcd_putsf(text);
}
}
Re: Код бегущей строки WH0802
Добавлено: Вс окт 28, 2012 12:44:24
m210
Ну теперь вроде бы все, надо теперь в железе проверять

Re: Код бегущей строки WH0802
Добавлено: Вт окт 30, 2012 17:44:30
m210
Дошли наконец-то руки собрать устройство...в общем, во-первых, чтобы текст был читаемый, в цикле поставил delay_ms(1500);
чем меньше, тем с более бешеной скоростью он носится, но обратная сторона в том, что при больших задержках delay управлят устройством практически нереально, на кнопки не реагирует почти, строки текста во второй строке выводит только после того,как полностью пройдет первая строка влево/вправо...т.е. если символов будет около 100, то, чтобы посмотреть значения во второй строке или перейти в след пункт меню, придется минуту подождать
Попробовал сделать переменные, которые не дают работать циклу, пока не выведется нижняя строка, тут вроде бы все хорошо, жить можно. а с кнопками сложнее...делал в теле цикла код if(PIND.0 == 0) break; это дает возможность останавливать цикл и переходить в другой пункт меню, но если кнопку держать постоянно (а это необходимо чтобы выставить значение переменной от 0 до 255) то бегущая строка полностью исчезает. Другая проблема что кнопка перехода меню срабатывает не всегда - просто останавливает бегущую строку. Можно ли это все поправить?
Re: Код бегущей строки WH0802
Добавлено: Ср окт 31, 2012 17:17:41
phanis
Можно сделать так запускаем таймер с прерыванием каждые 10 мсек в обработчике выставляем флаг, далее этот же флаг ловим в основном цикле. Получаем некий интервал времени от которого отталкиваемся, далее обрабатывая условия попадаем в функцию сдвига строки(она уже будет другой).