Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей... |
20.05.2007, 23:39
|
|
Прохожий
Регистрация: 13.04.2007
Сообщений: 7
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Приведение типов
Обнаружил, что в си для 8051 нет функций ftoa, fcnv, ecnv...
Вобщем, надо перевести double (или что угодно с плавающей точкой) в строку.
Может кто-нибудь помочь?
|
|
|
|
20.05.2007, 23:52
|
|
Прописка
Регистрация: 21.06.2003
Сообщений: 118
Сказал спасибо: 0
Сказали Спасибо 19 раз(а) в 19 сообщении(ях)
|
unsigned char IntFC(float fcf)
{
xdata float k;
xdata unsigned char n;
if (fcf › 255) return(0xff);
n=0;
k=0;
while (k‹fcf)
{
k = k+1;
n++;
}
return(n);
}
unsigned char IntFC_m(float fcf)
{
xdata float k;
xdata unsigned char n;
if (fcf › 255) return(0xff);
n=0;
k=0;
while (k‹fcf)
{
k = k+1;
n++;
}
return(n);
}
/* ---------------------------- */
/*Процедура преобразования FLOAT в массив ch[_]
f - float переменная;
ch[] - массив char
*/
void FloatToChar(void)
{
//Формируем FLOAT-указатель на массив
fpnt = (float*)&ch[0];
*fpnt = f;
return;
}
/*Процедура преобразования массива ch[_] в Float
f - float переменная;
ch[] - массив char
*/
void CharToFloat(void)
{
fpnt = (float*)&ch[0];
f = *fpnt;
}
/*---------------------------------------------------------*/
// Процедура преобразования Char в двоично-десятичный вид
unsigned char CharToBinDec(unsigned char ctb)
{
xdata unsigned char ctb1,ctb2,ctb3;
ctb2 = 0;
ctb3 = 0;
ctb1 = ctb;
if (ctb1›99) return(99);
if (ctb1==0) return(0);
while (ctb1!=0)
{
ctb1--;
ctb2++;
if (ctb2==10)
{
ctb2 = 0;
ctb3++;
}
}
//
ctb3 = ctb3 * 16;
ctb2 = ctb3|ctb2;
return(ctb2);
}
- это конечно не прямой ответ, а в твоем случае я вижу такое решение:
1 Разделить число на целую и дробную части
2 посчитать количество десятых, сотых, тысячных и тп
3 произвести текстовое преобразование через case
|
|
|
|
21.05.2007, 19:39
|
|
Прохожий
Регистрация: 13.04.2007
Сообщений: 7
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Мне кажется оптимально сделать так:
1) Умножать число на 10, пока оно не станет целым, попутно подсчитывая количество умножений.
2) Последовательно делить число на 10, преобразуя остатки в код символа, складывать их в строку.
3) Исходя из количества умножений в п.1, засунуть в нужное место точку.
Проблема возникает с первым пунктом: как определить целое число или нет?
Я вижу два варианта:
1) Есть функция modf, которая выдает дробную часть. Типа, если дробная часть равна нулю, значит число уже целое. Однако функция вроде как предназначена для типа float, а мне надо работать с double.
2) Каким-нибудь образом округлить число и сравнить с оригиналом: равно, значит целое. Но, опять же, как округлить 6-байтовый double я не представляю...
|
|
|
|
21.05.2007, 20:36
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.05.2006
Адрес: Москва
Сообщений: 3,559
Сказал спасибо: 76
Сказали Спасибо 326 раз(а) в 230 сообщении(ях)
|
Re: Приведение типов
Сообщение от Hormiga
|
Обнаружил, что в си для 8051 нет функций ftoa, fcnv, ecnv...
Вобщем, надо перевести double (или что угодно с плавающей точкой) в строку.
Может кто-нибудь помочь?
|
если для вывода "наружу" то printf
вот примеры - avr123.nm.ru/z5.htm
и /z4.htm
__________________
Обучалка AVR PIC ARM начинающим программирование курс самоучитель шаг за шагом с нуля, CVAVR, PROTEUS, MPLAB, WinAVR, IAR, KEIL электроника - http://proavr.narod.ru
|
|
|
|
21.05.2007, 20:56
|
|
Прохожий
Регистрация: 13.04.2007
Сообщений: 7
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Вывод на экран и коды символов там далеко не ASCII, поэтому и приходится писать ручками.
|
|
|
|
21.05.2007, 20:59
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.05.2006
Адрес: Москва
Сообщений: 3,559
Сказал спасибо: 76
Сказали Спасибо 326 раз(а) в 230 сообщении(ях)
|
Дак если там кодировка "не та" чем бы вам помогли СТАНДАРТНЫЕ фкнкции ftoa, fcnv, ecnv ????
__________________
Обучалка AVR PIC ARM начинающим программирование курс самоучитель шаг за шагом с нуля, CVAVR, PROTEUS, MPLAB, WinAVR, IAR, KEIL электроника - http://proavr.narod.ru
|
|
|
|
21.05.2007, 21:33
|
|
Прохожий
Регистрация: 13.04.2007
Сообщений: 7
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Тем, что они подавали бы результат не сразу на выход, а в память, где я мог его "доработать напильником" (вычесть 0x20, если быть точным).
|
|
|
|
21.05.2007, 22:43
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.05.2006
Адрес: Москва
Сообщений: 3,559
Сказал спасибо: 76
Сказали Спасибо 326 раз(а) в 230 сообщении(ях)
|
так библу ПРИНТФ подрихтуйте !
__________________
Обучалка AVR PIC ARM начинающим программирование курс самоучитель шаг за шагом с нуля, CVAVR, PROTEUS, MPLAB, WinAVR, IAR, KEIL электроника - http://proavr.narod.ru
|
|
|
|
22.05.2007, 00:08
|
|
Почётный гражданин KAZUS.RU
Регистрация: 13.05.2006
Адрес: Москва
Сообщений: 3,559
Сказал спасибо: 76
Сказали Спасибо 326 раз(а) в 230 сообщении(ях)
|
преобразование int-char
свернутая версия atoi С стандарта ANSI но в отличие
от оригинала работает быстрее.
Вызывать
itoa2(5999);
результат будет в массиве asc[5]
Код:
unsigned char asc[5];
void itoa2(unsigned int binval)
{
int step[]={10000,1000,100,10,1};
unsigned int temp,val;
unsigned char i,atemp;
val=binval;
for (i=0; i‹5; i++)
{
temp=step[i];
atemp='0';
while(val ›= temp)
{
atemp++;
val-=temp;
}
asc[i]=atemp;
}
}
Не ПРОВЕРЯЛ !
__________________
Обучалка AVR PIC ARM начинающим программирование курс самоучитель шаг за шагом с нуля, CVAVR, PROTEUS, MPLAB, WinAVR, IAR, KEIL электроника - http://proavr.narod.ru
|
|
|
|
22.05.2007, 11:51
|
|
Частый гость
Регистрация: 28.08.2006
Сообщений: 12
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Для pic18 под MCC18 (в нем отсутствует sprintf для
double: 4 байта стандарт ANSI C) я использовал нижеприведенную функцию:
Код:
|
double tmp_flt;
unsigned char Bx[10];
rom const char formatP[]={2,1};
//1-й байт: число сиволов до запятой
//2-й байт: число сиволов после запятой
//char *result - указатель на RAM куда записать
//строку числа
//вызов:
/*Печать в RAM значения tmp_flt в формате: "XX.X" без позиции знака*/
tmp_flt=12.3;
DoubleToSt((double)tmp_flt,(char *)&Bx[0],(rom const char*)&formatP[0]);
void DoubleToSt(double input,char *result,rom const BYTE *format)
{
BYTE bcd[8];
BYTE * pD;
BYTE m,Xo;
union {
struct {
unsigned bit0 :1;
unsigned bit07 :7;
};
BYTE Reg8;
}cntPos;
S8 bits_after_dot, bits_before_dot;
U8 sign = 0x00;
bcd[0] = bcd[1] = bcd[2] = bcd[3] = 0;
if ( !*(U32 *)&input ) {
bcd[7] = bcd[6] = bcd[5] = bcd[4] = 0;
// return;
goto digToText;
}
if ( (*(U32 *)&input & 0x80000000) == 0x80000000) sign++;
//bits_before_dot = ((U16)( (U16)(*(U32 *)&input) ›› 16) ‹‹ 1) ›› 8;
bits_before_dot = (((*(U32 *)&input) ›› 24) ‹‹ 1);
if (*(U32 *)&input & 0x00800000) bits_before_dot |= 1;
*((U8 *)&input + 3) = 0;
*(U32 *)&input |= 0x00800000;
*(U32 *)&bcd[4] = *(U32 *)&
bits_before_dot -= 126;
bits_after_dot = 24 - bits_before_dot;
if (bits_after_dot) {
do {
*(U32 *)&bcd[0] ››= 1;
if (*(U8 *)&input & 0x01) *(U32 *)&bcd[0] |= 0x80000000;
*(U32 *)&input ››= 1;
if (bcd[1] & 0x80) bcd[1] -= 0x30;
if (bcd[1] & 0x08) bcd[1] -= 0x03;
if (bcd[2] & 0x80) bcd[2] -= 0x30;
if (bcd[2] & 0x08) bcd[2] -= 0x03;
if (bcd[3] & 0x80) bcd[3] -= 0x30;
if (bcd[3] & 0x08) bcd[3] -= 0x03;
} while (--bits_after_dot);
}
*(U32 *)&input = *(U32 *)&bcd[4];
bcd[7] = bcd[6] = bcd[5] = bcd[4] = 0;
if (bits_before_dot › 0) {
do {
bcd[4] += 0x33;
if (!(bcd[4] & 0x08)) bcd[4] -= 0x03;
if (!(bcd[4] & 0x80)) bcd[4] -= 0x30;
bcd[5] += 0x33;
if (!(bcd[5] & 0x08)) bcd[5] -= 0x03;
if (!(bcd[5] & 0x80)) bcd[5] -= 0x30;
bcd[6] += 0x33;
if (!(bcd[6] & 0x08)) bcd[6] -= 0x03;
if (!(bcd[6] & 0x80)) bcd[6] -= 0x30;
*(unsigned long *)&bcd[4] ‹‹= 1;
if (*(U32 *)&input & 0x00800000) bcd[4] |= 1;
*(U32 *)&input ‹‹= 1;
} while (--bits_before_dot);
}
bcd[0] = sign;
digToText: pD=&bcd[7];
//знак
if (sign) *result++=0x2d; else *result++=0x20;
//целая часть
for (cntPos.Reg8=7;cntPos.Reg8›0;cntPos.Reg8--)
{
Xo=*pD;
if (!cntPos.bit0)
{
Xo=(Xo››4)|(Xo‹‹4);
}
Xo=(Xo&0x0F) |0x30;
m=*format;
if (cntPos.Reg8‹=m)
{
*result++=Xo;
}
if (cntPos.bit0) Xo=*--pD;
}
format++;
//разделитель точка
if (*format)
{
*result++=0x2E;
m=6-(*format);
for (cntPos.Reg8=6;cntPos.Reg8›0;cntPos.Reg8--)
{
Xo=*pD;
if (!cntPos.bit0)
{
Xo=(Xo››4)|(Xo‹‹4);
}
Xo=(Xo&0x0F) |0x30;
if (cntPos.Reg8›m)
{
*result++=Xo;
}
if (cntPos.bit0) Xo=*--pD;
}
}
*result=0;
} |
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 22:32.
|
|