|
Согласование переменных разных типов |
|
|
|
Feb 4 2010, 06:36
|

Частый гость
 
Группа: Свой
Сообщений: 194
Регистрация: 14-02-07
Из: УКРАИНА
Пользователь №: 25 344

|
Цитата(GoodNews @ Feb 4 2010, 00:22)  Если есть одна переменная у которой тип "char", вторая переменная типа "uint16_t" на которой реализован счётчик. Как их представить в переменной типа "char" для последующей записи в порт LCD? Стандартное преобразование типов С : Код { char chValH, chValL; uint16 uiCnt;
chValL = (char) (uiCnt); chValH = (char) (uiCnt >> 8); } далее далее старшую и младшую часть в порт. Если счетчик обновляется в прерывании то предусмотреть запрет прерывания во время чтения счетчика.
--------------------
"Для того чтобы избежать критики, надо ничего не делать, ничего не говорить и никем не быть" "Каждый из нас бывает дураком по крайней мере пять минут в день; мудрость заключается в том, чтобы не превысить лимит." Элберт Хаббард
|
|
|
|
|
Feb 4 2010, 08:54
|

Частый гость
 
Группа: Участник
Сообщений: 88
Регистрация: 12-01-09
Из: Minsk (BY)
Пользователь №: 43 259

|
Цитата(Палыч @ Feb 4 2010, 09:44)  Вам - что, нужно получить последовательность символов, соответствующих значению счетчика? Тогда - функция sprintf. Ну, и поместить эту последовательность в переменную массив char'ов... Как-то так: Код uint16_t Cnt; char Array[10]; sprintf(Array, "%d", Cnt); Я хотел взять некоторое значение, например 125,3876, добавить к нему текст (в а конкретно "MHz"), и всё это отправить в lcd_putdata() в соответствующую строку дисплея (запись в дисплей у меня реализована, выбор строк тоже). Вот функция записи в дисплей: Код void lcd_putchar(char data) { LCD_CTL |= LCD_RS; //Включаем режим обработки данных дисплеем (если бит инвертирован, то - обработка инструкций) LCD_PORT = data; lcd_strobe(); LCD_CTL &= ~(LCD_RS|LCD_RW); } void lcd_putdata(uint8_t line, char* data) { lcd_select_addr(line); while(*data) { lcd_busy(); lcd_putchar(*data++); } } int main(void) { /// lcd_init(); lcd_putdata(1, "1234567890ABCDEF"); lcd_putdata(2, "GHIJKLMNOPQRSTUV"); lcd_putdata(3, "WXYZ!@#$%^&*()_+"); /// ..... }
|
|
|
|
|
Feb 4 2010, 09:05
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(GoodNews @ Feb 4 2010, 11:54)  Я хотел взять некоторое значение, например 125,3876, добавить к нему текст (в а конкретно "MHz"), и всё это отправить в lcd_putdata() в соответствующую строку дисплея (запись в дисплей у меня реализована, выбор строк тоже). Ну, так и воспользуйтесь функцией sprintf - это самый простой, но, правда, и самый затратный по памяти способ. Правда, я не понял как Вы из целого значения желаете получить "125,3876"? Если в целой переменной у Вас храниться частота в килогерцах, то более 65535 поместить в неё не удастся... PS. Для переменной типа uint_t нужно использовать sprintf(Array, "% u", Cnt);
|
|
|
|
|
Feb 4 2010, 09:20
|

Частый гость
 
Группа: Участник
Сообщений: 88
Регистрация: 12-01-09
Из: Minsk (BY)
Пользователь №: 43 259

|
Цитата(Палыч @ Feb 4 2010, 11:05)  Ну, так и воспользуйтесь функцией sprintf - это самый простой, но, правда, и самый затратный по памяти способ. Правда, я не понял как Вы из целого значения желаете получить "125,3876"? Если в целой переменной у Вас храниться частота в килогерцах, то более 65535 поместить в неё не удастся...
PS. Для переменной типа uint_t нужно использовать sprintf(Array, "%u", Cnt); Тут скорее надо float, я не подумал как-то. По памяти - я отрабатываю каждый модуль отдельно (LCD, kbd ...), а потом всё будет собрано для mega128.
|
|
|
|
|
Feb 4 2010, 16:12
|

