Перейти к содержанию
    

Помогите разобраться с таймером и SPI для мега 16

Я по прерыванию таймера Т2 формирую импульсы длительностью 8 мс…. Т.е. через каждые 8мс должно наступать прерывание. К примеру я по 10 прерыванию устанавливаю бит а по 11 сбрасываю его. Импульс же должен получиться 8 мс, а у меня всего 1 мс. В чем может быть причина?

МK тактируется от внутренней RC цепочки частотой 8 мгц. Коэффициент деления для Т2 беру 1024. Получаем 8 000 000/1024=7812,5 1/7812.5=0,000128. Далее для формирования импульса длительностью 8 мс делю 0,008/0,000128=63. Получается, что Т2 до переполнения должен просчитать 63 раза. Записываю в счетный регистр число 255-63=192 или С0. Вот собственно и все. Может я где то в расчетах ошиблась?

 

Второй вопрос по SPI:

Почему-то у меня на плате выводы SPI MISO, MOSI соединены через резистор 4,7 кОм. Я соединяю их напрямую перемычкой длиной примерно 8 см. У меня такое ощущение что мой SPI срабатывает от помехи. Хочу увидеть какие данные шлют друг другу мк и ничего не могу увидеть. Может причина в настройках?

Если не лень, посмотрите алгоритм, пожалуйста... Ну что я делаю не так?

Для мастер

На выводе SS высокий уровень. Инициализирую SPI:

Включаю SPI, разрешаю прерывания., режим мастер, частота CLK 125 кГц.

На вывод SS Slave подаю 0 в SPDR загружаю данные.

В прерывании считываю принятые данные от Slave вызываю функцию обработки принятых данных.

 

Для Slave

Инициализирую SPI: Включаю SPI, разрешаю прерывания.

В SPDR загружаю данные.

В прерывании считываю принятые данные от Master вызываю функцию обработки принятых данных.

 

Заранее благодарю :)

прошу прощения за много бкафф

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сударыня, прошу Вас, покажите кусочек исходника с инициализацией. А лучше покажите его целиком. Это гораздо яснее нам скажет, что Вы делаете, нежели словесные описания. Вы, к примеру, могли напутать с прескаллером. Лично я обычно таймер инциализирую по-другому - об этом я уже неоднократно писал (прям любимая моя тема), например здесь

http://electronix.ru/forum/index.php?showtopic=55363

 

SPI... Как инициализируете, не забыли ли про направление портов, как соедины девайсы (схема)?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Пр направление портов не забыла....

Как соединены - сейчас не могу схему кинуть.....

SPI как писала выше соединяю перемычками, т.к. почему то у меня на плате выводы SPIежду сосбой соединены через резистор 4,7 К. эта плата досталась мне от другого разработчика.

Исходник у меня большой.... как мне кажется. но вот, смотрите:

#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/eeprom.h>
#include <util/delay.h>

// port definitions
/*
PA0 AIN        adc            in
PA1 AGND    adc            in
PA2 Uref/2     adc            in
PA3 TST        adc            in
PA4    AGND      adc            in
PA5    AGND      adc            in
PA6    AGND      adc            in
PA7    AGND      adc            in

PB0 F_CONTROL              out
PB1 P_OUT                  out
PB2 P_OUT1                 out
PB3 P_relays            out
PB4    SS        spi start    out
PB5    MOSI    spi            out    
PB6    MISO    spi            in
PB7    SCK        spi            out

PC0                     out
PC1                     out
PC2 LED1.1    dual led    out
PC3 LED1.2    dual led    out
PC4    Zap1                out
PC5    Zap2                out
PC6    PGOOD    test        in          
PC7                        out

PD0 N_relays            out
PD1  TEST                out
PD2                     in
PD3                     in
PD4    SYNC3    sync        out
PD5    SYNC4    sync        out
PD6    MODE    cfg            in        1 - first, 0 - second
PD7    SNU                    out
*/



// global defines
#define uchar unsigned char
#define ushort unsigned short

// Установка, сброс и инвертирование бита в регистрах
#define SET_B(x) |= (1<<x) // Установить бит
#define CLR_B(x) &=~(1<<x) // Очистить бит
#define INV_B(x) ^=(1<<x) // Инверитровать бит
// x - номер бита в регистре


