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

Не Работают Прерывания Uart


l-e-o-n-a-r-d-o

Рекомендуемые сообщения

Пишу в кодевижине. Тини2313

Есть небольшая програмка, которая в мейне с помощью getchar() работает отлично. Что именно делает: если принят первый байт 253, тогда остальных 7 записывает в буффер.

вот она

while (1) // безконечный цикл

{

if( getchar() == 253 ) // ждем того момента пока не словим "старт"

{

for( i=0; i<7; i++ ) // если приняли ютарт, считываем еще 7 байт принятых

{

rx_buffer = getchar(); // и помещаем их в буффер

}

frame(); // вызываем вункцию анализатора принятой посылки

}

}

вот это работает замечательно. Теперь это же нужно засунуть в прерывания. Да проблема в том, что сколько я не пытался, прерывания вообще отказываются работать, точней такое впечатление что первое сработало, и на этом все закончилось. (обработку прерываний формирует генератор кодевижина). Даже текст привводить не буду, потому что ниче не работало. (даже один байт не принимает!) Вчера я еще 2 часа воевал с протеусом в котором вообще ничего не работало. :angry:

вот например такое:

// USART Receiver interrupt service routine

interrupt [uSART_RXC] void usart_rx_isr(void)

{

char status,data;

data=UDR;

putchar('3');

}

тоже не работает :(

Дайте мне пожалуйста РАБОЧИЙ пример работы с прерываниями в кодевижине от юарта. Или может скажите где тут какие то подводные камни? фьюзы? ....

чем шире кругозор, тем тупее угол обозрения

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

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

// USART initialization

// Communication Parameters: 8 Data, 1 Stop, No Parity

// USART Receiver: On

// USART Transmitter: On

// USART Mode: Asynchronous

// USART Baud Rate: 115200

UCSRA=0x00;

UCSRB=0xD8;

UCSRC=0x06;

UBRRH=0x00;

UBRRL=0x01;

// USART Receiver interrupt service routine

interrupt [uSART_RXC] void usart_rx_isr(void)

{

char status,data,i=0;

bit rec=0;

status=UCSRA;

data=UDR;

if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)

{

if (rec==1) { rx_buffer=data; i++;}

if (i == 8) { i=0; rec=0; frame_received=1; frame();}

if (data == 253) {rec=1;}

};

}

даже и 1 байт не хочет принимать, не говоря уже о этом.

чем шире кругозор, тем тупее угол обозрения

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

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Лучше комментарий к коду.

Как не раз указывалось, в прерывании лучше не задерживаться и уж тем более не организовывать проверки, циклы, счетчики.

Вот мои замечания.

Начнем с того, что прерывание наступает КАЖДЫЙ РАЗ, когда в приемнике появляются принятые данные (байт). В твоем коде, l-e-o-n-a-r-d-o, все переменные будут сбрасываться при приеме каждого байта, что не позволит выполнится ни одному условию.

Например:

// USART Receiver interrupt service routine

interrupt [uSART_RXC] void usart_rx_isr(void)

{

char status,data,i=0;   обнулил данные, счетчик и статус

bit rec=0;                  обнулил флаг записи (я прав?)

status=UCSRA;

data=UDR;

if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)

{

if (rec==1) { rx_buffer=data; i++;} даже если попал сюда, не выполнится, т.к. rec=0 всегда (см. выше)

if (i == 8) { i=0; rec=0; frame_received=1; frame();} это тоже не выполнится, i=0 сам обнуляешь при входе в прерывание каждый раз (см. выше) 

if (data == 253) {rec=1;} выполнится в начале, но при следующем байте опять обнулится, сам это делаешь (см. выше)

Прием осуществляется по-байтно и каждый принятый байт будет вызывать прерывание, которое вначале все твои признаки обнулит, а потом ничего не сделает, т.к. обнуленные счетчики и флаги не проходят ни по одному условию. Вот примерно так. Может я чего и не допонял, пусть парни поправят, если что не так.

Зайди в прерывание, прочитай буфер в регистр (если нет ошибок - проверка это уже по желанию), далее можешь его сохранить в ОЗУ (для гарантии) и выходи из прерывания. Все остальное - сделаешь в мейне.

Изменено пользователем Геннадий
Ссылка на комментарий
Поделиться на другие сайты

мда, действительно, я об этом не подумал.. :wacko: Попробую исправить, сделав переменные глобальными, отпишусь о результате.

еще немного другой вопрос, в протеусе у когото хотя бы такое:

interrupt [uSART_RXC] void usart_rx_isr(void)

{

char status,data,i=0;

data=UDR;

putchar(data);

}

работает??? потому что сколько я не воевал с протеусом, он даже не хочет по приему моргнуть диодом..не то что отправить это назад.

чем шире кругозор, тем тупее угол обозрения

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

мда.. чудо свершилось! во первых, сами прерывания (1 байт) заработали!

interrupt [uSART_RXC] void usart_rx_isr(void)

{

char status,data;

data=UDR;

putchar('3');

}

вот такое заработало уже. А дальше- подкорректировал обработку прерываний для приема пакета 8 байт, и теперь все заработало как надо, так же как было в мейне (см. 1 пост) тоесть то что надо!!!! :rolleyes:

Огромное спасибо Геннадий, я б про это еще не скоро подумал бы!!! который день ломал голову над этим, а оно было под носом! как всегда вобщем)

