delay_ms + прерывания?

Обсуждаем контроллеры компании Atmel.
sbvp
Родился
Сообщения: 12
Зарегистрирован: Пт авг 21, 2009 21:00:12
Откуда: Bila Tserkva

Re: delay_ms + прерывания?

Сообщение sbvp »

Поставил в местах "до" и "после" задержки контрольные точки регистра UCSRA. Так в циклическом режиме, когда данных на входе нет его значение 0х60. Если данные приходят во время задержки, то устанавливается 0х68. Сбросить его не удается. По даташиту это бит Bit 3 – DOR: Data OverRun (0х68=b01101000).
Спойлер

Код: Выделить всё

/*****************************************************
Chip type               : ATmega8
Program type            : Application
AVR Core Clock frequency: 8,000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
*****************************************************/

#include <mega8.h>
// Alphanumeric LCD functions
#include <lcd.h>

 
#ifndef RXB8
#define RXB8 1
#endif

#ifndef TXB8
#define TXB8 0
#endif

#ifndef UPE
#define UPE 2
#endif

#ifndef DOR
#define DOR 3
#endif

#ifndef FE
#define FE 4
#endif

#ifndef UDRE
#define UDRE 5
#endif

#ifndef RXC
#define RXC 7
#endif

#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<DOR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)

// USART Receiver buffer
#define RX_BUFFER_SIZE 8
char rx_buffer[RX_BUFFER_SIZE];

#if RX_BUFFER_SIZE <= 256
unsigned char rx_wr_index,rx_rd_index,rx_counter;
#else
unsigned int rx_wr_index,rx_rd_index,rx_counter;
#endif

// This flag is set on USART Receiver buffer overflow
bit rx_buffer_overflow;

// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSRA;
data=UDR;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
   {
   rx_buffer[rx_wr_index++]=data;
#if RX_BUFFER_SIZE == 256
   // special case for receiver buffer size=256
   if (++rx_counter == 0) rx_buffer_overflow=1;
#else
   if (rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
   if (++rx_counter == RX_BUFFER_SIZE)
      {
      rx_counter=0;
      rx_buffer_overflow=1;
      }
#endif
   }
}
            
#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+
char getchar(void)
{
char data;
while (rx_counter==0);
data=rx_buffer[rx_rd_index++];
#if RX_BUFFER_SIZE != 256
if (rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
#endif
#asm("cli")
--rx_counter;
#asm("sei")
return data;
}
#pragma used-
#endif
        

// Standard Input/Output functions
#include <stdio.h>
#include <stdlib.h>

#include <delay.h>
//дисплей
#asm
.equ __lcd_port=0x18
#endasm  

       
// Declare your global variables here  

unsigned int tm=10;
unsigned int t5,t4,t2;                                          
int tmc;
unsigned char bufer[2];


                  
void display()          //Функция отображение надписи "ONLINE" на LCD
{
 lcd_clear();           //Очистка дисплея
 lcd_putsf("ONLINE");   //Вывод надписи "ONLINE" на дисплей
 //lcd_gotoxy(0,1);       //Переход курсора на второй ряд и первый разряд досплея
}


//Таймер0 таймаута бездействия
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Reinitialize Timer 0 value
TCNT0=0xFF;
// Place your code here
//while(1){
//delay_ms(1000);
//printf("  ");
//}
--t2;                   
}

// Timer2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{  
// Reinitialize Timer2 value
TCNT2=0xFF;
// Place your code here

t4++;

if((t4==30) && (t5==0)){

//printf("tmc=%d", tmc);
lcd_gotoxy(0,1);           //перенос курсора
lcd_putsf("                ");    //вывод на дисплей "" 
lcd_gotoxy(0,1);           //перенос курсора
lcd_putsf("REQ");    //вывод на дисплей ""
sprintf(bufer,"%d",tmc);
lcd_gotoxy(4,1);
lcd_putsf("  ");
lcd_gotoxy(4,1);
lcd_puts(bufer);

tmc--;

if(tmc<0){
lcd_gotoxy(0,1);           //перенос курсора 
lcd_putsf("                ");
lcd_gotoxy(0,1);           //перенос курсора 
lcd_putsf("PING");    //вывод на дисплей ""
//delay_ms(1000);
//lcd_gotoxy(0,1);           //перенос курсора 
//lcd_putsf("    ");    //вывод на дисплей ""
//printf("1SREG=%x", SREG);
printf("1UCSRA=%x", UCSRA);
printf("PING");

printf("2UCSRA=%x", UCSRA);

delay_ms(1000);

UCSRA=0x60;
printf("3UCSRA=%x", UCSRA);
t5=0;
tmc=tm;
 }
t4=0;
} 
}


