|
winavr & sprintf |
|
|
|
Oct 17 2008, 18:38
|
Частый гость
 
Группа: Свой
Сообщений: 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 читал, форум поиском пробегал......
|
|
|
|
|
 |
Ответов
(1 - 12)
|
Oct 17 2008, 19:29
|
Участник

Группа: Участник
Сообщений: 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. Этот код дан для примера.
|
|
|
|
|
Oct 17 2008, 21:01
|
Частый гость
 
Группа: Участник
Сообщений: 169
Регистрация: 31-08-05
Из: New York
Пользователь №: 8 118

|
Я бы использовал snprintf, чтобы никогда не залезть за границы массива.
--------------------
ASB
|
|
|
|
|
Oct 17 2008, 22:11
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 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 прикрутится.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Oct 18 2008, 10:56
|

Гуру
     
Группа: Модераторы
Сообщений: 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)
|
|
|
|
|
Oct 18 2008, 21:17
|
Частый гость
 
Группа: Свой
Сообщений: 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 жрет больше.
|
|
|
|
|
Oct 18 2008, 23:04
|

Гуру
     
Группа: Свой
Сообщений: 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)  ..какие будут замечание по тюнингу этого супер кода? Выкинуть  . И комментарии по поводу пожирания хидерами памяти тоже. Взять книжку по "C". Читать. "работать с контроллерами" и "бегать поиском" погодить.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Oct 19 2008, 17:29
|
Частый гость
 
Группа: Свой
Сообщений: 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. Просьба помочь советом, а не посылать к учебнику.
|
|
|
|
|
Oct 19 2008, 18:04
|
Профессионал
    
Группа: Свой
Сообщений: 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 пишет не то и не туда.
|
|
|
|
|
Oct 20 2008, 01:05
|

Местный
  
Группа: Свой
Сообщений: 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
|
|
|
|
|
Oct 20 2008, 16:18
|
Частый гость
 
Группа: Свой
Сообщений: 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
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|