остался только вопрос протеуса. У когото работают прерывания юарта в протеусе?? (свои я проверял на железе)

чем шире кругозор, тем тупее угол обозрения

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

  • 12 лет спустя...

Здравствуйте, у меня похожая проблема, не срабатывает прерывание по приему, помогите разобраться пожалуйста

void UART_Init(unsigned int speed)//Инициализация модуля USART 8bit, 2 stop bit
{
    cli();
    UBRR0H = (speed & 0x0F00) >> 8;
    UBRR0L = (speed & 0x00FF);
    UCSR0B |= ((1 << TXEN0) | (1 << RXEN0) /*| (1 << TXCIE0)*/ | (1 << RXCIE0));
    /* Set frame format: 8data,  2stop bit  */
    UCSR0C = (1<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00);
    sei();
}

ISR(USART_RX_vect) //Прерывания после приема
{     
   PORTB ^= (1<<5);    
}
int main(void)
{   
    UART_Init(103); //9600
    DDRB |= (1<<5);
}

P.s: было выяснено, что прерывания работает как бесканечный цикл, чего не должно быть, но оно есть.

Изменено пользователем Kostyanskiy
Ссылка на комментарий
Поделиться на другие сайты

@Kostyanskiy Чтобы прерывание загасить, в обработчике прерывания надо прочитать принятый байт. Типа, вот так

char data = UDR

 

Изменено пользователем Yurkin2015
Ссылка на комментарий
Поделиться на другие сайты

@Yurkin2015 благодарю, но я так и не понял с чем это связано, это по меньшей мере не логично, ведь прерывание это не цикл, где  можно почитать? В даташите я не помню чтобы это было описано. 

И тут еще один такой момент есть, я читаю строку по ЮАРТ и походу не могу считать буфер в который я её записываю,  идея такая:

При получении строки считывать регистр на приянятые данные, если там есть знак переноса строки, то у нас уже конец строки и в основном цикле парсим данные и понимаем какое условие выполнять, так проблема в том, что условие strcmp или strstr не читают данные с буфера приема, что порекомендуете сделать?

Вот код прерывания

ISR(USART_RX_vect) //Прерывания после приема
{   
    if ((UCSR0A & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN)) == 0)
    {
       while (UDR0 != 0x0D) 
       {
          sReceivedChar[rx_count++] = UDR0;       
          PORTB ^= (1<<5);
          if((UDR0 == 0x0D) && (FlagRecievData == 0)) FlagRecievData = 1;
       }            
    }
}

Вот код парсира, если убрать эту строку (strcmp(sReceivedChar, "1") == 0), то соответственно все заработает по приходу рандомного символа в порт

int main(void)
{   
    UART_Init(103); //9600
    DDRB |= (1<<5);

    while (1) 
    {
        if((strcmp(sReceivedChar, "1") == 0) && (FlagRecievData == 1))
        {
           UART_Transmit("OK");
           UART_Transmit((const char*)sReceivedChar);
           FlagRecievData = 0;
        }
    }
}

 

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

@Kostyanskiy Надо переделать обработчик прерывания:

ISR(USART_RX_vect) //Прерывания после приема
{   
    if ((UCSR0A & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN)) == 0)
    {
       if (UDR0 != 0x0D) 
       {
          sReceivedChar[rx_count] = UDR0;
          if (rx_count < sizeof(sReceivedChar)-1)
            rx_count++;
          PORTB ^= (1<<5);
       }            
       else
       {
            sReceivedChar[rx_count] = 0;
            rx_count = 0;
            FlagRecievData = 1;
       }
    }
}

 

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

@Yurkin2015  

8 минут назад, Yurkin2015 сказал:
sReceivedChar[rx_count] = 0;

Немного не понял для чего это, мы типа стираем 0x0D из sReceivedChar?

Это к сожалению тоже не работает:unsure:

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

