реклама на сайте
подробности

 
 
> Как вывести на LCD большое число, Не могу вывести число, большее 32767
Tomade
сообщение Aug 20 2008, 11:53
Сообщение #1


Участник
*

Группа: Новичок
Сообщений: 23
Регистрация: 26-05-08
Пользователь №: 37 817



Подскажите чайнику, как переехать такую проблему.
Микроконтроллер серии ATMega, нужно выводить на ЖКИ типа РС1602F (c контроллером) инкрементируемую переменную, которая может принимать значения, к примеру, от 0 до 1 000 000. Работу программы (см. вложение) симулирую на VMLAB3.12.
Что получается? До значания переменной, равного 32767, всё идёт нормально. А вот следующее индицируемое число равняется -32768 (со знаком минус), и все последующие начинают декрементироваться, то есть -32767, -32766, -32765 и т.д. Почему?

Сообщение отредактировал Tomade - Aug 20 2008, 11:55
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 20)
zhevak
сообщение Aug 20 2008, 12:04
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065



Для ответа на Ваш вопрос, Вы указали мало данных.
Как минимум нужно видеть Ваш код.


--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
Go to the top of the page
 
+Quote Post
Maik-vs
сообщение Aug 20 2008, 12:04
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 246
Регистрация: 4-12-06
Пользователь №: 23 101



Цитата(Tomade @ Aug 20 2008, 15:53) *
Подскажите чайнику, как переехать такую проблему.
Микроконтроллер серии ATMega, нужно выводить на ЖКИ типа РС1602F (c контроллером) инкрементируемую переменную, которая может принимать значения, к примеру, от 0 до 1 000 000. Работу программы (см. вложение) симулирую на VMLAB3.12.
Что получается? До значания переменной, равного 32767, всё идёт нормально. А вот следующее индицируемое число равняется -32768 (со знаком минус), и все последующие начинают декрементироваться, то есть -32767, -32766, -32765 и т.д. Почему?


Потому что объявлено как int, старший бит трактуется как знак. Объявите unsigned int - получите 0 .. 65535. Читайте про представление чисел в Си.
Go to the top of the page
 
+Quote Post
=GM=
сообщение Aug 20 2008, 12:10
Сообщение #4


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(Maik-vs @ Aug 20 2008, 11:04) *
Потому что объявлено как int, старший бит трактуется как знак. Объявите unsigned int - получите 0 .. 65535

Всё равно не хватит до миллиона, надо объявить переменную как LONG.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
Tomade
сообщение Aug 20 2008, 12:18
Сообщение #5


Участник
*

Группа: Новичок
Сообщений: 23
Регистрация: 26-05-08
Пользователь №: 37 817



Цитата(=GM= @ Aug 20 2008, 16:10) *
Всё равно не хватит до миллиона, надо объявить переменную как LONG.

Так и делал:

char lcd_buffer[33];
unsigned long int x = 32760;
void main(void)
{
lcd_init(16);
while(1){
sprintf(lcd_buffer,"%i",x);
lcd_clear();
lcd_puts(lcd_buffer);
x++;
delay_ms(20);}}

- эффекта никакого.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 20 2008, 12:22
Сообщение #6


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



"%i" - это int, надо - "%l" или "%lu" (второе для unsigned long)


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Aug 20 2008, 12:36
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



Странно... есть же на данном форуме тема с чужим готовым кодом...

Код
void lcd_menu_value(
    unsigned long freq,
    unsigned char width,    // full width
    unsigned char comma,        // comma position (from right, inside width)
    unsigned char rj        // right truncated
    )
{
    //PROGMEM
    static const unsigned long vals [] =
    {
        10000000,
        1000000,
        100000,
        10000,
        1000,
        100,
        10,
        1,
    };
    const unsigned  char j = (sizeof vals /sizeof vals [0]) - rj;
    unsigned  char i = (j - width);
    unsigned  char z = 1;    // only zeroes

    ws1602_gotoxy(0, 0);        // курсор в начало первой строки

    for (; i < j; ++ i)
    {
        //ldiv_t res = ldiv(freq, pgm_read_dword(& vals [i]));
        ldiv_t res = ldiv(freq, vals [i]);
        if (comma == (j - i))
            ws1602_wrdata('.');

        if (z == 1 && (i + 1) < j && res.quot == 0)
            ws1602_wrdata(' ');    // supress zero
        else
        {
            z = 0;
            ws1602_wrdata('0' + res.quot);
        }
        freq = res.rem;

    }
}