// init_ports

#define F_CONTROL   PB0
#define P_OUT          PB1
#define P_OUT1         PB2
#define P_relays     PB3
#define SLED1        PC2
#define SLED2        PC3 
#define Zap1        PC4
#define Zap2        PC5
#define SNU         PD7
#define TEST        PD1
#define N_relays    PD0


#define CPU_CLK                8000000
#define ADC_BUFFER_SIZE     255 //Размер  массива для рез-та АЦП
#define ADC_STOP_STEP        255//Кол-во  шагов АЦП
#define EEA_LEVEL             0
#define EEA_LEVELDELTA        1
#define EEA_LEVEL_OFF       18
#define EEA_LEVELDELTA_OFF    5
#define STATUS1_ON        PORTC|=_BV(SLED1)
#define STATUS1_OFF        PORTC&=~_BV(SLED1) 
#define FCONTROL_ON      PORTB|=_BV(F_CONTROL)
#define FCONTROL_OFF     PORTB&=~_BV(F_CONTROL)
#define POUT_ON          PORTB|=_BV(P_OUT)
#define POUT_OFF        PORTB&=~_BV(P_OUT)
#define POUT1_ON          PORTB|=_BV(P_OUT1)
#define POUT1_OFF        PORTB&=~_BV(P_OUT1)
#define SNU_ON          PORTD|=_BV(SNU)
#define SNU_OFF            PORTD&=~_BV(SNU)
#define Zap1_ON         PORTD|=_BV(Zap1)
#define Zap1_OFF        PORTD&=~_BV(Zap1)
#define Zap2_ON         PORTD|=_BV(Zap2)
#define Zap2_OFF        PORTD&=~_BV(Zap2)
#define P_rel_ON         PORTD|=_BV(P_relays)
#define P_rel_OFF        PORTD&=~_BV(P_relays)
#define N_rel_ON         PORTD|=_BV(N_relays)
#define N_rel_OFF        PORTD&=~_BV(N_relays)

// global variables

volatile signed char result[ADC_BUFFER_SIZE];      //преобразов. массив знач. АЦП
volatile signed char adc_buffer[ADC_BUFFER_SIZE]; // Массив значений АЦП
volatile signed char val;                   //Максимальное значение в массиве 
volatile signed char  val8;                 //Переменная для анализа уровня
volatile signed char adc_delta;             //Разница значений между двумя АЦП
volatile signed char adc2;                  //Принятый рез-т АЦП
volatile signed char level;
volatile signed char level_delta;
volatile signed char dop1;
volatile signed char dop2;
volatile signed char max_val;
volatile uchar leveloff; 
volatile uchar level_deltaoff;
volatile uchar adc_counter;                 //Счетчик АЦП преобразов.
volatile uchar cnt_T2;                  //Счетчик периодов таймера Т2
volatile uchar cnt_isrt2;               //Счетчик прерываний таймера t2 
uchar eeprom_addr;
uchar data_slave;                           //переменная для считыв. принятых данных 
uchar n;                                // Переменная для подсчета числа импульсов


//functions
void filter ();
void analyze();
void spi_mastertransmit();
void analyze_transmit();
void test_transmit();

//Инициализация портов
void init_pio()       
{ DDRA=0;
  DDRB=0xBF;
  DDRC=0xBF;
  DDRD=0xB3;
  PORTB=0x10;                    // откл.Slave по  выводу SS
  PORTC=0x30;
  PORTD=0x01;
}

void read_cfg()
{
eeprom_write_byte(0,0x93); //Порог включения
eeprom_write_byte(1,0x00);
eeprom_write_byte(18,0x74); //Порог выключения
eeprom_write_byte(5,0x00);
//read
level=eeprom_read_byte(EEA_LEVEL);
  level_delta=eeprom_read_byte(EEA_LEVELDELTA);
  leveloff=eeprom_read_byte(EEA_LEVEL_OFF);
  level_deltaoff=eeprom_read_byte(EEA_LEVELDELTA_OFF);
}

