Код бегущей строки WH0802

Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Ответить
Прорезались зубы
Сообщения: 218
Зарегистрирован: Сб окт 02, 2010 19:06:46
Откуда: Красногорск

Сообщение m210 »

Всем привет! Помогите дописать код до конца. Пытаюсь сделать код бегущей строки, при которой, дойдя до последнего символа в массиве, строка начинает идти в обратную сторону, потом наоборот. В итоге я почти реализовал такую штуковину, но при обратном движении происходит какая то ахинея.

Для эксперимента вывожу слово "Initialization..."
При движении справа-налево никаких нареканий нет, все ок...как только слово начинает идти в обратную сторону, дисплей в 0й и 1й ячейке дублирует букву, естественно эти дублеры сохраняются в массиве и при втором цикле вместо надписи "Initialization..." выводится "IInitializtion...", на третьем круге "IIInitialition..." и т.д.
Выкладываю код реализации этой нелогичности :)

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

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 становится еще хуже
Реклама
Вымогатель припоя
Сообщения: 513
Зарегистрирован: Сб фев 19, 2011 18:04:08
Откуда: Татарстан, пос. Актюбинский

Сообщение 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++;





Последний раз редактировалось phanis Пт окт 26, 2012 10:35:19, всего редактировалось 1 раз.
Контактная информация:
Реклама
Прорезались зубы
Сообщения: 218
Зарегистрирован: Сб окт 02, 2010 19:06:46
Откуда: Красногорск

Сообщение m210 »

Спасибо за примеры кода, но в первом случае бегущая строка как таковой не работает, смещается на 1 индекс и останавливается,потом в обратную сторону также. Тоже пробовал использовать временный массив, но и запоролся на этой проблеме. По второму коду надо додумывать, чтобы текст выводился на дисплей, но с с++ у меня огромные проблемы :) Знаю его очень плохо

Кстати наверно важное уточнение,кодирую в CodeVision :)
Прорезались зубы
Сообщения: 218
Зарегистрирован: Сб окт 02, 2010 19:06:46
Откуда: Красногорск

Сообщение m210 »

но в первом случае бегущая строка как таковой не работает, смещается на 1 индекс и останавливается,потом в обратную сторону также
Так собственно почему она не работает в таком варианте?
Реклама
Эиком - электронные компоненты и радиодетали
Вымогатель припоя
Сообщения: 513
Зарегистрирован: Сб фев 19, 2011 18:04:08
Откуда: Татарстан, пос. Актюбинский

Сообщение 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++;
Контактная информация:
Реклама
Прорезались зубы
Сообщения: 218
Зарегистрирован: Сб окт 02, 2010 19:06:46
Откуда: Красногорск

Сообщение m210 »

Ок , проект выложу, когда вернусь с работы:)
Реклама
Вымогатель припоя
Сообщения: 513
Зарегистрирован: Сб фев 19, 2011 18:04:08
Откуда: Татарстан, пос. Актюбинский

Сообщение 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);
Контактная информация:
Прорезались зубы
Сообщения: 218
Зарегистрирован: Сб окт 02, 2010 19:06:46
Откуда: Красногорск

Сообщение m210 »

Огромное спасибо! Теперь работает! :)
Только вместо flash char text[] = {"Initialization..0123456789"}
указал char text[] = {"Initialization..0123456789"}, иначе компилируется с ошибкой.

Еще вопрос - есть способ указывать текст в массиве в теле программы? чтобы использовать только переменные text[], а не задавать вначале программы массивы с разными текстами?
Вымогатель припоя
Сообщения: 513
Зарегистрирован: Сб фев 19, 2011 18:04:08
Откуда: Татарстан, пос. Актюбинский

Сообщение 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);
   
   }
}
По поводу вопроса не совсем понял. Нужен пример.
Контактная информация:
Прорезались зубы
Сообщения: 218
Зарегистрирован: Сб окт 02, 2010 19:06:46
Откуда: Красногорск

Сообщение 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
Вымогатель припоя
Сообщения: 513
Зарегистрирован: Сб фев 19, 2011 18:04:08
Откуда: Татарстан, пос. Актюбинский

Сообщение 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; 
 }      
}
Контактная информация:
Прорезались зубы
Сообщения: 218
Зарегистрирован: Сб окт 02, 2010 19:06:46
Откуда: Красногорск

