Pergunta

Sou muito novo na programação C e estou trabalhando em um aplicativo de firmware para o meu MCU. Esse método estava funcionando bem quando eu estava usando o compilador Keil (Big Endian), mas quando mudei para o compilador SDCC (Little Endian), ele não está funcionando corretamente. Alguém pode explicar o que estou fazendo de errado ???

O dispositivo de destino é um Silicon Labs C8051F320, que é baseado na arquitetura 8051.

unsigned **int** MotorSteps  = 0;     //"Global" variables
unsigned **int** MotorSpeed  = 0;
bit RampUp()
{
    float t = 0;
    t = MotorSteps;
    if ( t < 51 )
    {
        t = (1-((50 - t)/50))*15;   
        t = (t * t);        
        MotorSpeed = 100 + t;           
        return 0;
    }
    else return 1;
}

Adicionado: Primeiro, agora mudei os motociclistas e o Motorspeed para ser Ints não assinado.No meu depurador, por algum motivo, se eu definir um ponto de interrupção na linha de estatuto IF, na primeira entrada desta função Motorsteps = 00, então T deve ser atribuído a 0 também, mas o depurador mostra que t = 0,031497 (decimal ). Se eu mudar o depurador para exibir em hexadecimal, t = 0x3d010300. É como se t estivesse sendo designado ...

Foi útil?

Solução

Se motores = 49 então

(50 - 49) / 50 = 0.02

próximo

(1 - 0.02) = 0.98

e

0.98 * 15 = 14.7

Squaring esse valor definiria t como

t = 14.7 * 14.7 = 216.09

Finalmente, a conversão implícita do flutuador de volta para o char não assinado transborda da variável MotorsPeed:

MotorSpeed = 100 + 216.09...// Implicitly converts the float t to an unsigned char of 216

A soma de 100 + 216 = 316, é claro, transborda de um char não assinado e você acaba com 316-256 = 60.

Provavelmente, esse é um comportamento indesejado, independentemente do compilador.

Outras dicas

É como se t estivesse sendo designado ...

Não há razão para o compilador atribuir um valor de 0 a t na declaração

float t = 0;

uma vez que é imediatamente atribuído a motores na próxima linha. Meu palpite é que o otimizador está ignorando a atribuição a zero na declaração e o depurador está simplesmente exibindo o valor não inicializado para a memória em que T está localizado na pilha.

Você pode considerar se livrar completamente da fórmula e usar uma tabela de pesquisa para os valores da rampa. Parece que existem apenas 51 valores para que a tabela seja relativamente pequena. O código para procurar um valor seria Muito de Mais rápido do que usar as bibliotecas de ponto flutuante em um 8051.

#define NUM_RAMP_STEPS 51
unsigned char MotorSteps = 0;     //"Global" variables
unsigned char MotorSpeed = 0;
const unsigned char RampTable[NUM_RAMP_STEPS] = {...appropriate values...};
bit RampUp()
{
    if ( MotorSteps < NUM_RAMP_STEPS )
    {
        MotorSpeed = RampTable[MotorSteps];           
        return 0;
    }
    else return 1;
}

Pelo menos você pode testar seu número inteiro em vez do flutuador para evitar as bibliotecas de pontos flutuantes, a menos que você precise deles ...

unsigned **int** MotorSteps  = 0;     //"Global" variables
unsigned **int** MotorSpeed  = 0;
bit RampUp()
{
    if ( MotorSteps < 51 )
    {
        float t = MotorSteps;
        t = (1-((50 - t)/50))*15;   
        t = (t * t);        
        MotorSpeed = 100 + t;           
        return 0;
    }
    else return 1;
}

Por que você mudou de ser para le? O que é a arquitetura do dispositivo de destino? E a propósito, o que é?

Enfim, para questionar. Tenho certeza de que o problema ocorre quando a conversão ocorre. Tente rastrear sua linha de código por linha com a calculadora e tente encontrar quando os números se tornam inesperados.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top