// инициализация таймера
void init_timers()              
{TCCR0=_BV(CS02)|_BV(CS00);     // clk/1024 
TCNT0=0xFC;                     // частота ацп 2 кГц
TCCR2=_BV(CS22)|_BV(CS20);      // clk/1024 
TCNT2=0xC0;
TIMSK=_BV(TOIE0)|_BV(TOIE2);               //Флаг разр.прерыв. по  переполнению таймера
}


// Инициализация SPI
// init SPI                    
void init_SPI()
{ 
SPCR=_BV(SPIE)|_BV(SPE)| _BV(MSTR)|_BV(SPR1); //вкл.SPI,разр.прерыв., реж.мастер
PORTB CLR_B(4);
//PORTB=0;
//sei();                                      //Вкл. Slave по  выводу SS
}

//Инициализация АЦП
// init ADC                     
void init_adc()
{ADCSRA=_BV(ADEN)|_BV(ADATE)|_BV(ADIE)|_BV(ADPS2)|_BV(ADPS1);//Вкл.АЦП,реж. работы по  таймеру,разр. прерыв от  компаратора, clk/64
ADMUX=_BV(ADLAR);     //Выравнивание рез-та по  левой границе
SFIOR=0x80;           // Запуск АЦП по  прерыванию  таймера Т0
//sei();
} 

// Timer0    прерывание по  таймеру                      
ISR(TIMER0_OVF_vect) 
{ TCNT0=0xFC;
  ADCSRA|=0x40;//start ADC
}

// Timer2    прерывание по  таймеру формирование сигналов запуска     
ISR(TIMER2_OVF_vect) 
{ TCNT2=0xC0;
cnt_isrt2++;
if (cnt_isrt2==0x96) PORTC CLR_B(4); // начало зап1
if (cnt_isrt2==0x97) 
{  PORTC SET_B(4);                    // конец зап1          
   PORTC CLR_B(5);}                  // начало зап2
if (cnt_isrt2==0x98) PORTC SET_B(5);  // конец зап2
if (cnt_isrt2==0xC8) 
{cnt_T2++;                     //конец одного  периода
cnt_isrt2=0;}                  // Обнуление счетчика прерываний 
if (cnt_T2==0x03){ 
    if (n<0x01) 
     {PORTB SET_B(3);   //Запуск поляризованного реле
       n++;             // Считаем количество импульсов
     }
   }
if (cnt_T2>=0x04) PORTD CLR_B(0);   // Конец запуска нейтрального  реле
if (cnt_T2==0x04) 
{  PORTB CLR_B(3);                 // Конец запуска поляризованного  реле
  cnt_T2=0;                    // обнуление счетчика периодов
  } 
}




// ADC  Прерывание по  окончанию АЦП
ISR(ADC_vect)
{ uchar c;
  //ADCSRA |= _BV(ADIF);         // clear flag
  //ADCSRA|=0x40; 
  //loop_until_bit_is_set(ADCSRA,ADIF); 
  //ADCSRA |= _BV(ADIF);        // clear flag
  c=ADCL;
  c=ADCH;                   // Результат АЦП
  adc_buffer[adc_counter]=c;// Массив данных АЦП
  adc_counter++;            //Увел-е на 1 счетчтка АЦП
    if(adc_counter>=ADC_STOP_STEP) //Если АЦП закончено начинаем фильтровать
   {adc_counter=0; 
   filter();
    }
}

void filter () // Сглаживаем синусоиду
{ uchar i;
  const char porog=0x0F; // Значение порога 0,24В 
for(i=0;i<ADC_STOP_STEP;i++)
{
result[i]=(adc_buffer[i]+adc_buffer[i+1])/2; 
if (result[i]>porog) adc_buffer[i]=result[i];} // Берем значения больше порога
analyze();
}

// analyze data
void analyze()
{ uchar i;
  val=0;
  //uchar val8;
  max_val=0;
  for(i=0;i<ADC_STOP_STEP-1;i++) 
{  if(adc_buffer[i]>max_val) max_val=adc_buffer[i]; //Ищем наибольшее значение
  }
  val8=max_val;
  val=val8;         // Максимальное значение в массиве
  //analyze_transmit();
  spi_mastertransmit();
}