// External Interrupt 0 service routine

interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here            
}

void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTB=0x00;
DDRB=0x00;

// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=In 
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=T 
PORTD=0x00;
DDRD=0xFE;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 7,813 kHz
TCCR0=0x05;
TCNT0=0xFF;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=0xFFFF
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x05;
TCNT1H=0x00;
TCNT1L=0xFF;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: 7,813 kHz
// Mode: Normal top=0xFF
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x07;
TCNT2=0xFF;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Rising Edge
// INT1: Off
GICR|=0x40;
MCUCR=0x03;
GIFR=0x40;

// Timer(s)/Counter(s) Interrupt(s) initialization
//TIMSK=0x00;
//TIMSK=0x01;
TIMSK=0x41;


// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=0x00;
UCSRB=0x98;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x33;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// ADC initialization
// ADC disabled
ADCSRA=0x00;

// SPI initialization
// SPI disabled
SPCR=0x00;

// TWI initialization
// TWI disabled
TWCR=0x00;

// Alphanumeric LCD initialization
// Connections are specified in the
// Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
// RS - PORTB Bit 0
// RD - PORTB Bit 1
// EN - PORTB Bit 2
// D4 - PORTB Bit 4
// D5 - PORTB Bit 5
// D6 - PORTB Bit 6
// D7 - PORTB Bit 7
// Characters/line: 8

lcd_init(16);          //инициализация дисплея
tmc=tm;
printf("start");     //вывод в УАРТ "terminal= "

display();                //отображение надписи "онлайн"

#asm("sei")

while (1)                //бесконечный цикл (цыклическое выполнение бипа онлайн)
  {   
  // if(t==0)              
   // {
     // printf("t=0");
     delay_ms(1000);
   // } 
   if (rx_counter!=0){
   printf("rc=%c", getchar());   
   
   }
     printf("UCSRA=%x", UCSRA);
  }                      
}                        
Реклама
Аватара пользователя
SergeBS
Вымогатель припоя
Сообщения: 683
Зарегистрирован: Пт апр 11, 2008 11:24:53
Откуда: Владимир

Re: delay_ms + прерывания?

Сообщение SergeBS »

Граждане, вы что, прикалываетесь?
Вошел в прерывание, т.е. ЗАПРЕТИЛ на время его обработки все прерывания, а там забабахал задержку. И удивляешься что при ВСЕХ запрещенных прерываниях какое-то не работает?
А что, должно быть по-другому?
Поставить перед _delay_ms - sei();
А после cli();
При выходе из прерывания флаг разрешения автоматом выставляется.
Человек - это звучит гордо, а обезьяна - объективно...
Реклама
Аватара пользователя
SergeBS
Вымогатель припоя
Сообщения: 683
Зарегистрирован: Пт апр 11, 2008 11:24:53
Откуда: Владимир

Re: delay_ms + прерывания?

Сообщение SergeBS »

Я вообще не понимаю: вся обработка делается в прерывании.
В любом букваре советуют выставить в прерывании флаг - признак необходимости какой-то обработки и вывалиться из прерывания, всю обработку делая в основном цикле.
И тут ТАКОЕ... :o
Не Кашкаров случайно надоумил так делать? :)
Человек - это звучит гордо, а обезьяна - объективно...
sbvp
Родился
Сообщения: 12
Зарегистрирован: Пт авг 21, 2009 21:00:12
Откуда: Bila Tserkva

Re: delay_ms + прерывания?

Сообщение sbvp »

SergeBS писал(а):Граждане, вы что, прикалываетесь?
Вошел в прерывание, т.е. ЗАПРЕТИЛ на время его обработки все прерывания, а там забабахал задержку. И удивляешься что при ВСЕХ запрещенных прерываниях какое-то не работает?
А что, должно быть по-другому?
Поставить перед _delay_ms - sei();
А после cli();
При выходе из прерывания флаг разрешения автоматом выставляется.
Спасибо, заработало! Мысли вокруг этого были, но что-то не додумался, пробовал сначала cli();, а потом sei();. Думал, что по логике когда он выходит из прерывания, то разрешает все прерывания, а значит ЮСАРТ должен принимать, а тут оказалось...
SergeBS писал(а):Я вообще не понимаю: вся обработка делается в прерывании.
В любом букваре советуют выставить в прерывании флаг - признак необходимости какой-то обработки и вывалиться из прерывания, всю обработку делая в основном цикле.
И тут ТАКОЕ... :o
Не Кашкаров случайно надоумил так делать? :)
Нет, я по букварю Лебедева и из универа что-то помню, но все козни - это моя личная фантазия :)))
А какой "букварь" посоветуете?
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
SergeBS
Вымогатель припоя
Сообщения: 683
Зарегистрирован: Пт апр 11, 2008 11:24:53
Откуда: Владимир

