This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] MSP430FR5994:具有长结果溢出的Int乘法

Guru**** 633810 points
Other Parts Discussed in Thread: MSP430FR5994
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1092992/msp430fr5994-int-multiplication-with-long-result-overflowing

部件号:MSP430FR5994
主题中讨论的其他部件: MSP430WARE

我在MSP430FR5994上有一些将数字相乘的代码。 在本例中,我将80乘以1159,尽管在我的应用中,voltage_differation_range通常在1000左右。

int voltage_difference_range;
long int range_um;

voltage_difference_range = 80;
range_um = voltage_difference_range * 1159;

80*1159=92720。9.272万。 但是,我显示的是2.7184万。 鉴于9.272万 - 6.5536万 = 2.7184万,我认为这是一个溢出问题是安全的。 问题是,我不明白为什么range_um会溢出。 根据MSP430Ware的调试器,range_um的值如下所示。



在我看来,还有2个字节可以包含数据,因为我将它声明为长。

请告诉我是否需要更多信息来解决此问题,或者是否有明显的解决方案来解决此问题。

我的完整代码,以防它有帮助。 问题代码本身位于代码底部附近的一个标志上。 我已经离开了初始化程序,以防它们提供帮助。

#include <msp430.h>
#include <stdio.h>
#include <stdlib.h>

#define PWM_16HZ 2048
#define PWM_32HZ 1024

char printkeeper;
int memval3_old = 0, memval4_old = 0, memval3_new = 0, memval4_new = 0, i = 0;      //Old is for storing old ADC values
int voltage_difference_new, voltage_difference_old, voltage_difference_range, voltage_difference_doppler; //Remove float whenever possible!
long int range_um, speed_um;
int range, speed;

int main(void)
{
    WDTCTL = WDTPW | WDTHOLD;               // Stop WDT

    // GPIO Setup

    P1OUT &= ~BIT0;                         // 16Hz Clock Pin Setup

    P1DIR |= BIT0 | BIT1 | BIT2 | BIT5;     // Bits 1.2, 1.5 set to clock (TA1.1, TB0.2) (p88_s, p91_s)
    P1SEL0 |= BIT0 | BIT1 | BIT2 | BIT5;    // See p88-90_s
    PJSEL0 = BIT4 | BIT5;                   // For XT1 Oscillator (p118_s)

    P1SEL1 |= BIT3 | BIT4 ;                 // ADC Pin Setup
    P1SEL0 |= BIT3 | BIT4 ;                 // 1.3 and 1.4 set to ADC input (A3, A4) from p90_s

    P3DIR |= BIT0;                          // Set Pin 3.0 as output, for permanent 3.3V.


    // Disable the GPIO power-on default high-impedance mode to activate
    // previously configured port settings
    PM5CTL0 &= ~LOCKLPM5;
    //P1OUT |= BIT0;

    // Clock System Setup

    CSCTL0_H = CSKEY_H;                     // Unlock CS registers
    CSCTL1 = DCOFSEL_3;                     // Set DCO to 4MHz (p105)
    CSCTL2 = SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK;   // Set clock source
    CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1;   // Set all dividers, clock speed 1MHz
    CSCTL4 &= ~LFXTOFF;                     // Something related to the 32kHz oscillator

    do
    {
        CSCTL5 &= ~LFXTOFFG;                // Clear XT1 fault flag
        SFRIFG1 &= ~OFIFG;
    } while (SFRIFG1 & OFIFG);              // Test oscillator fault flag

    CSCTL0_H = 0;                           // Lock clock registers

    //ADC Setup

    ADC12CTL0 = ADC12SHT0_0 | ADC12ON;      // Sampling time, S&H=4, ADC12 on [p893, CTL0 = control 0, SHT0_0 = sample & hold time, knowledge of register value from p88_s]

    ADC12CTL1 = ADC12SHP | ADC12SHS_4 | ADC12CONSEQ_1; // Use TA1.1 to trigger, (SHP means using sample timer (p897), SHS means "sample-and-hold source select" (p895, p84_s)
                                                       // which selects which source is used to activate sampling (4 being TA1.1 because of p84_s), CONSEQ_1 = Conversion sequence select,
                                                       // 1 means multiple-channel which means multiple channels are converted and sampled, memory gets overriden everytime (p881)
    ADC12CTL2 |= ADC12RES_2;                // 12-bit conversion results, p897
    ADC12CTL3 |= ADC12CSTARTADD_3;          // Use MEM3/MCTL3 as first, p898

    ADC12MCTL3 = ADC12INCH_3 ;              // A3 ADC input select from Input Channel 3 (p901), output to MEM3
    ADC12MCTL4 = ADC12INCH_4 | ADC12EOS;    // A4 ADC input select, also setting EOS bit at A4

    ADC12IER0 |= ADC12IE3 | ADC12IE4;      // Enable ADC interrupt [IER = interrupt enable, for IFG0 bit, which tells us when the sequence is complete]


    // Configure TimerA1.1 to periodically trigger ADC12 at a rate of 32Hz
    TA1CCR0 = PWM_32HZ - 1;                   // PWM Period for TA1, 1024/32768 = /32
    TA1CCTL1 = OUTMOD_3;                    // TACCR1 set/reset (Shape of set/reset in p652)

    TA1CCR1 = PWM_32HZ / 2;                   // TACCR1 PWM Duty Cycle
    TA1CTL = TASSEL__ACLK | MC__UP;         // ACLK, up mode

    // Configure TimerA0.0 to generate a 16Hz Square Wave
    TB0CCR0 = PWM_16HZ - 1;                   // PWM Period for TB0, 2048/32768 = /16
    TB0CCTL2 = OUTMOD_7;                    // TBCCR1 set/reset (Shape of set/reset in p652)

    TB0CCR2 = PWM_16HZ /2;                  // TB0CCR2 PWM Duty Cycle
    TB0CTL = TASSEL__ACLK | MC__UP;         // ACLK, up mode

    ADC12CTL0 |= ADC12ENC | ADC12SC;        // Start sampling/conversion
    printf("135\n");
    __bis_SR_register(LPM0_bits | GIE);     // Enter LPM0, enable interrupts

    __no_operation();

}

