Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Проблема с sscanf_P
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
alux
Для преобразования строки в целое число попробовал сделать так:
Код
sscanf_P(lcd_buf, "%d", &mn);
printf_P("\n\rMONTH %d", mn);
...................
sscanf_P(lcd_buf, "%d", &dt);
printf_P("\n\rDATE %d", dt);
....................
sscanf_P(lcd_buf, "%d", &yr);
printf_P("\n\rYEAR %d", yr);
rtc_set_time(0,min,hr,dy,dt,mn,yr-2000);

Терминал честно выводит переменную yr= 2007. Точно так же делаю с другими переменными времени. Проблема в том, что эти переменные не пишутся в RTC. Вернее пишут, но 0. Точнее записалось только значение года ("2007").Хотя если явно инициализировать эти переменные какими-то значениеми или преобразовать с помощью ф-ции StrToInt(), то эти "какие-то"значения или результат ф-ции StrToInt() запишутся без проблем в RTC. В ф-ции rtc_set_time() каждое значение делается dec2bcd. В чем дело?
tag
Цитата(alux @ Dec 21 2007, 10:38) *
Для преобразования строки в целое число попробовал сделать так:
Код
sscanf_P(lcd_buf, "%d", &yr);
printf_P("\n\rYEAR %d", yr);
rtc_set_time(0,min,hr,dy,dt,mn,yr-2000);

Терминал честно выводит переменную yr= 2007. Точно так же делаю с другими переменными времени. Проблема в том, что эти переменные не пишутся в RTC. Вернее пишут, но 0. Точнее записалось только значение года ("7").Хотя если явно инициализировать эти переменные какими-то значениеми или преобразовать с помощью ф-ции StrToInt(), то эти "какие-то"значения или результат ф-ции StrToInt() запишутся без проблем в RTC. В ф-ции rtc_set_time() каждое значение делается dec2bcd. В чем дело?



...подробней можно? Покажите прототипы функций и как объявлены переменные
alux
Цитата(tag @ Dec 21 2007, 12:25) *
...подробней можно? Покажите прототипы функций и как объявлены переменные

Переменные объявлены как глобальные. В компиляторе включена опция --string_literals_in_flash.
void rtc_set_time(unsigned char second, unsigned char minute, unsigned char hour,
unsigned char day, unsigned char date, unsigned char month, unsigned int year);

int sscanf_P(const char *__s, PGM_P __format,…);
int printf_P(PGM_P __format,…);
Использую CLIB
sergik_vrn
Цитата(alux @ Dec 21 2007, 10:38) *
Для преобразования строки в целое число попробовал сделать так:
Терминал честно выводит переменную yr= 2007. Точно так же делаю с другими переменными времени. Проблема в том, что эти переменные не пишутся в RTC. Вернее пишут, но 0. Точнее записалось только значение года ("7").Хотя если явно инициализировать эти переменные какими-то значениеми или преобразовать с помощью ф-ции StrToInt(), то эти "какие-то"значения или результат ф-ции StrToInt() запишутся без проблем в RTC. В ф-ции rtc_set_time() каждое значение делается dec2bcd. В чем дело?

а все остальные переменные тоже выводите в терминал, и они тоже имеют правильные значения? и прям таки если после вывода в терминал эти переменные инициализировать повторно тем же значением, то все нормально пишется? чудеса прям какие-то получаются
alux
Цитата(sergik_vrn @ Dec 21 2007, 14:15) *
чудеса прям какие-то получаются

Все остальные переменные точно так же вывожу на терминал. Чудес не бывает. Должно быть какое-то логическое объяснение.
sergik_vrn
Цитата(alux @ Dec 21 2007, 13:41) *
Все остальные переменные точно так же вывожу на терминал. Чудес не бывает. Должно быть какое-то логическое объяснение.