Частый гость
 
Группа: Участник
Сообщений: 88
Регистрация: 12-01-09
Из: Minsk (BY)
Пользователь №: 43 259

|
Цитата(rezident @ Feb 4 2010, 15:18)  Да, да. Сначала во float преобразовать, а потом sprintf-ом на LCD вывести, и для этого mega на xmega поменять, потому что размера ОЗУ не хватает.  Вы бы погуглили вначале по теме BCD преобразования и использования fixed point арифметики. На форуме уже раз сто мусолили эти темы. так планируется в дальнейшем использование mega128, просто mega16 доступнее в плане цены и если убью при прошивке (STK600 можно найти только на eBay), вот поэтому на mega16 испытываю модули по отдельности (lcd и пр.).
|
|
|
|
|
Feb 5 2010, 12:09
|

Частый гость
 
Группа: Участник
Сообщений: 88
Регистрация: 12-01-09
Из: Minsk (BY)
Пользователь №: 43 259

|
Решил попробовать использовать такой вариант кода (всё-таки float): Код char* get_freq(uint32_t Fr, uint8_t type) { static char Str[16]; static float tmp; tmp = Fr / 1000U; switch(type) { case (0): //KHz sprintf(Str, "%4.6fKHz", (double)tmp); return Str; break; /* case (1): //MHz sprintf(Str, "%4.6fMHz", (double)tmp); return Str; break; */ } return 0; } int main(void) { uint32_t i = 560000; lcd_init(); /*...*/ lcd_putdata(1, get_freq(i, 0)); /*...*/ } Проблема в sprintf(Str, "%4.6fKHz", (double)tmp), так как в итоге ничего не отображается (просто пустая строка). Почему не хочет показывать, ведь вроде функцию вызвал правильно?
|
|
|
|
|
Feb 5 2010, 13:31
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(GoodNews @ Feb 5 2010, 15:09)  Почему не хочет показывать, ведь вроде функцию вызвал правильно? Функция printf (и еже с ними) ну очень прожорлива до памяти. Чтобы как-то это обойти, обычно, поставляется несколько вариантов библиотек, в которых от самых "худых" функций (поддерживают только сhar и int) до самых навороченных (это Ваш вариант - поддерживают плавучку). В зависимости от используемой среды разработки нужно как-то указать: какой вариант использовать... Цитата(GoodNews @ Feb 5 2010, 15:09)  Решил попробовать использовать такой вариант кода (всё-таки float): Код char* get_freq(uint32_t Fr, uint8_t type) { static char Str[16]; static float tmp; tmp = Fr / 1000U; /*...*/ } Такое вычисление tmp - никуда не годится! Правильно записать tmp = Fr / 1000.0; Цитата(GoodNews @ Feb 5 2010, 15:09)  Код sprintf(Str, "%4.6fKHz", (double)tmp); Преобразование к double - абсолютно лишнее
|
|
|
|
|
Feb 5 2010, 14:02
|

Частый гость
 
Группа: Участник
Сообщений: 88
Регистрация: 12-01-09
Из: Minsk (BY)
Пользователь №: 43 259

|
Цитата(Палыч @ Feb 5 2010, 15:27)  Функция printf (и еже с ними) ну очень прожорлива до памяти. Чтобы как-то это обойти, обычно, поставляется несколько вариантов библиотек, в которых от самых "худых" функций (поддерживают только сhar и int) до самых навороченных (это Ваш вариант - поддерживают плавучку). В зависимости от используемой среды разработки нужно как-то указать: какой вариант использовать...
Такое вычисление tmp - никуда не годится! Правильно записать tmp = Fr / 1000.0;  среда разработки - Vim, набор библиотек - avr-libc, компилятор - avr-gcc, библиотека stdio.h из комплекта avr-libc. Цитата(Палыч @ Feb 5 2010, 15:31)  Преобразование к double - абсолютно лишнее без него ругается, что tmp - float, а %4.6f - double!
Сообщение отредактировал GoodNews - Feb 5 2010, 14:03
|
|
|
|
|
Feb 5 2010, 19:35
|

Частый гость
 
Группа: Участник
Сообщений: 88
Регистрация: 12-01-09
Из: Minsk (BY)
Пользователь №: 43 259

|
Цитата(ukpyr @ Feb 5 2010, 21:06)  а что вы передаете в lcd_putdata (что возвращает get_freq) ? в lcd_putdata уходит char (который возвращает get_freq), так как если передавать в чистом виде числовое значение, то дисплей его считает как код символа и соответственно показывает символ, соответствующий полученному значению.
|
|
|
|
|
Feb 6 2010, 17:29
|

Частый гость
 
Группа: Участник
Сообщений: 88
Регистрация: 12-01-09
Из: Minsk (BY)
Пользователь №: 43 259

|
На данный момент решён вопрос с отображение значений во float. Действия следующие: Код char* get_freq() { static char Str[16]; double tmp; tmp = 560.1223; sprintf(Str, "%4.4fkHz", tmp); return Str;
} Т.е. в таком виде работает отлично (плюс дополнительные команды к линкеру для подключения внешних библиотек) + 2к к размеру флэша.
|
|
|
|
|
Feb 7 2010, 12:30
|

Частый гость
 
Группа: Участник
Сообщений: 88
Регистрация: 12-01-09
Из: Minsk (BY)
Пользователь №: 43 259

|
Вариант #2. В таком виде - работает. Если раскомментить и вызвать через функцию - виснет. Почему? Проц поставил ATmega32. main.hКод #ifndef _MAIN_H #define _MAIN_H #endif #define khzFmt "F=%4.4fkHz" #define mhzFmt "F=%3.4fMHz" char buf[16]; main.cКод #ifndef F_CPU #define F_CPU 8000000UL #endif #include <avr/io.h> #include <stdio.h> #include <stdint.h> #include "lcd.h" #include "main.h" /*void hzToStr(char* buf, const uint32_t hz, uint8_t freqSelect) { double fd = (float)hz / 1000.0f; if (freqSelect == 0) snprintf(buf, sizeof(buf), khzFmt, fd); if (freqSelect == 1) snprintf(buf, sizeof(buf), mhzFmt, fd); }*/ int main(void) { uint32_t hz = 1325235; lcd_init(); double fd = (double)hz / 1000.0f; snprintf(buf, sizeof(buf), khzFmt, fd); lcd_putdata(1, (char*)buf); //hzToStr(buf, hz, 0); //lcd_putdata(1, (char*)buf); lcd_putdata(2, "adflasdf"); while(1){;} }
|
|
|
|
|
Feb 7 2010, 13:16
|

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

|
Если уж использовать в WinAVR printf, то тогда так: Код void lcd_putchar(char data); // то, что уже есть
int lcd_file_putc(char ch, FILE * stream) { (void) stream; lcd_putchar(ch); return 0; }
// аналогично создаём и для UART void uart_putchar(char ch); // он может вообще в кольцевой буфер помещать, ждать только если места нет int uart_file_putc(char ch, FILE * stream) { (void) stream; if(ch == '\n') uart_putchar('\r'); uart_putchar(ch); return 0; }
FILE lcd_file = FDEV_SETUP_STREAM(lcd_file_putc, 0, _FDEV_SETUP_WRITE); FILE uart_file = FDEV_SETUP_STREAM(uart_file_putc, uart_file_getc, _FDEV_SETUP_WRITE);
#define lcd_stream (&lcd_file); #define uart_stream (&uart_file);
fprintf_P( lcd_stream, PSTR("Freq %6.3fMHz"), freq);
fputs_P( PSTR("Hello!\n"), uart_stream); fprintf_P( uart_stream, PSTR("Freq %6.3fMHz"), freq); А для ЖКИ можно и вообще так: Код void lcd_printf_P(uint8_t x, uint8_t y, prog_char *fmt, ...) __attribute__((format(printf, 3, 4)));
void lcd_printf_P(uint8_t x, uint8_t y, prog_char *fmt, ...) { lcd_gotoxy(x,y);
va_list vl; va_start(vl, fmt); vfprintf_P( lcd_stream, fmt, vl); va_end(vl); }
lcd_printf_P(1, 5, PSTR("%6.3MHz"), freq); Раз уж платить увеличенным расходом кода, то хоть знать за что. Цитата(GoodNews @ Feb 7 2010, 14:30)  Если раскомментить и вызвать через функцию - виснет. Почему? Да так вроде всё нормально. Не вижу причины :-( Определять переменные в .h нехорошо (это я про char buf[16]), но к зависанию это не имеет отношения.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Feb 7 2010, 15:49
|

Частый гость
 
Группа: Участник
Сообщений: 88
Регистрация: 12-01-09
Из: Minsk (BY)
Пользователь №: 43 259

|
Цитата(ReAl @ Feb 7 2010, 15:16)  Если уж использовать в WinAVR printf Собственно я не WinAVR использую. Платформа Linux, ядро 2.6.28-17_x86-64, компилятор AVR-GCC, прогер - avrdude, программатор - AVRISP (JONIS+ в запасе), набор библиотек avr-libc.
|
|
|
|
|
Feb 7 2010, 17:05
|

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

|
Цитата(GoodNews @ Feb 7 2010, 17:49)  Собственно я не WinAVR использую. Платформа Linux, ядро 2.6.28-17_x86-64, компилятор AVR-GCC, прогер - avrdude, программатор - AVRISP (JONIS+ в запасе), набор библиотек avr-libc. Да это я по привычке, конечно, имелись ввиду avr-gcc и avr-libc, а инсталлятором этого добра и средой для выполнения служат WinAVR+Windows или apt + Linux - какая разница? У меня проекты собираются и там, и там.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
Feb 7 2010, 17:51
|

Частый гость
 
Группа: Участник
Сообщений: 88
Регистрация: 12-01-09
Из: Minsk (BY)
Пользователь №: 43 259

|
Цитата(ReAl @ Feb 7 2010, 19:05)  Да это я по привычке, конечно, имелись ввиду avr-gcc и avr-libc, а инсталлятором этого добра и средой для выполнения служат WinAVR+Windows или apt + Linux - какая разница? У меня проекты собираются и там, и там. Ну там сильно отличий наверное нету. Только библиотеки по-разному называются (ioavr.h против io.h насколько я помню). Но не принципиально. Я думаю что реализую через int, так как всё-таки работает не так, как хотелось бы. Пока попробую через int в общем. Спасибо!
|
|
|
|
|
Feb 8 2010, 16:37
|

Частый гость
 
Группа: Участник
Сообщений: 88
Регистрация: 12-01-09
Из: Minsk (BY)
Пользователь №: 43 259

|
Цитата(XVR @ Feb 8 2010, 13:01)  Пока видна 1 ошибка - sizeof(buf) в hzToStr и main не равны, т.к. в main это массив, а в hzToStr это указатель (параметр) Его надо было тоже как указатель использовать в main?
|
|
|
|
|
Feb 14 2010, 09:52
|

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

|
Цитата(GoodNews @ Feb 7 2010, 19:51)  Ну там сильно отличий наверное нету. Только библиотеки по-разному называются (ioavr.h против io.h насколько я помню). Вообще нету. #include <avr/io.h> и побежали. Я же говорю - компилирутся и под вин, и под убунтой одни и те же проекты без изменений вообще и без ОС-зависимых define-ов. Цитата(GoodNews @ Feb 8 2010, 18:37)  Его надо было тоже как указатель использовать в main? Нет, в hzToStr нужно отдельным параметром передавать длину буфера. В первый просмотр я, наверное, ослеп, раз такое не заметил :-(
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0
|
|
|