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

 
 
 
Reply to this topicStart new topic
_alex__
сообщение Mar 22 2018, 20:14
Сообщение #1


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

Группа: Участник
Сообщений: 102
Регистрация: 25-06-14
Пользователь №: 82 059



Имеетя 24-х разрядное двоичное число представленное в виде трех однобайтных (unsigned char) переменных
BYTE2,BYTE1,BYTE0 (старший -> младший байт числа)

Нужно это число пребразовать в 8 разрядов десятичного числа представленных unsigned char переменными DIGIT7...DIGIT0 (старший -> младший байт числа)

Возможно использовать только переменные unsigned char т.к. это для восьмиразрядного микроконтроллера.

Помогите написать на языке С функцию для такого преобразования.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 22 2018, 23:31
Сообщение #2


Гуру
******

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



QUOTE (_alex__ @ Mar 22 2018, 22:14) *
Возможно использовать только переменные unsigned char т.к. это для восьмиразрядного микроконтроллера.
Глупость вы тут написали. Как только вы это поймете, задача сведется к трем строчками кода.

1)пока исходое число не равно нулю
2)записать в выходной буфер остаток от деления исходного числа на 10
3)поделить исходное число на 10.


--------------------
На любой вопрос даю любой ответ
"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
Mareng
сообщение Mar 23 2018, 01:28
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 53
Регистрация: 19-02-07
Пользователь №: 25 487



Придется искать 24-разрядный микроконтроллер, иначе никак!)
Go to the top of the page
 
+Quote Post
mcheb
сообщение Mar 23 2018, 04:58
Сообщение #4


Местный
***

Группа: Участник
Сообщений: 326
Регистрация: 30-05-06
Пользователь №: 17 602



На PIC16 я делал так
CODE
uint32_t value;
uint8_t digit[8];
void lcdPrint(void)
{
digit[7] = 0;
while(value >= 10000000)
{
value -= 10000000;
++digit[7];
}
digit[6] = 0;
while(value >= 1000000 )
{
value -= 1000000;
++digit[6];
}
digit[5] = 0;
while(value >= 100000 )
{
value -= 100000;
++digit[5];
}
digit[4] = 0;
while(value >= 10000 )
{
value -= 10000;
++digit[4];
}
digit[3] = 0;
while(value >= 1000 )
{
value -= 1000;
++digit[3];
}
digit[2] = 0;
while(value >= 100 )
{
value -= 100;
++digit[2];
}
digit[1] = 0;
while(value >= 10 )
{
value -= 10;
++digit[1];
}
digit[0] = 0;
while(value >= 1 )
{
value -= 1;
++digit[0];
}
}
Go to the top of the page
 
+Quote Post
_alex__
сообщение Mar 23 2018, 09:23
Сообщение #5


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

Группа: Участник
Сообщений: 102
Регистрация: 25-06-14
Пользователь №: 82 059



Цитата(Mareng @ Mar 23 2018, 01:28) *
Придется искать 24-разрядный микроконтроллер, иначе никак!)


Есть реализация этой задачи на assembler, но не знаю как это на С перевести

Код
CBLOCK  
    DIGIT0  
    DIGIT1  
    DIGIT2  
    DIGIT3  
    DIGIT4  
    DIGIT5  
    DIGIT6  
    DIGIT7  
    BIN0    
    BIN1    
    BIN2    
        cycles  
    deccnt  
    octcnt  
    bitcnt  
ENDC

bin2dec
    CLRF   FSR
    CLRF   INDF

    clrf DIGIT0
    clrf DIGIT1
    clrf DIGIT2
    clrf DIGIT3
    clrf DIGIT4
    clrf DIGIT5
    clrf DIGIT6
    clrf DIGIT7
    clrf cycles    
    movlw 08    
    movwf octcnt
octloop:         
    incf cycles  
    movlw 03       
    movwf bitcnt
bitloop:
    rlf BIN0
    rlf BIN1
    rlf BIN2
    movlw DIGIT0
    movwf FSR
    movfw cycles
    movwf deccnt
decloop:
    rlf INDF
    movlw 0xF6
    addwf INDF,0
    btfsc STATUS,0
    movwf INDF
    incf FSR
    decfsz deccnt
    goto decloop
    decfsz bitcnt
    goto bitloop
    decfsz octcnt
    goto octloop
    return
Go to the top of the page
 
+Quote Post
Baser
сообщение Mar 23 2018, 09:46
Сообщение #6


Просто Che
*****

Группа: Свой
Сообщений: 1 567
Регистрация: 22-05-07
Из: ExUSSR
Пользователь №: 27 881



Цитата(_alex__ @ Mar 22 2018, 22:14) *
Нужно это число пребразовать в 8 разрядов десятичного числа представленных unsigned char переменными DIGIT7...DIGIT0 (старший -> младший байт числа)

Если программной памяти много, применяют sprintf()
Если же памяти мало, ищите реализации нестандартной функции ltoa()
Также есть оптимальный не очевидный алгоритм через упакованный BCD формат, поищите по слову bin2bcd

Цитата
Возможно использовать только переменные unsigned char т.к. это для восьмиразрядного микроконтроллера.

Вам выдали специальный вариант компилятора Си, поддерживающего только unsigned char ? sm.gif
Go to the top of the page
 
+Quote Post
_alex__
сообщение Mar 23 2018, 13:12
Сообщение #7


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

Группа: Участник
Сообщений: 102
Регистрация: 25-06-14
Пользователь №: 82 059



Цитата(mcheb @ Mar 23 2018, 04:58) *
На PIC16 я делал так


Спасибо! Работает. Вопрос решен.
Go to the top of the page
 
+Quote Post
megajohn
сообщение Mar 23 2018, 13:44
Сообщение #8


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

Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143