вот именно, что должно. поскольку у значений памяти нет, должно быть все равно, откуда они берутся - если у Вас х == 5, и это значение видно в терминале, то выполнение операции х = 5 не должно влиять на последующий вызов f(x), иначе это чудеса и есть.
рыть надо в сторону определения разницы между результатом выполнения sscanf() и простым присваиванием. для начала я бы напечатал отладочную информацию на предмет выполнения условия равентсва тех значений, что вы получаете из sscanf() с теми, которые Вы ожидаете получить
Dog Pawlowa
Цитата(alux @ Dec 21 2007, 11:38) *
Проблема в том, что эти переменные не пишутся в RTC. Вернее пишут, но 0. Точнее записалось только значение года ("7").Хотя если явно инициализировать эти переменные какими-то значениеми или преобразовать с помощью ф-ции StrToInt(), то эти "какие-то"значения или результат ф-ции StrToInt() запишутся без проблем в RTC. В ф-ции rtc_set_time() каждое значение делается dec2bcd. В чем дело?

А почему Вы решили, что RTC способен принять это значение года одной переменной?
Какой RTC вы используете? Как кодируется год в нем?
tag
Цитата(alux @ Dec 21 2007, 12:08) *
Переменные объявлены как глобальные. В компиляторе включена опция --string_literals_in_flash.
void rtc_set_time(unsigned char second, unsigned char minute, unsigned char hour,
unsigned char day, unsigned char date, unsigned char month, unsigned int year);

int sscanf_P(const char *__s, PGM_P __format,…);
int printf_P(PGM_P __format,…);
Использую CLIB



...практически ничего не прояснили. Код покажите пожалуйста.
alux
Цитата(Dog Pawlowa @ Dec 21 2007, 16:17) *
А почему Вы решили, что RTC способен принять это значение года одной переменной?

Потому что, у DS1338 год пишется переменной в диапазоне 0...99.
Код
void rtc_set_time(unsigned char second, unsigned char minute, unsigned char hour,
                  unsigned char day, unsigned char date, unsigned char month, unsigned int year)
{
    i2c_start(RTC_ADDR|W);          // write slave address + write
    i2c_write(0x00);                  // write register address, 1st clock register
    
    //Установить системное время :
    i2c_write(dec2bcd(second));
    i2c_write(dec2bcd(minute));
    i2c_write(dec2bcd(hour));  

    // Установить системную дату :
    i2c_write(dec2bcd(day));  
    i2c_write(dec2bcd(date));  
    i2c_write(dec2bcd(month));
    i2c_write(dec2bcd(year));  
    
    // Настроить выход на генерацию 32768Гц :
    i2c_write(0x13);                  // enable sqwe, 32768Hz output, clear OSF bit
    i2c_stop();    
}

Весь код показывать не буду. Слишком большой. Суть проблемы в следующем: в результате действия программы загрузил в lcd_buf строку"2007". Сделал sscanf_P в переменную YR. Вывел на терминал значение YR. Показывает 2007. Дальше загрузил в lcd_buf строку"12". Сделал sscanf_P в переменную MN. Вывел на терминал значение MN. Показывает 12. И т.д. со следующими переменными. Когда инициализировал таким образом последнюю переменную MIN, вызываю ф-цию rtc_set_time(). В результате - в часах - одни "0" . Кроме года. Если перед вызовом rtc_set_time() присвоить этим переменным значения непосредственно вот так: yr=2007, mn=12, dt=23, dy=6, ..., то эти значения запишутся в RTC.

Добавлено

Только что проверил значения переменных непосредственно перед вызовом ф-ции rtc_set_time(). Значения переменных, кроме года равны 0 ! Где-то херятся переменные. Провел простой эксперимент: Редактирую переменные в такой последовательности: YR,MN,DT,DY,HR,MIN ; на терминал вывожу значение переменной + предыдущее значение отредактированной переменной. Выяснилось, что при редактировании DT обнуляется MN и т.д. И в этом вся проблема. Но тогда вопрос в следующем. Почему простая замена функций sscanf_P на StrToInt сохраняет значения переменных? Виновата sscanf_P?