// analyze_transmit анализ  принятых данных
void analyze_transmit()
{ dop1=0x05;  // Допустимое. значение 5
  dop2=0x00;  // Допустимое значение 0
  adc_delta=val-adc2; // Определение разницы измеренного  и принятого значения АЦП
if (adc_delta>dop1) val8=adc2; //Если разница положительная используем принятое значение АЦП
else 
  {adc_delta=adc2-val; // Если отриц.,вычисляем положительную разницу
  val8=val;            // используем измеренное значение
  }

    if (adc_delta>dop2) // Если разница больше допустимого
    { STATUS1_OFF;      //Выкл. индик.
      FCONTROL_OFF;       //Выкл. контр. частоту
      POUT_OFF;           //Выкл. фронт ключ
      //POUT1_ON;           //Вкл. тыл. ключ
    SNU_OFF; 
      return;
    }
  else 
  if (adc_delta<dop2)   //Если разница меньше допустимого -  анализ порога
  {
          if(val8>(level-level_delta)) //если больше порога
        { STATUS1_ON;      //Вкл. индик
           FCONTROL_ON;     //Вкл. контр. частоту
          POUT_ON;         //Вкл. Вкл. фронт. кл.
        //POUT1_OFF;       //Выкл. тыл.  ключа
        SNU_ON;          //Вкл. сигнала наличия уровня
        test_transmit();
     }
   
              else         // если меньше порога
  //if (val<(leveloff-level_deltaoff)) 
            {    STATUS1_OFF;  //Выкл. индик.
              FCONTROL_OFF; //Выкл. контр. частоту
              POUT_OFF;     //Выкл. фронт ключ
             //POUT1_ON;    //Вкл. тыл. ключ
              SNU_OFF;      //Выкл. сигнала наличия уровня
           }
   } 
}


void spi_mastertransmit() // Передача макс. значения массива по SPI
{init_SPI();
SPDR=val;
while(!(SPSR & (1<<SPIF)));
{};
return SPDR;
}

ISR (SIG_SPI)
{
adc2=SPDR;
SPCR=0x40;                 // Прием макс. значения массива по SPI
analyze_transmit();
sei();
}

// test_transmit() вывод  на вых тест рез-та АЦП
void test_transmit()
{ signed char res1;
  signed char res2;
  int i;
  for (i=0; i<8;i++)
  { 
    res1=val8>>i;
    res2=res1&01;
    if (res2==1) 
    PORTD SET_B(1); 
    else 
    PORTD CLR_B(1);
    
  }
}

int main(void)
{  
   init_pio();
   read_cfg();
   init_adc();
   init_timers(); 
   ACSR=0x80;     // Выкл. аналог.  компаратора
   sei();         // Разрешение прерываний
   while (1);
   }

Это для мастера, для слэйва тоже самое, разница только в настрйках SpI и портаВ

 

Для слэйва:

настройки портов

//Инициализация портов
void init_pio()       
{ DDRA=0;
  DDRB=0x4F;
  DDRC=0xBF;
  DDRD=0xB3;
  PORTB=0x00;                    // откл.Slave по  выводу SS
  PORTC=0x30;
  PORTD=0x01;
}

 

Настройка SPI

 // Инициализация SPI
// init SPI                    
void init_SPI()
{ 
SPCR=_BV(SPIE)|_BV(SPE)|_BV(SPIF)|_BV(SPR1); //вкл.SPI,разр.прерыв., реж.мастер                                //Вкл. Slave по  выводу SS
//sei();
}

 

Передача данных по Spi

void spi_mastertransmit()  // Передача макс. значения массива по SPI
{
init_SPI();
SPDR=val;
while(!(SPSR & (1<<SPIF)));
}

ISR (SIG_SPI)
{ 
adc2=SPDR;                // Прием макс. значения массива по SPI
analyze_transmit();

}

 

да. вот еще вопросик возник... в AVR Studio когда я просматриваю программу в пошаговом режиме там можно заметить время между прерываниями... так вот у меня АЦП, запускается по прерыванию таймера Т0 через каждые 0,5 мс а в AVR Studio я наблюдаю величину в 2 раза большую. с чем это связано?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну во-первых, Вы действительно задали неверный прескаллер, а именно - 128. Так что, код в этой строчке