void ws1602_dispfreq(unsigned long freq)
{
    lcd_menu_value(freq, 7, 2, 1);
}


Сообщение отредактировал Genadi Zawidowski - Aug 20 2008, 12:39
Go to the top of the page
 
+Quote Post
GDI
сообщение Aug 20 2008, 12:41
Сообщение #8


Профессионал
*****

Группа: Свой
Сообщений: 1 235
Регистрация: 14-05-05
Из: Санкт-Петербург
Пользователь №: 5 008



Цитата
sprintf(lcd_buffer,"%i",x);

Цитата
"%i" - это int, надо - "%l" или "%lu" (второе для unsigned long)

Еще от компилятора зависит, какая там спринтф будет, в ИАРе, вроде поддержку ЛОНГ отдельно надо включать, в настройках проекта.


--------------------
http://www.embedders.org Блоги разработчиков электроники.
Go to the top of the page
 
+Quote Post
zhevak
сообщение Aug 20 2008, 13:08
Сообщение #9


Знающий
****

Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065



Цитата(Tomade @ Aug 20 2008, 18:18) *
Так и делал:

char lcd_buffer[33];
unsigned long int x = 32760;
void main(void)
{
lcd_init(16);
while(1){
sprintf(lcd_buffer,"%i",x);
lcd_clear();
lcd_puts(lcd_buffer);
x++;
delay_ms(20);}}

- эффекта никакого.


Обратите внимание на указанную функцию. В CodeVision в настройках надо указывать какую библиотеу вы будете тиспользовать:

- Меню Project \ Confugire
- В окне настроек вкладка C Compiler
- На вкладке внизу слева настройки (s)printf Features


--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
Go to the top of the page
 
+Quote Post
Tomade
сообщение Aug 21 2008, 05:49
Сообщение #10


Участник
*

Группа: Новичок
Сообщений: 23
Регистрация: 26-05-08
Пользователь №: 37 817



Спасибо всем откликнувшимся. Вот что получилось (компилятор - CVAVR 1.25.2). Если в строке sprintf(lcd_buffer,"%i",x) вместо i ставить I или Iu, то в симуляторе на табло LCD вообще ничего не выводится (и для int, и для long). После игры в метод тыка оказалось, что правильно выводятся числа до 65535, если вместо i ставить просто u, причём независимо от настроек, о которых говорил zhevak в последнем письме.
Другие варианты, перечисленные в справке CVAVR для (s)printf features, ни к чему не привели.
Как же вывести на экран LCD число, большее 65535?
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 21 2008, 06:05
Сообщение #11


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Tomade @ Aug 21 2008, 11:49) *
Если в строке sprintf(lcd_buffer,"%i",x) вместо i ставить I или Iu, то в симуляторе на табло LCD вообще ничего не выводится (и для int, и для long).


Надо не I, а L! (от long)


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Aug 21 2008, 06:27
Сообщение #12


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



А через функцию char *ltoa(long value, char *string, int radix)? Или ее нет в библиотеке?
Go to the top of the page
 
+Quote Post
zhevak
сообщение Aug 21 2008, 06:36
Сообщение #13


Знающий
****

Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065