Цитата(_alex__ @ Mar 23 2018, 16:12) *
Спасибо! Работает. Вопрос решен.


чой-та коробит от такого. Может лучше так ?!

Код
char *dest = digit;
u32 div = 1000000000UL,  tmp;

while( div )
{
    tmp = (u8)( value / div);
    in_num -= tmp * div;
    div /= 10;
    *dest++ = '0' + tmp;
}


--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
Go to the top of the page
 
+Quote Post
k155la3
сообщение Mar 23 2018, 14:19
Сообщение #9


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

Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848



Если я правильно понял задачу. Из двоичного получить BCD.
Ф-ии реализовывывал сам, "наразвес". Давно. Метод не помню как называется, кажется в термине присутствует "даббл дубл" или похоже.
Исходные ссылки брал в Wiki. - линк внизу поста.
Работает быстро, за счет чисто двоичной математики.

ps int == 16-разрядный

SUPPORT.C
Код
#include  "support.h"

// unsigned int bin2BCD( unsigned int in_word ) { return bin2BCD( (unsigned char ) in_word ); }

// unsigned int bin2BCD( int in_word ) { return bin2BCD( (unsigned char ) in_word ); }
char bin2BCD( int in_word )
{
     static unsigned char arr[2]; // результат
     unsigned char *c_ptr = (unsigned char *) &in_word;

     memset( arr, 0x00, sizeof(arr));
     bin8_to_bcd( arr, c_ptr[0] );
     return arr[0];
}

// преобразование из 8-битного двоичного arg_bin8 в упакованный BCD - в массиве bcd3[2]
void bin8_to_bcd( unsigned char *bcd3, unsigned char arg_bin8 )
{
    unsigned long i_src;    // рабочий регистр
    unsigned char *arr;
    arr = (unsigned char *) &i_src;
    i_src = 0;

    arr[0] = arg_bin8;    // младший байт раб.регистра - исходное bin число

    unsigned char test1;
    for(int i=0; i<8; i++)
    {    i_src = i_src << 1;
        if( i >= 7 ) break;
        test1 =  arr[1] & 0x0F;            if( test1 >= 5 ) add_3( &arr[1], B_LOW );
        test1 = (arr[1] >> 4 ) & 0x0F;    if( test1 >= 5 ) add_3( &arr[1], B_HI );
        test1 =  arr[2] & 0x0F;            if( test1 >= 5 ) add_3( &arr[2], B_LOW );
        test1 = (arr[2] >> 4 ) & 0x0F;    if( test1 >= 5 ) add_3( &arr[2], B_HI );
        test1 =  arr[3] & 0x0F;            if( test1 >= 5 ) add_3( &arr[3], B_LOW );
        test1 = (arr[3] >> 4 ) & 0x0F;    if( test1 >= 5 ) add_3( &arr[3], B_HI );
    }

    bcd3[1] = arr[2];    // старший разряд BCD
    bcd3[0] = arr[1];    // 2 младших разряда BCD

}


// вспомогательная ф-я прибавки 3 к тетраде (без переноса)
// обрабатывается байт по c_ptr, sw1 - указывает какя тетрада обрабатывается B_LOW / B_HI
void add_3( unsigned char *c_ptr, int sw1 )
{
    unsigned char ch1, ch2;
    ch2 = *c_ptr;
    if( sw1 == B_LOW )    // младшая тетрада в ch1
    {    ch1 = *c_ptr & 0x0F;            
        ch1 += 3;
        *c_ptr = ( ch2 & 0xF0 ) | ( ch1 & 0x0F );
    }
    else            // старшая тетрада в ch1
    {    ch1 = *c_ptr & 0xF0;            
        ch1 += 0x30;
        *c_ptr = ( ch1 & 0xF0 ) | ( ch2 & 0x0F );
    }

}


SUPPORT_H
Код
#ifndef SUPPORT_H
#define SUPPORT_H
#include  <string.h>
. . . .
// Вспомогательные ф-ии

// переключатель террад
#define B_HI    1
#define B_LOW    2

// вспомогательная ф-я прибавки 3 к тетраде (без переноса)
// второй параметр - переключатель тертрады B_HI / B_LOW
void add_3( unsigned char *, int );    

// ф-я конвертации из bin в упакованный BCD
// ( вызывает add_3() )
void bin8_to_bcd( unsigned char *, unsigned char);

// ф-я конвертации из bin в упакованный BCD
// ( вызывает bin8_to_bcd() )
//  unsigned int si1 = bin2BCD( 123 );
//  (si1) == 0x0123
//unsigned int bin2BCD( unsigned char );
//unsigned int bin2BCD( unsigned int );
char bin2BCD( int );
#endif


Wiki Double_dabble
Go to the top of the page
 
+Quote Post
ae_
сообщение Mar 24 2018, 11:28
Сообщение #10


Участник
***

Группа: Свой
Сообщений: 462
Регистрация: 2-04-07
Из: Иркутск
Пользователь №: 26 695



Цитата(mcheb @ Mar 23 2018, 13:58) *
На PIC16 я делал так
Код
    digit[0] = 0;
    while(value >= 1 )
    {
        value -= 1;
        ++digit[0];
    }
}

А последнюю цифру(разряд единиц) зачем крутить?
Код
digit[0] = value
Go to the top of the page
 
+Quote Post
Lagman
сообщение Mar 26 2018, 13:30
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



Цитата(Сергей Борщ @ Mar 23 2018, 02:31) *
1)пока исходое число не равно нулю
2)записать в выходной буфер остаток от деления исходного числа на 10
3)поделить исходное число на 10.


Нельзя так над человеком издеваться :-)
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 22nd June 2025 - 22:12
Рейтинг@Mail.ru


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