@Kostyanskiy Мы не стираем 0x0D, а записываем 0 в конец строки. Если функция srtcmp() будет сравнивать строки от начала до конца, как она узнает где конец в строке sReceivedChar? До какого места сравнивать? Признаком конца как раз и является 0.

Кстати, для упрощения выкиньте strcmp() и для начала сравните только первый принятый символ:

if((sReceivedChar[0] == '1')&&(FlagRecievData == 1))
{
	UART_Transmit("OK"); 
	UART_Transmit((const char*)sReceivedChar);
	FlagRecievData = 0;
}

 

Изменено пользователем Yurkin2015
Ссылка на комментарий
Поделиться на другие сайты

@Yurkin2015 А вот это уже реально не понятно, откуда \r в начале строки, и почему 9-ка пропала в конце?:huh: 

image.png.6be9cdb6dc691735be6a6a7300faa1f4.png

P.s Недозаписался символ в конце при проверке условия UDR0 != 0x0D, исправил так, 

if (UDR0 != 0x0D)
       {
           sReceivedChar[rx_count++] = UDR0;
           if (rx_count > sizeof(sReceivedChar)) rx_count = 0;        
       }
       else
       {
           sReceivedChar[rx_count] = UDR0;
           sReceivedChar[rx_count + 1] = 0;
           rx_count = 0;
           FlagRecievData = 1;
       }          

Но что делать с  \r в начале, и как он там появляется, не понятно.

Изменено пользователем Kostyanskiy
Ссылка на комментарий
Поделиться на другие сайты

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

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

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

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

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

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

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
  • Сообщения

    • Музыки много не бывает! Да и можно потом архив передать по наследству, или продать на Авито. Кстати, сам бы такой купил, в свое время, но уже тоже чуть поднакопил. Терабайта три-четыре.
    • Конечно есть. Каскад Баксандала вообще линейнее, а тут еще с плавающим питанием. Тройка на выходе(правда кривоватая),термоузел Шиклаи, подстройка нуля. Дальнейшее развитие- Симметрон: тройка Акопова с термостабилизацией в УН и тройка Локанти в ВК. https://forum.cxem.net/index.php?/topic/225180-умзч-симметрон/#comments  
    • Данная схема передатчика температуры и влажности для метеостанции OREGON  BAR388HG.
    • Плавный розжиг ставил на 500Вт лампы вышек освещения (задолбался лазить их менять), лдс работали с дросселем, но без пускателя и не одного происшествия ))) Ах да, на вышки лазил с "парашютным" ремнем безопасности и переставлял только 1 опору из 4.
    • Вспомнил ещё одну скандальную схемку : Народ наверняка помнит "бум" по мягкому запуску ламп накаливания с целью продления срока службы оной ... Я тоже наступил на такие грабли !  Смысл затеи был в постоянном подогреве спирали, что уменьшает пусковой ток Л. в разы. (типо УРА-УРА мы победили!! ;-)   ) Схем было - КУЧА...и самая простая - это в параллель выключателю ставился кондей  (монтировался в свободное место в самом выключателе  0,25мкф х 400в) Режим Л. выбирался таким чтобы Л. была НЕхолодная, но и не светилась. Обычно лампы перегорают в момент включения и обычно "негромко".... И такая констукция действительно продлевала жизнь Л. ,а в момент отключения приятно гасилась с некоторым замедлением ... И всё было хорошо пока я не заметил , что спираль Л.стала провисать (вытягиваться ) ..ну вытягивается и вытягивается .... пока такая Л. не взорвалась с кучей мелкого стекла и неожданной яркой вспышкой!  Хорошо , что она висела не над столом (с закусью) да и детишек в этот момент в комнате небыло... Анализ: провисшая спираль создала долгоживущее(гдето 0,5сек плазьменное образование  (обычно такая цепь рвётся симметрично )  Температура в такой плазьме куда выше чем нагрев ,собственно, самой вольфрамовой спиральки , а т.к. Л. имеет наполнение т.н. буферным газом то этот газ сработал как дополнительное вещество в разгоне плазьмы(отсюда сильная вспышка) . Брызги металла по всей колбе, что привело к созданию масcы мелких осколков стекла .... ну и БА-БАХ ес-но ... ------------------------- Ещё было повторение схемы для ЛДС без дросселя (ставился конденсатор 10мкф х 600в ...какаято схема толи в ЮТ толи в Радио) Новинку смонтировал в новом стенде в виде освещения рабочего места . Через пару дней  встретил Шефа ,он и рассказал : Сижу , оформляю бумаги    и как рванёт эта твоя модернизация !!  Кондей не выдержал !!  С тех пор больше не занимаюсь такими "разработками" ;-) да и по жизни они уже "скончались" - везде запуск на электронике , или светодиоды ...  
×
×
  • Создать...