Цитата(Tomade @ Aug 21 2008, 11:49) *
Спасибо всем откликнувшимся. Вот что получилось (компилятор - CVAVR 1.25.2). Если в строке sprintf(lcd_buffer,"%i",x) вместо i ставить I или Iu, то в симуляторе на табло LCD вообще ничего не выводится (и для int, и для long). После игры в метод тыка оказалось, что правильно выводятся числа до 65535, если вместо i ставить просто u, причём независимо от настроек, о которых говорил zhevak в последнем письме.
Другие варианты, перечисленные в справке CVAVR для (s)printf features, ни к чему не привели.
Как же вывести на экран LCD число, большее 65535?


Попробуйте сделать так:

Код
#include <stdio.h>
...

  unsigned long x;
  x = 1000000;
  char s1[10];

...

  sprintf(s1, "%li", x);  // Библиотечная функция
  LCD_StringXY(0, 1, s1);  // -- это моя функция, у Вас должно быть что-то свое


Вы заставили-таки меня сделать это.

Вы неправильно используете модефикаторы. Я попробовал и так sprintf(s1, "%li", x); и так sprintf(s1, "%ld", x); -- работает в обоих случаях. У меня CodeWizardAVR V1.25.3 Standard.


--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
Go to the top of the page
 
+Quote Post
bloodden
сообщение Aug 21 2008, 06:52
Сообщение #14


Бывалый
***

Группа: Validating
Сообщений: 375
Регистрация: 19-10-05
Из: Kiev, UA
Пользователь №: 9 853



Цитата(GDI @ Aug 20 2008, 15:41) *
Еще от компилятора зависит, какая там спринтф будет, в ИАРе, вроде поддержку ЛОНГ отдельно надо включать, в настройках проекта.

Истина. Как и в CVAVR впрочем тоже. В настройках проекта. По-умолчанию там стоит до инта.


--------------------
Заходите кому надо на мой сайт
Go to the top of the page
 
+Quote Post
Tomade
сообщение Aug 21 2008, 09:59
Сообщение #15


Участник
*

Группа: Новичок
Сообщений: 23
Регистрация: 26-05-08
Пользователь №: 37 817



АНТОХА: Надо не I, а L! (от long)
В вашем предыдущем письме было I. Впрочем, ставил и I, и l, и L - не помогает. В этих случаях совсем ничего не высвечивается.
bloodden: Как и в CVAVR впрочем тоже. В настройках проекта. По-умолчанию там стоит до инта.
В предыдущем письме сообщал, что перепробовал разные настройки. Не помогло.
zhevak: Вы неправильно используете модификаторы. Я попробовал и так sprintf(s1, "%li", x); и так sprintf(s1, "%ld", x); -- работает в обоих случаях.
Проблема в том, что я не программист. Можно сказать, радиолюбитель, решивший самостоятельно изучить МК (и СИ) и что-то на них собирать. Потому то, что для программиста очевидно, для меня - далеко не так. А именно:
sprintf(s1, "%li", x); // Библиотечная функция - где эта функция должна находиться? Как проверить, что она есть? И если нет, то где взять и куда вставить?
LCD_StringXY(0, 1, s1); // -- это моя функция, у Вас должно быть что-то свое.
Если бы знать, что своё должно быть... А просто поставить, к примеру, sprintf(s1, "%li", x); - ни к чему не приводит.
Короче, пойду покупать пистолет. help.gif
Go to the top of the page
 
+Quote Post
zhevak
сообщение Aug 21 2008, 10:15
Сообщение #16


Знающий
****

Группа: Свой
Сообщений: 723
Регистрация: 29-08-05
Из: Березовский
Пользователь №: 8 065



Цитата(Tomade @ Aug 21 2008, 15:59) *
Короче, пойду покупать пистолет. help.gif


1. Сказку о двух лягушках расказать или знаете?

2. Решать задчи, которые уже знаешь как решать, -- не интересно. Намного интереснее решать те задачи, к которым даже не знаешь как подступится. Только такие задачи способствуют росту.

3. А судьи кто? Обычные люди (usual people) о конкретном человеке судят по тому, чего он достиг на данный момент. Продвинутые люди (advanced people) смотрят на то, какие задачи он себе ставит и как быстро он растет. Не обращайте внимание на то, что говорят первые. Идите своей дорогой. И будет Вам счастье!

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


