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

 
 
> winavr & sprintf
TechMike
сообщение Oct 17 2008, 18:38
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 130
Регистрация: 30-07-08
Из: Moscow
Пользователь №: 39 302



Не получается преобразовать 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 читал, форум поиском пробегал......
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 12)
Nick_Shl
сообщение Oct 17 2008, 19:29
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 17-04-08
Пользователь №: 36 850



Цитата(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. Этот код дан для примера.
Go to the top of the page
 
+Quote Post
Aleksandr Barano...
сообщение Oct 17 2008, 21:01
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 169
Регистрация: 31-08-05
Из: New York
Пользователь №: 8 118



Я бы использовал snprintf, чтобы никогда не залезть за границы массива.


--------------------
ASB
Go to the top of the page
 
+Quote Post
ReAl
сообщение Oct 17 2008, 22:11
Сообщение #4


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(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 прикрутится.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Oct 18 2008, 10:56
Сообщение #5


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(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]));
}


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Oct 18 2008, 19:14
Сообщение #6


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



А ещё есть замечательные функции itoa и utoa.
См. avr-libc-user-manual.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
TechMike
сообщение Oct 18 2008, 21:17
Сообщение #7


Частый гость
**

Группа: Свой
Сообщений: 130
Регистрация: 30-07-08
Из: Moscow
Пользователь №: 39 302



Изначально серийник 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 жрет больше.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Oct 18 2008, 23:04
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(Сергей Борщ @ 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". Читать.
"работать с контроллерами" и "бегать поиском" погодить.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
TechMike
сообщение Oct 19 2008, 17:29
Сообщение #9


Частый гость
**

Группа: Свой
Сообщений: 130
Регистрация: 30-07-08
Из: Moscow
Пользователь №: 39 302



Не получается, делаю так:
Код
#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. Просьба помочь советом, а не посылать к учебнику.
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Oct 19 2008, 18:04
Сообщение #10


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

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



Цитата(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 пишет не то и не туда.
Go to the top of the page
 
+Quote Post
MTh
сообщение Oct 20 2008, 01:05
Сообщение #11


Местный
***

Группа: Свой
Сообщений: 234
Регистрация: 28-02-06
Из: Иркутск
Пользователь №: 14 771



Цитата(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. У него си очень далек от стандартного. Потому собирать кочки будете сами и расхлебывать тоже.

Сообщение отредактировал MTh - Oct 20 2008, 01:10
Go to the top of the page
 
+Quote Post
TechMike
сообщение Oct 20 2008, 16:18
Сообщение #12


Частый гость
**

Группа: Свой
Сообщений: 130
Регистрация: 30-07-08
Из: Moscow
Пользователь №: 39 302



Цитата(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
Go to the top of the page
 
+Quote Post
MTh
сообщение Oct 23 2008, 00:46
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 234
Регистрация: 28-02-06
Из: Иркутск
Пользователь №: 14 771



Пожалуйста.
Рад что все получилось.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 30th June 2025 - 10:04
Рейтинг@Mail.ru


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