TCCR2=_BV(CS22)|_BV(CS20);      // clk/1024

не соответствует комментарию к ней. Внимательно почитайте doc2466, страница 130.

 

Собственно SPI. Во-первых, не надо его переинициализировать при каждой команде записи. Во-вторых, меня сильно смущает это строчка

while(!(SPSR & (1<<SPIF)));

У вас включен обрабочик SPI, следовательно, флаг SPIF сбрасывается аппаратно. Вполне возможно, что здесь у вас просто проваливается в вечный цикл.

 

А вообще, пересмотрите общую структуру кода и оформление кода. У вас очень много голых чисел в исходнике, много таких мест, работы который вызывает опасение.

 

у меня АЦП, запускается по прерыванию таймера Т0

Зачем это надо? Используйте Free Runing Mode

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

while(!(SPSR & (1<<SPIF)));

У вас включен обрабочик SPI, следовательно, флаг SPIF сбрасывается аппаратно. Вполне возможно, что здесь у вас просто проваливается в вечный цикл.

Не-не-не-не! На этот while попадаем из ISR(ADC_vect).

 

Интереснее зачем в ISR(SIG_SPI) есть строка "SPCR=0x40;", которая мастер отключает... да еще и вложенные прерывания разрешаются..

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Интереснее зачем в ISR(SIG_SPI) есть строка "SPCR=0x40;", которая мастер отключает... да еще и вложенные прерывания разрешаются..

Меня тоже сие удивило. А вообще, там много "интересных" строчек... :(

 

Не-не-не-не! На этот while попадаем из ISR(ADC_vect).

дададада, действительно... туплю...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

хочу сказать что

while(!(SPSR & (1<<SPIF)));

что с этой строчкой что без нее одна фигня...

про прескалер у меня так в книге написано, что эти коэффициенты соответствуют коффициенту 1024...

SPI у меня так был настроен в другой программе где просто передавались данные - все работало.

По крайней мере на порт выводило передаваемые данные. Спасибо за советы. пойду дальше разбираться. На вопросы отвечу позже - сейчас на работу убегаю.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо всем за помощь :)

Не судите строго - это первая программа, которую я пишу. До этого программированием не занималась. поэтому может что то быть криво косо не красиво, но мне сейчас важно что бы это работало.

с таймером разобралась - все получилось.

С SPI тоже все хорошо. видно что отсылается что принимается. конечно все это с учетом Ваших замечаний.

Теперь возник еще один вопрос, никак не могу понять в чем же дело...

я в пошаговом режиме просматриваю алгоритм - все отлично работает, если переменные val и adc2 имеют значения больше 0х80 - то все корректно работает, если меньше то там где не нужно в статус регистре устанавливаются флаги Н, S, V, C . Дальше идет неверное выполнение программы. я так понимаю, что это связано с отрицательными числами. Везде стараюсь сравнивать переменные одинаковых типов. Правда в этой программе приходится переменный val , adc2 присваивать числа, т.к. на самом деле в эти переменные записывается результат АЦП. Точнее в переменной val хранится результат АЦП а переменная adc2 - в нее пишется принятое по SPI значение. Может кто нибудь подскажет на что обратить внимание? и какие еще косяки бросились Вам в глаза в первом исходнике? Мне сейчас это важно. заранее благодарю :)

#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/eeprom.h>
#include <util/delay.h>


// global defines
#define uchar unsigned char
#define ushort unsigned short


// init_ports

#define F_CONTROL   PB0
#define P_OUT          PB1
#define P_OUT1         PB2
#define P_relays     PB3
#define SLED1        PC2
#define SLED2        PC3 
#define Zap1        PC4
#define Zap2        PC5
#define SNU         PD7
#define TEST        PD1
#define N_relays    PD0


#define CPU_CLK                8000000
#define STATUS1_ON        PORTC|=_BV(SLED1)
#define STATUS1_OFF        PORTC&=~_BV(SLED1) 
#define FCONTROL_ON      PORTB|=_BV(F_CONTROL)
#define FCONTROL_OFF     PORTB&=~_BV(F_CONTROL)
#define POUT_ON          PORTB|=_BV(P_OUT)
#define POUT_OFF        PORTB&=~_BV(P_OUT)
#define POUT1_ON          PORTB|=_BV(P_OUT1)
#define POUT1_OFF        PORTB&=~_BV(P_OUT1)
#define SNU_ON          PORTD|=_BV(SNU)
#define SNU_OFF            PORTD&=~_BV(SNU)


