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

Не Работают Прерывания 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 пользователей онлайн

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

    • Спасибо за совет. Автором данного проекта я не являюсь, мне нужно было воссоздать уличный датчик для метеостанции взамен пропавшего(( Из разного найденного в интернете этот проект работает с моей станцией Орегон (спасибо автору). В понедельник попробую последовать Вашему совету. Но все равно куча непоняток  как блин это работает)) Если дело в неправильной отправки команды, то как на это влияет подключение датчика температуры? Если совсем не подключать таймер, то передача идет один раз (как и прописано в программе), станция принимает и отображает, но минут через сколько-то естественно станция уже ни чего не показывает, но с таймером питание полностью не пропадает с ардуинки, но передача сигнала каким-то образом работает по таймеру.  В моем понимании данная команда подается один раз потому, что таймер должен отключать питание МК после передачи сигнала и каждые 43 сек снова подавать питание (так того требует станция).  Ардуино передает показания температуры отключается полностью и 43 секунды мк не работает.  Сейчас у меня питание пока сделано на подпитке от солнечной батареи, но пару пасмурных дней и аккумулятор съедается до отключения(
    • thickman Так и сделаю. Вытащу из бу БП.  Буду знать, как отличить. Благодарю. Заменил транзисторы на IRFB20N50K. Картина стала, совсем другой.  Похоже трудность не в драйвере, на момент подвозбуда, переходные процессы, в нем, завершены. Увеличил затворные резисторы до 50ом, стало немного лучше.  Не понятно, почему верхний ключ греется несколько сильнее. Возможно, стоит посмотреть ток в коллекторе.  Снабберные емкости временно удалил, изменений не произошло.  Замена ТГР на другой, на кольце MSTN-16A-TH, так же, результата не принесла.   irfb20n50k.pdf
    • А что нить из ассортимента активных щупов производства СССР..))
    • Типа такого: https://aliexpress.ru/item/2044864227.html?sku_id=58855020183
    • поняли неправильно. У ТЛ494 никакой защиты нет, усилители ошибки не защита, они не должны приводить к ложным импульсам. Причем тут "микруха" ?  надо нагружать ВСЁ. До сих пор вообще непонятно о каком ИИП идет речь и сколько у него каналов. Бесполезно схему рисовать? - Помогать так бесполезно. Картина кривая по самое "немогу" продолжаются картинки, снятые через ногу и без цены деления.
×
×
  • Создать...