Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: winavr & sprintf
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
TechMike
Не получается преобразовать char в string но в шестнадцатеричной системе.
Цель: выплюнуть в usart серийник ds1990 в шестнадцатеричном виде, делаю для примера так:
Код
#include <stdio.h>
char idd2;
sprintf(idd2,"%02X",10);

Но в idd2 нет 0C, что я делаю не так?
Компилятор AVRstudio 4.12 + WinAVR-20050214, тело mega16+8мгц кварц.

P.S. Немного терпения плс, так как рабтаю с контролерами не давно, avr-libc-user-manual-1.2.3.pdf читал, форум поиском пробегал......
Nick_Shl
Цитата(TechMike @ Oct 17 2008, 21:38) *
Не получается преобразовать char в string но в шестнадцатеричной системе.
Цель: выплюнуть в usart серийник ds1990 в шестнадцатеричном виде, делаю для примера так:
Код
#include <stdio.h>
char idd2;
sprintf(idd2,"%02X",10);

Но в idd2 нет 0C, что я делаю не так?
Если коротко - все!
Нету в Си стрингов. Только массивы чаров. В данном случае вы объявили один символ. sprintf принимает первым аргументом указатель, а вы ему его не передали.
Правильно так:
Код
#include <stdio.h>
char idd2[тут количество символов в массиве];
sprintf(idd2,"%02X",10);
либо так:
Код
#include <stdio.h>
char idd2;
sprintf(&idd2,"%1X",10);
Но тогда вы получите один символ и если sprintf выдаст больше - потрете всё что лежит за idd2. Этот код дан для примера.
Aleksandr Baranov
Я бы использовал snprintf, чтобы никогда не залезть за границы массива.
ReAl
Цитата(TechMike @ Oct 17 2008, 21:38) *
Не получается преобразовать char в string но в шестнадцатеричной системе.
Цель: выплюнуть в usart серийник ds1990 в шестнадцатеричном виде, делаю для примера так:
Ну если цель _только_ выплюнуть серийник в 16-ричном виде, то даже я сделал бы в что-то в духе:

Код
void put_nibble_hex(uint8_t n)
{
    n &= 0x0F;
    n += '0';
    if( n > '9' ) n += 'A' - '0' - 10;
    uart_put_char(n);
}


void put_byte_hex(uint8_t b)
{
    put_nibble_hex( b >> 8);
    put_nibble_hex( b );
}


А если хочется сервис printf, то тогда лучше не буфер выделять каждый раз и snprintf() использовать, а, как я уже писал, делать так:

Код
#include <stdio.h>

FILE uart_file = FDEV_SETUP_STREAM(uart_putc, 0, _FDEV_SETUP_WRITE);

    fprintf_P( uart_file, PSTR("%02X\n"), b); // форматная строка во флеше
    fprintf( uart_file, "%02X\n", b); // если вдруг хочется - форматная строка в ОЗУ

А если вторым параметром FDEV_SETUP_STREAM дать uart_getc, то и fscanf прикрутится.
Сергей Борщ
Цитата(Nick_Shl @ Oct 17 2008, 22:29) *
Код
#include <stdio.h>
char idd2;
sprintf(&idd2,"%1X",10);
Но тогда вы получите один символ и если sprintf выдаст больше - потрете всё что лежит за idd2. Этот код дан для примера.
А sprintf выдаст больше - он добавляет завершающий ноль последним символом в результирующую строку. Так что такой код не годится даже в качестве примера.


Цитата(ReAl @ Oct 18 2008, 01:11) *
Код
void put_nibble_hex(uint8_t n)
{
    n &= 0x0F;
    n += '0';
    if( n > '9' ) n += 'A' - '0' - 10;
    uart_put_char(n);
}
Как вариант:
Код
void put_nibble_hex(uint8_t n)
{
    static prog_char const Table[] = "0123456789ABCDEF";
    uart_put_char(pgm_read_byte(&Table[n & 0x0F]));
}
demiurg_spb
А ещё есть замечательные функции itoa и utoa.
См. avr-libc-user-manual.
TechMike
Изначально серийник ds1990 получаю в виде массива char, так что думаю вот такой вариант будет самое оно:
Код
#include <stdio.h>
char idd1[8];
char idd2[8];

ReadKey(idd1,2); //в idd1 серийник таблетки
sprintf(idd2,"%02X",idd1);
//выводим в USART idd2


Вроде тут уже ошибисть не в чем, какие будут замечание по тюнингу этого супер кода?

P.S. Легче конечно не использовать sprintf, а например в цикле дергать функции аналогичные написаным ReAl, так как памяти stdio.h жрет больше.
zltigo
Цитата(Сергей Борщ @ Oct 18 2008, 12:56) *
static prog_char const Table[] = "0123456789ABCDEF";

Код
    static prog_char const Table[16] = "0123456789ABCDEF";

ибо лишний байт, а на некоторых платформах вообще целых 4 лишних никчему.

Цитата(TechMike @ Oct 18 2008, 23:17) *
..какие будут замечание по тюнингу этого супер кода?

