更改C全局变量 [英] Changing a global variable in C

查看:202
本文介绍了更改C全局变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在一个AVR芯片上的C程序。每当串行信号的一声,它运行串行中断ISR(USART_RX_vect)。在这种方法中,应该打开更改 = 1; 。然后在我的主,而循环,应该清除LCD,并显示它,然后设置变化= 0 试。

这是阻止它继续做calulations,并在LCD上显示结果一分钟一百万次。<​​/ P>

然而,当中断方法改变改变变量为1,它似乎并没有改变它全球,并在主要方法总是0 ..

有在这儿有点东西,是用于调试目的。

  / * LCD DEFINES * /
LED的#define PB5
#定义output_low(端口,针)端口和放大器; =〜(1 <<;&LT;针)
#定义output_high(端口,针)端口| =(1 <<;&下;针)
#定义set_input(PORTDIR,PIN)PORTDIR&安培; =〜(1 <<;&LT;针)
#定义set_output(PORTDIR,PIN)PORTDIR | =(1 <<;&LT;针)/ * UART串行DEFINES * /
#定义F_CPU 16000000UL
#定义波特率9600
#定义MYUBRR F_CPU / 16 /波特1#定义STARTCHAR'R'
#定义则EndChar'E'字符阅读;
CHAR INPUTBUFFER [12];
焦炭readStatus;
uint8_t有位置;
INT变化;焦炭产量;
INT结果;轴结构
{
    uint8_t有axisNumber;
    uint16_t位置;
    uint16_t oldPosition;}轴1,轴,轴3;