Прикладываю файл. Если кто-нибудь в нем разберется smile.gif Функция выводит статические надписи в разные строки и значения переменных с координаты х=49. Редактирование значения текущего символа, который выделен мигающим курсором , осуществляется с клавиатуры 4х4. UP, DOWN смещение курсора в пределах строки. Число с цифровой клавиатуры заменяет текущее знакоместо и переносит курсор на следующее. ENTER - сохранение отредактированной переменной. При чем когда сохраняем последнюю отредактированную переменную, то вызывается ф-ция rtc_set_time. Хочется услышать ваше мнение. Громоздко получилось или это нормально?
tag
Цитата(alux @ Dec 21 2007, 16:21) *
Весь код показывать не буду. Слишком большой. Суть проблемы в следующем: в результате действия программы загрузил в lcd_buf строку"2007". Сделал sscanf_P в переменную YR. Вывел на терминал значение YR. Показывает 2007. Дальше загрузил в lcd_buf строку"12". Сделал sscanf_P в переменную MN. Вывел на терминал значение MN. Показывает 12. И т.д. со следующими переменными. Когда инициализировал таким образом последнюю переменную MIN, вызываю ф-цию rtc_set_time(). В результате - в часах - одни "0" . Кроме года. Если перед вызовом rtc_set_time() присвоить этим переменным значения непосредственно вот так: yr=2007, mn=12, dt=23, dy=6, ..., то эти значения запишутся в RTC. Непосредственно перед вызовом ф-ции вывожу на терминал все переменные, инициализированные sscanf_P. Показывает на терминале нужные значения. А в RTC писать не хочет. Что еще непонятного?



...чудес не бывает. Например меня смущает что у вас параметр (функция rtc_set_time) year имеет тип unsigned int, а все остальные unsigned char...хотя функция dec2bcd() наверняка принимает параметр типа char. Типичная ошибка такая - порт I2C разделяется еще с каким либо устройством так что в процессе обмена с часами (при распараллеливании задач) выполняется еще обмен с этим устройством и вот вам неизвестные значения. Посмотрите может у вас переменные используются где-то еще
alux
Цитата(tag @ Dec 21 2007, 18:09) *
Например меня смущает что у вас параметр (функция rtc_set_time) year имеет тип unsigned int, а все остальные unsigned char...хотя функция dec2bcd() наверняка принимает параметр типа char.

Пусть Вас это не смущает.
Код
static unsigned int bcd2dec(unsigned int bcd);
static unsigned int dec2bcd(unsigned int dec);

Цитата(tag @ Dec 21 2007, 18:09) *
Типичная ошибка такая - порт I2C разделяется еще с каким либо устройством так что в процессе обмена с часами (при распараллеливании задач) выполняется еще обмен с этим устройством и вот вам неизвестные значения. Посмотрите может у вас переменные используются где-то еще

Ключевой вопрос : почему тогда с функцией unsigned char StrToInt(char *pStr, unsigned int *pResult);, нет такой проблемы?
Сергей Борщ
Цитата(alux @ Dec 21 2007, 15:21) *
Виновата sscanf_P?
Скорее всего виновата нехватка стека. sscanf использует довольно много стека, а ваша StrToInt гораздо меньше. Когда работает scanf, она своими данными залезает на ваши и затирает их.
alux
Цитата(Сергей Борщ @ Dec 21 2007, 19:05) *
Скорее всего виновата нехватка стека. sscanf использует довольно много стека, а ваша StrToInt гораздо меньше. Когда работает scanf, она своими данными залезает на ваши и затирает их.

Похоже на правду. Не проверял, но думаю, что так оно и есть.
Dron_Gus
А scanf("%d") случайно не на int требует указатель? Вы же ему на char даете. Соответственно 3 соседние ячейки затираются.

И попробуйте тестовые printf поставить после ВСЕХ scanf, тогда сразу понятно станет.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.