Re: delay_ms + прерывания?

Сообщение SergeBS »

Хороший вопрос. Особенно если лет 5 только конкретные даташиты читать, т.е. эпоха букварей проскочила незаметно.
Не знаю, в каком букваре точно такое есть, но в любом просто ДОЛЖНО быть: в прерывании делаются исключительно действия, которые нельзя прерывать (такая вот тавтология). Все прочее - в основном цикле. Т.е. UART выставил прерывание - быстренько прочитать буфер, чтобы освободить для следующего приема и вывалиться. Дальше можно не спеша обрабатывать полученное - оно никуда не денется, да и новые данные без ошибок будут приняты.
Как-то так.
Попробуй полистать Фрунзе, ну ARV еще есть.
Короче, ну не знаю я, где такое конкретно есть. Это вообще для любой системы с прерываниями так. Мне тоже специально искать - где это.
Вообще при любом проекте, как стало ясно, что предстоит делать, полезно список аппнотов от Атмел полистать - там мноого полезного уже готового к применению. Я делаю так.
Человек - это звучит гордо, а обезьяна - объективно...
Реклама
sbvp
Родился
Сообщения: 12
Зарегистрирован: Пт авг 21, 2009 21:00:12
Откуда: Bila Tserkva

Re: delay_ms + прерывания?

Сообщение sbvp »

Понял, спасибо!
Реклама
Аватара пользователя
SergeBS
Вымогатель припоя
Сообщения: 683
Зарегистрирован: Пт апр 11, 2008 11:24:53
Откуда: Владимир

Re: delay_ms + прерывания?

Сообщение SergeBS »

В общем все плохо :(. 4-5 букварей по МК листанул - мимо. В обучалках местных тоже пусто. Как обрабатывать прерывания - есть везде, а вот что код в прерываниях нужно до минимума сводить - нигде. Я это дело еще в прошлом веке на архитектуре ЭВМ уяснил, а для МК оказывается и нет ничего. Хоть самому пиши.
Человек - это звучит гордо, а обезьяна - объективно...
Аватара пользователя
menzoda
Вымогатель припоя
Сообщения: 535
Зарегистрирован: Вт авг 28, 2012 22:21:33

Re: delay_ms + прерывания?

Сообщение menzoda »

По этому поводу ничего нет, потому что сведение кода в прерывании до минимума не есть априори верное решение. Что делать в прерывании, а что не делать в нем, зависит только от конкретной задачи и архитектуры ПО.

К примеру, во многих документах по управлению АД от Texas Instruments, практически весь функционал реализован в одном прерывании. Почему? Потому что, как они говорят, у МК достаточно сил все обработать в одном прерывании, да и проще так. А раз в данном случае так проще, то почему бы и нет?

В общем, думать надо и самому решать, что делать в прерывании, а что нет. Другое дело, что нужен некий опыт, чтобы не наколоться на этом.
clawham
Поставщик валерьянки для Кота
Сообщения: 1957
Зарегистрирован: Пт окт 31, 2008 09:38:55
Откуда: Одесса
Контактная информация:

Re: delay_ms + прерывания?

Сообщение clawham »

По поводу прерываний - в данном случае нет ничего серьёзного что нужно было бы так срочно отрабатывать - ставьте флаг что прерывание было и в основном цикле проверяйте

Дальше - очень не рекомендую так работать с еепром.....в начале программы выделите буффер в обычной памяти и туда скопируйте то что в еепроме ибо в случае обесточивания кристалла во время чтения еепрома - данные в текущей ячейке с вероятностью 75% испортятся.....текущая ячейка остаётся текущей и через 10 000 циклов после окончания общения с еерпом потому я просто создаю в первой ячейке переменную 8 бит целое и после каждого сеанса общения с еепромом инкрементирую её.....текущей получается она и её испорченность не влияет на моё настроение :)
Что нас не убило сделало нас осторожней
Не доверяйте русским лужам - это может быть вход в метро.
sbvp
Родился
Сообщения: 12
Зарегистрирован: Пт авг 21, 2009 21:00:12
Откуда: Bila Tserkva