Выкинуть sad.gif. И комментарии по поводу пожирания хидерами памяти тоже. Взять книжку по "C". Читать.
"работать с контроллерами" и "бегать поиском" погодить.
TechMike
Не получается, делаю так:
Код
#include <stdio.h>
char idd1[8];
char idd2[8];

ReadKey(idd1,2); //в idd1 серийник таблетки (8 байт)
sprintf(idd2,"%02X",(int)idd1);
USART_Send_srt(idd2); //выводим в USART idd2


В терминале выводит число "13A", хотя в idd1 всего 8 байт, почему так????

P.S. Просьба помочь советом, а не посылать к учебнику.
sergeeff
Цитата(TechMike @ Oct 19 2008, 21:29) *
Не получается, делаю так:
Код
#include <stdio.h>
char idd1[8];
char idd2[8];

ReadKey(idd1,2); //в idd1 серийник таблетки (8 байт)
sprintf(idd2,"%02X",(int)idd1);
USART_Send_srt(idd2); //выводим в USART idd2


В терминале выводит число "13A", хотя в idd1 всего 8 байт, почему так????

P.S. Просьба помочь советом, а не посылать к учебнику.


А что книжки почитать влом? А перед коллегами по форуму выглядеть не с лучшей стороны нормально?

Формат "%02X" в Вашем понимании, что означает? А число "13A" - сколько байт занимает? А int в AVR - это сколько байт? Вот разберитесь в этих несложных моментах и все получится. (если еще сможете понять в чем разница в вызове функции с передачей параметров по значению и по ссылке). Что-то мне представляется, что ReadKey пишет не то и не туда.
MTh
Цитата(TechMike @ Oct 19 2008, 20:29) *
Не получается, делаю так:
Код
#include <stdio.h>
char idd1[8];
char idd2[8];

ReadKey(idd1,2); //в idd1 серийник таблетки (8 байт)
sprintf(idd2,"%02X",(int)idd1);
USART_Send_srt(idd2); //выводим в USART idd2


В терминале выводит число "13A", хотя в idd1 всего 8 байт, почему так????

P.S. Просьба помочь советом, а не посылать к учебнику.


Во-первых внимательно читайте что Вам пишут. Если нужно вывести 8 байт, то не забываем про \0 в конце. printf именно по нему определяет что пора остановиться. Второе, зачем каставали к int ? У вас передано название массива - что воспрнимается как указатель, а Вы еше кастанули к int. Компилер сишный использует двухбайтовые указатели даже для 8-и битной платформы. Вот и вывелось двухбайтное число (0х13А).
Третье, у Вас массив из hex-ов. Я может не прав (в плане вывода массива - можно использовать цикл и конкатенацию) но попробуйте сделать так - самый быстрый способ проверки:
Код
char *str[9];
unsigned char idd2[8];
sprintf(str, "%02X%02X%02X%02X%02X%02X%02X%02X", idd2[0], idd2[1], idd2[2], idd2[3], idd[4], idd2[5], idd2[6], idd2[7]);
USART_Send_srt(*str); //выводим в USART idd2

Почитайте, что есть указатель, что есть строка. Чем массив char'ов отличается от стринга. Форматирование. Преобразование типов. Работу с указателями. Программит станет намного проще.
И выкиньте CV AVR. У него си очень далек от стандартного. Потому собирать кочки будете сами и расхлебывать тоже.
TechMike
Цитата(MTh @ Oct 20 2008, 05:05) *
Во-первых внимательно читайте что Вам пишут. Если нужно вывести 8 байт, то не забываем про \0 в конце. printf именно по нему определяет что пора остановиться. Второе, зачем каставали к int ? У вас передано название массива - что воспрнимается как указатель, а Вы еше кастанули к int. Компилер сишный использует двухбайтовые указатели даже для 8-и битной платформы. Вот и вывелось двухбайтное число (0х13А).
Третье, у Вас массив из hex-ов. Я может не прав (в плане вывода массива - можно использовать цикл и конкатенацию) но попробуйте сделать так - самый быстрый способ проверки:
Код
char *str[9];
unsigned char idd2[8];
sprintf(str, "%02X%02X%02X%02X%02X%02X%02X%02X", idd2[0], idd2[1], idd2[2], idd2[3], idd[4], idd2[5], idd2[6], idd2[7]);
USART_Send_srt(*str); //выводим в USART idd2

Почитайте, что есть указатель, что есть строка. Чем массив char'ов отличается от стринга. Форматирование. Преобразование типов. Работу с указателями. Программит станет намного проще.
И выкиньте CV AVR. У него си очень далек от стандартного. Потому собирать кочки будете сами и расхлебывать тоже.


Со всем Вами названым ознакомился. Респект Вам, все получилось, спасибо за терпение.
Код
#include <stdio.h>
char idd1[8];
char idd2[9];
ReadKey(idd1,2);
sprintf(idd2, "%02X%02X%02X%02X%02X%02X%02X%02X", idd1[0], idd1[1], idd1[2], idd1[3], idd1[4], idd1[5], idd1[6], idd1[7]);
USART_Send_srt(idd2); //выводим в шестнадцатеричном виде серийник ds1990
MTh
Пожалуйста.
Рад что все получилось.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.