// global variables


volatile signed char val;                   //Максимальное значение в массиве 
volatile signed char val8;                 //Переменная для анализа уровня
volatile signed char adc_delta;             //Разница значений между двумя АЦП
volatile signed char adc2;                  //Принятый рез-т АЦП
volatile uchar level;
volatile signed char leveloff;
volatile signed char dop1;
volatile signed char dop2;
volatile signed char n;
volatile signed char t;
uchar eeprom_addr;
uchar adc_addr;

//functions

void analyze_transmit();


//Инициализация портов
void init_pio()       
{ DDRA=0;
  DDRB=0xBF;
  DDRC=0xBF;
  DDRD=0xB3;
  PORTB=0x10;                    // откл.Slave по  выводу SS
  PORTC=0x30;
  PORTD=0x01;
}


// read cfg from eeprom

#define EEA_LEVEL           0
#define EEA_LEVEL_OFF   1

void read_cfg()
{eeprom_addr=0;
  adc_addr=0;
eeprom_write_byte(0,0xBB); //Порог включения
eeprom_write_byte(1,0x74); //Порог выключения
//read
level=eeprom_read_byte(EEA_LEVEL);
leveloff=eeprom_read_byte(EEA_LEVEL_OFF);
}

// analyze_transmit анализ  принятых данных
void analyze_transmit()
{ 
dop1=0x00;  // Допустимое. значение 5
  dop2=0x01;  // Допустимое значение 0
  val=0x0F;
  adc2=0F;
  adc_delta=val-adc2; // Определение разницы измеренного  и принятого значения АЦП
if (adc_delta>=dop1) val8=adc2; //Если разница положительная используем принятое значение АЦП
if (adc_delta<dop1) 
  {adc_delta=adc2-val; // Если отриц.,вычисляем положительную разницу
  val8=val;            // используем измеренное значение
  }

    if (adc_delta>dop2) // Если разница больше допустимого
    { STATUS1_OFF;      //Выкл. индик.
      FCONTROL_OFF;       //Выкл. контр. частоту
      POUT_OFF;           //Выкл. фронт ключ
      //POUT1_ON;           //Вкл. тыл. ключ
    SNU_OFF; 
      return;
    }
  
  if(adc_delta<=dop2) {     //Если разница меньше допустимого -  анализ порога    
  if (val8>=level)             //если больше порога                                // Здесь  устанавливаются флаги H,C,N Статус регистр
        { STATUS1_ON;      //Вкл. индик
           FCONTROL_ON;     //Вкл. контр. частоту
          POUT_ON;         //Вкл. Вкл. фронт. кл.
        //POUT1_OFF;       //Выкл. тыл.  ключа
        SNU_ON;          //Вкл. сигнала наличия уровня
       } 
     }
   
  else {            // если меньше порога
    if (val8<leveloff) 
            {    STATUS1_OFF;  //Выкл. индик.
              FCONTROL_OFF; //Выкл. контр. частоту
              POUT_OFF;     //Выкл. фронт ключ
             //POUT1_ON;    //Вкл. тыл. ключ
              SNU_OFF;      //Выкл. сигнала наличия уровня
           }
   } }



int main(void)
{  
   init_pio();
   read_cfg();
   while (1)
   analyze_transmit();
   }

Изменено пользователем _Надя

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Замените ненужные сложные конструкции типа

if (A>=B) {}
if (A<B) {}

на вполне себе логичные и простые

if(A>=B) {}
else {}

 

И стоит, пожалуй, внимательно посмотреть все ли переменные необходимо объявить как volatile.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо за совет :)

 

В принципе и так и так меняла конструкции - легче не стало. В этой программе пожалуй и не стоит все переменные объявлять как volatile. А на что это влияет?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В этой программе пожалуй и не стоит все переменные объявлять как volatile. А на что это влияет?

На работу оптимизатора компилятора. Керниган и Ричи, язык С.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...