// ADC12 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=ADC12_B_VECTOR
__interrupt void ADC12ISR (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(ADC12_B_VECTOR))) ADC12ISR (void)
#else
#error Compiler not supported!
#endif
{
    switch(__even_in_range(ADC12IV, ADC12IV__ADC12RDYIFG))
    {
        case ADC12IV__ADC12IFG3:            // Vector 18:  ADC12MEM3
            memval3_old = memval3_new;
            memval3_new = ADC12MEM3;
            ADC12IFGR0 &= ~ADC12IFG3;
            break;
        case ADC12IV__ADC12IFG4:            // Vector 20:  ADC12MEM4
            memval4_old = memval4_new;
            memval4_new = ADC12MEM4;

            voltage_difference_new = abs((memval3_new - memval4_new)); // These values are both +ve, rising edge
            voltage_difference_old = abs((memval3_old - memval4_old)); // These values are both +ve, falling edge

            voltage_difference_range = ((voltage_difference_new + voltage_difference_old));
            voltage_difference_doppler = ((voltage_difference_new - voltage_difference_old)); //Lower frequency means moving away
            //printf("%d\n", voltage_difference_range);

            voltage_difference_range = 80;
            range_um = voltage_difference_range * 1159; //Check notebook math, this is in micrometers to avoid floats
            speed_um = voltage_difference_doppler * 15766;  //Check notebook math, also in micrometers

            if (printkeeper == 31){
                printkeeper = 0;
                printf("VD: %d\n", voltage_difference_range);
                printf("R: %d\n", range_um);
                i++;
            }
            else {
                printkeeper = printkeeper + 1;
            }
            ADC12MCTL4 |= ADC12EOS;
            ADC12CTL0 &= ~ADC12ENC;
            ADC12CTL0 |= ADC12ENC;
            break;
        default: break;
    }
}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尝试将voltage_differation_range转换为较长的值。 正在对ints执行计算,然后转换为long。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我已经写了以下内容:

    range_um = (long) voltage_difference_range * 1159;

    我没有看到任何变化。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    奇怪。

    http://c-faq.com/expr/intoverflow1.html

    尝试转换到(长int)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    奥斯卡

    当我运行Keith建议的代码时,我得到预期结果:range_um = 9.272万。 如果您仍有问题,我认为它来自其他地方。

    #include <msp430.h> 
    
    
    /**
     * main.c
     */
    
    
    int voltage_difference_range;
    long int range_um;
    
    int main(void)
    {
    	WDTCTL = WDTPW | WDTHOLD;	// stop watchdog timer
    	
    
    	voltage_difference_range = 80;
    	range_um = (long) voltage_difference_range * 1159;
    
    	while (1);
    
    	return 0;
    }