--------------------
Хочешь рассмешить Бога -- расскажи ему о своих планах!
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 21 2008, 10:47
Сообщение #17


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Tomade @ Aug 21 2008, 15:59) *
АНТОХА: Надо не I, а L! (от long)
В вашем предыдущем письме было I. Впрочем, ставил и I, и l, и L - не помогает. В этих случаях совсем ничего не высвечивается.


Клевета! smile.gif Было маленькое L - l.
Почему не работает - не знаю, я не использую CVAVR.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Tomade
сообщение Aug 21 2008, 11:08
Сообщение #18


Участник
*

Группа: Новичок
Сообщений: 23
Регистрация: 26-05-08
Пользователь №: 37 817



Антоха: Клевета! Было маленькое L - l.
Прошу прощения. Был сбой при передаче данных. smile.gif
zhevak: Читайте книжки, посещайте форумы и уточняйте, что Вам не ясно.
Потому и обратился сюда. В моём окружении программистов МК нет.

Сообщение отредактировал Tomade - Aug 21 2008, 11:09
Go to the top of the page
 
+Quote Post
sss992
сообщение Aug 21 2008, 11:16
Сообщение #19


Участник
*

Группа: Участник
Сообщений: 18
Регистрация: 8-02-06
Пользователь №: 14 125



можно так сделать:

...
unsigned long int x = 1000000;
...
sprintf(lcd_buffer,"%.0f",(float)x);
...

в С30 работает. а вообще почитайте описание sprintf и разберитесь с типами в Вашем компиляторе
Go to the top of the page
 
+Quote Post
Tomade
сообщение Aug 22 2008, 07:25
Сообщение #20


Участник
*

Группа: Новичок
Сообщений: 23
Регистрация: 26-05-08
Пользователь №: 37 817



Ну вот, проблема решилась. Сделал следующее.
1.Сгенерировал начальные коды под микроконтроллер ATMega64L (было ATMega16).
2.В строке sprintf(lcd_buffer,"%u",x); вместо u поставил lu (как ранее советовал АНТОХА.
Всем спасибо.
Go to the top of the page
 
+Quote Post
Goodefine
сообщение Aug 25 2008, 07:32
Сообщение #21


Местный
***

Группа: Свой
Сообщений: 211
Регистрация: 6-08-07
Из: Приднестровье, Тирасполь
Пользователь №: 29 581



Можно сделать несколько иначе - не используя громоздкую sprintf (на мелких МК не всегда работает, плюс памяти отжирает много) для трехзначной переменной (наращивается аналогично), например:
Код
//объявляем переменные
char j=1;
char buffer [4];
char S =0; //сотни
char D =0; //десяки
char E =0; //единицы
//функция преобразования
void decbin (unsigned int x) {
            
unsigned int i;
            
// Place your code here
for (i=x; i>=100; i=i-100) {S++;};
for (i=x-100*S; i>=10; i=i-10) {D++;};
for (i=x-100*S-10*D; i>=1; i=i-1) {E++;};
}

main {
....
while (1)
      {
      // Place your code here
   j++;
  
   decbin(j);
  
   if (S==0){                     //условия для того, чтобы отображалось не "005 "  а "5" - нолики убирают...
                buffer[0]=1;
            }
               else {
              buffer[0]=48+S;
                    };
  
    if ((D==0)&&(S==0)){  
                buffer[1]=1;
            }
               else {
              buffer[1]=48+D;
                    };                
      buffer[2]=48+E;

lcd_gotoxy(7,1);
lcd_puts(buffer);

if (j==150) {j=0;}; //считаем до 150

S=0;
D=0;
E=0;

delay_ms(100);
};

....
}

Для attiny2313 размер кода со sprintf около 92%, а таким способом - около 45%...


--------------------
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 17:52
Рейтинг@Mail.ru


Страница сгенерированна за 0.01595 секунд с 7
ELECTRONIX ©2004-2016