/ *设置UART * /无效USART_Init(unsigned int类型UBRR)
{
   / *设置波特率* /
   UBRR0H =(unsigned char型)(UBRR&GT;&GT; 8);
   UBRR0L =(unsigned char型)UBRR;  / *启用接收器和发射器* /
   UCSR0B =(1 <<;&下; RXEN0)|(1 <<;&下; TXEN0);   / *设置帧格式:8data,2stop位* /
   UCSR0C =(1 <<;&下; USBS0)|(3';&下; UCSZ00);
}无效USART_Transmit(unsigned char型数据)
{
    UDR0 =数据;
}unsigned char型USART_Receive(无效)
{
   返回UDR0;
}/ ******************* **************** /INT主要(无效)
{
    / * INITALISE SERIAL * /
    USART_Init(MYUBRR);    / *打开接收完成中断* /
    UCSR0B | =(1 <<;&下; RXCIE0);    / *开启全局中断* /
    SEI();    位置= 0;
    变化= 0;    / *初始化LCD * /
    lcd_init(LCD_DISP_ON); / *初始化显示,光标关闭。 * /
    lcd_clrscr();
    lcd_puts(就绪);    //开启LED 13
    set_output(PORTB,LED);
    output_low(PORTB,LED);    而(1)/ *无限循环* /
    {
        如果(其他城市== 1)
        {
            //如果不读书,显示在LCD显示屏上的结果。
            axis1.position =(INPUTBUFFER [0]&下;&下; 8)| INPUTBUFFER [1];
            axis2.position =(INPUTBUFFER [2]&下;&下; 8)| INPUTBUFFER [3];
            axis3.position =(INPUTBUFFER [4]&下;&下; 8)| INPUTBUFFER [5];            CHAR axis1Printout [12];
            CHAR axis2Printout [12];
            CHAR axis3Printout [12];            sprintf的(axis1Printout,%U,axis1.position);
            sprintf的(axis2Printout,%U,axis2.position);
            sprintf的(axis3Printout,%U,axis3.position);            焦炭产量[40] =;
            strcat的(输出,axis1Printout);
            strcat的(输出,axis2Printout);
            // strcat的(输出,axis3Printout);            lcd_clrscr(); / *清除屏幕* /
            lcd_puts(输出);
            _delay_ms(300);
            变化= 0;
        }
    }
}/ * *中断/ISR(USART_RX_vect)
{
    变化= 1;
    无符号字符输入= USART_Receive();    如果(输入=='R')
    {
        readStatus = 0; //读
        位置= 0;
    }
    否则,如果((输入='E')及!及(位置&LT; 12)及及(位置-1个))
    {
        INPUTBUFFER [位置] =输入;
        位置++;
    }
    否则,如果(输入=='E')
    {
        readStatus = 1; //停止阅读
        位置= -1;
        output_high(PORTB,LED);
    }
}


解决方案

您需要使用volatile关键字来声明的变化:

 挥发性INT变化;

这告诉了两个线程(主执行循环,你的ISR code)不缓存在寄存器中的值,但总是从内存中获取它。

编辑:有与code另一个问题 - 在你的主循环,由您设置更改为0的时候,你可能已经有本应触发循环再次运行另一个中断。最简单的,但是,不能保证的解决方法是立即将变为0您检查后直它。正确的方法是使用一个锁 - 但根据您的情况,第一个选项可能会做

I am running a C program on an AVR chip. Whenever a serial signal is heard, it runs the serial interrupt ISR (USART_RX_vect). In this method it should turn on change to = 1;. Then in my main while loop, it should clear the LCD and display it and then set change = 0 again.

This is to stop it continually doing the calulations, and displaying the result on the LCD a million times a minute..

However, when the interrupt method changes the change variable to 1, it does not seem to change it "globally" and in the main method it is always 0..

There is a bit of stuff in here that is for debugging purposes.

/* LCD DEFINES */
#define LED PB5
#define output_low(port,pin) port &= ~(1<<pin)
#define output_high(port,pin) port |= (1<<pin)
#define set_input(portdir,pin) portdir &= ~(1<<pin)
#define set_output(portdir,pin) portdir |= (1<<pin)

/* UART SERIAL DEFINES */
#define F_CPU 16000000UL
#define BAUD 9600
#define MYUBRR F_CPU/16/BAUD-1

#define STARTCHAR 'R'
#define ENDCHAR 'E'

char reading;
char inputBuffer[12];
char readStatus;
uint8_t position;
int change;

char output;
int result;

struct Axis
{
    uint8_t axisNumber;
    uint16_t position;
    uint16_t oldPosition;

} axis1, axis2, axis3;


/* SETUP UART */

void USART_Init( unsigned int ubrr)
{
   /*Set baud rate */
   UBRR0H = (unsigned char)(ubrr>>8);
   UBRR0L = (unsigned char)ubrr;

  /*Enable receiver and transmitter */
   UCSR0B = (1<<RXEN0)|(1<<TXEN0);

   /* Set frame format: 8data, 2stop bit */
   UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}

void USART_Transmit( unsigned char data )
{
    UDR0 = data;
}

unsigned char USART_Receive( void )
{
   return UDR0;
}

/*****************************************************************/

int main(void)
{
    /* INITALISE SERIAL */
    USART_Init(MYUBRR);

    /* Turn on Receive Complete Interrupt */
    UCSR0B |= (1 << RXCIE0);

    /* Turn On GLobal Interrupts */
    sei();

    position = 0;
    change = 0;

    /* Initialise LCD */
    lcd_init(LCD_DISP_ON);  /* Initialize display, cursor off. */
    lcd_clrscr();
    lcd_puts("READY");

    //Turn on LED 13
    set_output(PORTB,LED);
    output_low(PORTB,LED);

    while (1)               /* Loop forever */
    {
        if (change == 1)
        {
            //If not reading, display the result on the LCD display.
            axis1.position  = (inputBuffer[0]<< 8) | inputBuffer[1];
            axis2.position  = (inputBuffer[2]<< 8) | inputBuffer[3];
            axis3.position  = (inputBuffer[4]<< 8) | inputBuffer[5];

            char axis1Printout[12];
            char axis2Printout[12];
            char axis3Printout[12];

            sprintf(axis1Printout,"%u ", axis1.position);
            sprintf(axis2Printout,"%u ", axis2.position);
            sprintf(axis3Printout,"%u ", axis3.position);

            char output[40] = "";
            strcat(output, axis1Printout);
            strcat(output, axis2Printout);
            //strcat(output, axis3Printout);

            lcd_clrscr();  /* Clear the screen*/
            lcd_puts(output);
            _delay_ms(300);
            change = 0;
        }
    }
}

/* INTERRUPTS */

ISR (USART_RX_vect)
{
    change = 1;
    unsigned char input = USART_Receive();

    if (input == 'R')
    {
        readStatus = 0; //Reading
        position = 0;
    }
    else if ((input != 'E') && (position < 12) && (position > -1))
    {
        inputBuffer[position] = input;
        position++;
    }
    else if (input == 'E')
    {
        readStatus = 1; //Stop Reading
        position = -1;
        output_high(PORTB,LED);
    }
}

解决方案

You need to declare change using the volatile keyword:

volatile int change;

This tells the two 'threads' (main execution loop and your ISR code) to not 'cache' the value in a register, but always retrieve it from memory.

Edit: There's another problem with the code - in your main loop, by the time you set changed to 0, you may have already had another interrupt which should have triggered your loop to run again. The easy-but-not-guaranteed fix is to immediately set changed to 0 straight after you check it. The proper way would be to use a lock - but depending on your situation, the first option might do.

这篇关于更改C全局变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