Сообщение 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 то вряд ли дойдет, все-таки не тот дисплей для этого :)
Надо будет собрать макетку, посмотреть, что получается по скорости в реальном устройстве. Надеюсь морганий заметно не будет, при очистке дисплея а нижней строке, т.к. получается сперва выполняется цикл верхней строки, и после окончания работы цикла верхней, начинает выводиться инфа в нижней строке.
Вымогатель припоя
Сообщения: 513
Зарегистрирован: Сб фев 19, 2011 18:04:08
Откуда: Татарстан, пос. Актюбинский

Сообщение phanis »

Если длина текста меньше или равно 8 символов зачем ее гонять вле/право?
можно же просто выводить текст

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

 lcd_putsf("text1");
Контактная информация:
Прорезались зубы
Сообщения: 218
Зарегистрирован: Сб окт 02, 2010 19:06:46
Откуда: Красногорск

Сообщение m210 »

конечно она больше 8, но не больше 20-30 символов...никак не 100
Название подпункта меню у меня больше...например первый пунт меню будет называться "Напряжение борт.сети" - 20символов
ниже будут показания, которые меньше 8 символов и я их соответственно вывожу через putsf, но это значение, например, 12.0В, выводится не сразу, а после того, как завершится верхний цикл
Вымогатель припоя
Сообщения: 513
Зарегистрирован: Сб фев 19, 2011 18:04:08
Откуда: Татарстан, пос. Актюбинский

Сообщение phanis »

передавать нужно строку с ее длиной put_scrolltext (" текст более 8 символов", количество символов в тексте )

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

put_scrolltext("Intialization..",15);
попробую сделать без указания длины текста, а пока придется вернуть исходную функцию
Спойлер

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

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;
 }     
}
Контактная информация:
Прорезались зубы
Сообщения: 218
Зарегистрирован: Сб окт 02, 2010 19:06:46
Откуда: Красногорск

Сообщение m210 »

Ну да, просто забыл указать это в моем примере :)
и придется вернуть исходную функцию
Зачем? если все работает и с тем примером, который я выложил ранее?
Собственно не понял, зачем нужна переменная stat, поэтому убрал ее из кода, все работает и без нее :))

Указание длины можно и оставить, особо не напрягает
Вымогатель припоя
Сообщения: 513
Зарегистрирован: Сб фев 19, 2011 18:04:08
Откуда: Татарстан, пос. Актюбинский

Сообщение 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);
 
 }      
}
Контактная информация:
Прорезались зубы
Сообщения: 218
Зарегистрирован: Сб окт 02, 2010 19:06:46
Откуда: Красногорск

Сообщение m210 »

Ну теперь вроде бы все, надо теперь в железе проверять :)
Прорезались зубы
Сообщения: 218
Зарегистрирован: Сб окт 02, 2010 19:06:46
Откуда: Красногорск

Сообщение m210 »

Дошли наконец-то руки собрать устройство...в общем, во-первых, чтобы текст был читаемый, в цикле поставил delay_ms(1500);
чем меньше, тем с более бешеной скоростью он носится, но обратная сторона в том, что при больших задержках delay управлят устройством практически нереально, на кнопки не реагирует почти, строки текста во второй строке выводит только после того,как полностью пройдет первая строка влево/вправо...т.е. если символов будет около 100, то, чтобы посмотреть значения во второй строке или перейти в след пункт меню, придется минуту подождать :)))

Попробовал сделать переменные, которые не дают работать циклу, пока не выведется нижняя строка, тут вроде бы все хорошо, жить можно. а с кнопками сложнее...делал в теле цикла код if(PIND.0 == 0) break; это дает возможность останавливать цикл и переходить в другой пункт меню, но если кнопку держать постоянно (а это необходимо чтобы выставить значение переменной от 0 до 255) то бегущая строка полностью исчезает. Другая проблема что кнопка перехода меню срабатывает не всегда - просто останавливает бегущую строку. Можно ли это все поправить?
Вымогатель припоя
Сообщения: 513
Зарегистрирован: Сб фев 19, 2011 18:04:08
Откуда: Татарстан, пос. Актюбинский

Сообщение phanis »

Можно сделать так запускаем таймер с прерыванием каждые 10 мсек в обработчике выставляем флаг, далее этот же флаг ловим в основном цикле. Получаем некий интервал времени от которого отталкиваемся, далее обрабатывая условия попадаем в функцию сдвига строки(она уже будет другой).
Контактная информация:
Ответить

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