ISR期间的sprintf导致崩溃?

时间:2015-03-27 20:35:15

标签: crash printf interrupt isr

我正在尝试格式化字符串,然后在 ISR 期间将其打印到 LCD ISR 正常运行,sprintf()已注释掉;但是当它被引入时,程序在 ISR 期间崩溃。

void __ISR(_CHANGE_NOTICE_VECTOR, IPL1) CNIntHandler(void) {
    //more of my code later
    LATBINV = LEDC; //invert LEDC to a 1
    hw_msDelay(20);

    int buttons = read_buttons();
    decode_buttons(buttons, &g_step_mode, &g_step_dir, &g_motor_delay);

    LATBINV = LEDC; //reinvert LEDC to 0

    mCNClearIntFlag(); //clear the CN flag
}

sprintf()发生在decode_buttons()内:

void decode_buttons(int f_buttons, int *f_step_mode, int *f_step_dir, int *f_motor_delay) {
    char f_mode_str;
    char f_dir_str;
    int f_RPM;
    char f_LCD_str;

    switch(f_buttons) {
        case 0x0000: //none pressed
            *f_step_mode = HS;
            f_mode_str = "HALF";
            *f_step_dir = CW;
            f_dir_str = "CW";
            *f_motor_delay = 20; // semipermanent value
            f_RPM = 15;
            break;

        case 0x0040: //BTN 1 pressed
            *f_step_mode = FS;
            f_mode_str = "FULL";
            *f_step_dir = CW;
            f_dir_str = "CW";
            *f_motor_delay = 40;
            f_RPM = 15;
            break;

        case 0x0080: // BTN 2 pressed
            *f_step_mode = HS;
            f_mode_str = "HALF";
            *f_step_dir = CCW;
            f_dir_str = "CCW";
            *f_motor_delay = 30;
            f_RPM = 10;
            break;

        case 0x00C0: //Both pressed
            *f_step_mode = FS;
            f_mode_str = "FULL";
            *f_step_dir = CCW;
            f_dir_str = "CCW";
            *f_motor_delay = 24;
            f_RPM = 25;
            break;

        default:
            break;
    }

    sprintf(f_LCD_str, "%s %s %d", f_dir_str, f_mode_str, &f_RPM);
    LCD_puts(f_LCD_str); //output string to LCD

    return;
}

我正在使用 PIC32 Cerebot 电路板,目标是使用步进电机的当前模式,方向和RPM更新 LCD 。我将澄清我能做什么并发布所需的任何内容。

1 个答案:

答案 0 :(得分:0)

sprintf组成一个字符串并将其存储在一个必须足够大的数组中:http://www.cplusplus.com/reference/cstdio/sprintf/

在您的代码中,传递给sprintf的输出缓冲区声明为

char f_LCD_str;

不是数组而是单个字符。 sprintf将不可避免地溢出。 一个好的宣言是

char f_LCD_str[30];

(其他字符数组的相同注释:f_mode_str和f_dir_str)

使用snprintf总是更安全,以避免溢出风险。在这种情况下,呼叫将是:

sprintf(f_LCD_str, 30, "%s %s %d", f_dir_str, f_mode_str, f_RPM);

注意:& f_RPM将打印变量的地址,其中f_RPM将根据您的需要打印出变量值。