Re: delay_ms + прерывания?

Сообщение sbvp »

clawham писал(а):По поводу прерываний - в данном случае нет ничего серьёзного что нужно было бы так срочно отрабатывать - ставьте флаг что прерывание было и в основном цикле проверяйте

Дальше - очень не рекомендую так работать с еепром.....в начале программы выделите буффер в обычной памяти и туда скопируйте то что в еепроме ибо в случае обесточивания кристалла во время чтения еепрома - данные в текущей ячейке с вероятностью 75% испортятся.....текущая ячейка остаётся текущей и через 10 000 циклов после окончания общения с еерпом потому я просто создаю в первой ячейке переменную 8 бит целое и после каждого сеанса общения с еепромом инкрементирую её.....текущей получается она и её испорченность не влияет на моё настроение :)
Вы имеете ввиду переменную tp ?!
Аватара пользователя
Kavka
Мудрый кот
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Re: delay_ms + прерывания?

Сообщение Kavka »

Небольшое замечание.
Если я правильно понял о каком _delay_ms идёт речь, то если во время выполнения _delay_ms произойдёт прерывание, то задержка увеличиться на время выполнения прерывания.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Аватара пользователя
SergeBS
Вымогатель припоя
Сообщения: 683
Зарегистрирован: Пт апр 11, 2008 11:24:53
Откуда: Владимир

Re: delay_ms + прерывания?

Сообщение SergeBS »

Понял правильно. Если при задержке _delay_ms будет прерывание, то она увеличится на время этого прерывания, т.е. на 2 перехода (в прерывание и возврат из него) и время обработки прерываний.
menzoda писал(а):К примеру, во многих документах по управлению АД от Texas Instruments, практически весь функционал реализован в одном прерывании. Почему? Потому что, как они говорят, у МК достаточно сил все обработать в одном прерывании, да и проще так. А раз в данном случае так проще, то почему бы и нет?
Боюсь, что ребятки из TI - не авторитет в таком вопросе. Они не проектировали ЭВМ и знают только 1 частный случай - свой. Есть только 1 прерывание и больше ничего. Им главное его успеть отработать до прихода его же 2-й раз. Не успевали бы - система бы не работала вообще.
Акцент поставлен неверно. Дело не в возможности обработать или не обработать все в одном прерывании, поскольку это всего лишь место, где лежит код обработки. Дело в другом, а именно:
1. Возможность возникновения другого прерывания во время обработки первого. Если невозможно - делай обработку где хочешь. Как у них. Ну есть всего одно прерывание, пока его обрабатываем - больше ничего не будет. Какие проблемы?
2. Допустимость пропуска или задержки обработки другого прерывания. Если допустимо - опять же делай где хочешь. Ну пропустил, ну задержал - да и фиг бы с ним. Не очень и хотелось :).
А вот если недопустимо - тады ОЙ! Как раз тутошний случай. В прерывании рисуем вывод на дисплей или делаем задержку - да пожалуйста. Вот только если за это время придет 2 символа в UART - 2-му кирдык, и затык с приемом - ошибка. А если мы этого не хотим, то нужно быстренько оттарабанить то, что НЕ в прерывании не сделать, и "освободить площадку" - чтобы успеть отработать приход символа по UART до прихода следующего. Или отрабатывая это прерывание - периодически проверять, что с UART - не пора ли осчастливить его обработкой принятого символа. Поллинг, работаем без прерываний.
Время гарантированной реакции на прерывание - это из характеристик систем реального времени. И там все гораздо печальнее. А где такие системы - ну понятно, да?
Не наш случай - спим спокойно. За нами не придут :). За ребятками из TI - тоже.
Человек - это звучит гордо, а обезьяна - объективно...
Аватара пользователя
balmer
Это не хвост, это антенна
Сообщения: 1433
Зарегистрирован: Вс дек 02, 2012 03:13:48
Откуда: Калининград

Re: delay_ms + прерывания?

Сообщение balmer »

sbvp писал(а):рабатывает прерывание по переполнению таймера (в данном случае таймер2), т.е. когда в этом сработавшем таймере доходит до delay_ms(1000)
Когда начинает выполняться прерывание, все прерывания автоматически запрещаются. Когда оно заканчивается - то разрешаются. Поэтому и не срабатывает прерывание по UART. Обычно всякие delay_ms пишут в основном коде, а из прерывания стараются выйти побыстрее.
Ответить

Вернуться в «AVR»