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

Автоматический выход из ждущего режима uart_receive();


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

#define F_CPU 16000000UL             // Тактовая частота микроконтроллера
#define BAUD 9600UL                                 // Скоорость приемо-передачи для консоли
#define MYUBRR (F_CPU/(BAUD*16)-1)        // Согласно заданной скорости подсчитываем значение для регистра UBRR



void uart_init(void)                             // Объявление функции UART для скорости приемо передачи
 {
    UBRR0H=(MYUBRR>>8);                  // Старшие 8 бит
    UBRR0L=MYUBRR;                                      // Младшие 8 бит)
    UCSR0B|=(1<<TXEN0)|(1<<RXEN0);                      // Бити разрешения приемо-передачи
    UCSR0C|=(1<<UCSZ00)|(1<<UCSZ01);                   // Устанавливем формат 8 бит данных
 }
 
 void uart_transmit(unsigned char data)                    // Объявление функции трансляции (вывода на экран)
 {
    while (!(UCSR0A & (1<<UDRE0)));                     // Ожидаем когда очистится буфер передачи
    
    UDR0 = data;                                        // Помещаем данные в буфер, начинаем передачу
 }


 unsigned char uart_receive(void)
 {
   
    while(!(UCSR0A & (1<<RXC0)));                          // Ожидаем пока данные будут получены
    return UDR0;                                         // Возврат 8-bit данные
                                         
 }

void USART_Flush(void){
    unsigned char dummy;
    while (UCSR0A & (1<<RXC0)) dummy = UDR0;
}

Добрый день! уважаемые форумчане, есть такая необходимость, как выход из ждущего режима  например с = uart_receive(); по приему символа чтоб при получение некоторых данных на другие пины от датчика или от другого МК, выходил на короткое время пока не выводится некоторые символы с помощью функции uart_transmit(data[i]); в основном цикле из массива данных  а потом сразу же после вывода символов данных, вернулся в режим готовности для приема символа с клавиатуры с = uart_receive();.
Что только не пробовал но никак не могу заставить UNO автоматически чтоб выходил из ждущего режима при получении данных для выполнения в основном цикле по выводу на консоль, данные будут выводиться на консоль Putty, как можно эту задачу организовать?

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

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

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

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

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

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

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

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

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

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

7 часов назад, IMXO сказал:

/////////////

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

11 часов назад, Геннадий сказал:

///////////////

Не тот режим  имел в виду, я имел в виду когда открываешь консоль Putty и там МК ждет ввода символа с клавиатуры, при этом  не срабатывает нужный мне цикл по выводу данных на консоль, да по прерыванию выводится но загрузить прерывания большими кодами не хотелось бы. Там всего лишь одна задача, как только приходить данные по Пинам и тут же отвязаться от функция uart_receive(void) и начинается основной цикл по выводу на экран данных и после, чтоб сразу же вернулась в функцию  uart_receive(void), где ждет ввода символа с клави.

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

6 часов назад, Сулейман Мавруханов сказал:

Да по прерыванию работает, но хотелось бы в этом деле обходить прерывания, так как там будут достаточно разнообразный коды и циклы...

Вот поэтому лучше именно прерывания.

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

по этому поводу у геймеров есть хорошая поговарка: "Если играя за мага на 100м левеле Вы начинаете искать двуручный меч с бонусами к силе и тяжелую броню, то Вы явно делаете что-то не так..."
перефразируя если при написании кода Вам для проверки флага  от перефирии потребовался бесконечный цикл, то однозначно Вы явно делаете что-то не так.

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

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

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

4 минуты назад, Геннадий сказал:

В чужих примерах частенько (почти всегда) применяется бесконечный цикл

а кто ж нормальный код в открытый доступ просто так выкладывает:rake::huh:

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

7 часов назад, Сулейман Мавруханов сказал:

хотелось бы в этом деле обходить прерывания, так как там будут достаточно разнообразный коды и циклы,

Прием данных по UART по любому должен быть в прерывании, иначе будут постоянные пропуски данных. Тем более никто не мешает принимать данные в прерывании, а обрабатывать в цикле.

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

3 часа назад, IMXO сказал:

нормальный код в открытый доступ

А голова на плечах для чего?

А так конечно, ардунисты позасрали весь иннет своими "костылями"

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

5 часов назад, BARS_ сказал:

Тем более никто не мешает принимать данные в прерывании, а обрабатывать в цикле.

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

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

while(1){
  if(flag_data_ready){
      // вывод на дисплей
  }
}

 

9 минут назад, Сулейман Мавруханов сказал:

приходится запускать именно в прерывании и по другому никак

Что мешает крутить его в цикле?

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

52 минуты назад, BARS_ сказал:

Что мешает крутить его в цикле?

Мешает то, что флаг бита RXCO из  цикла while(!(UCSR0A & (1<<RXC0)));  постоянно находится в 1 пока символ с клавиатуры не наберешь, вот тут то и проблема, принудительно этот бить с помощью прерываний сбросить я не смог, так как флаг этого бита в 1 то и цикл тут бесконечный.

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

3 минуты назад, Сулейман Мавруханов сказал:

что флаг бита RXCO из  цикла while(!(UCSR0A & (1<<RXC0)));  постоянно находится в 1

Такого не бывает. Даже даташит об этом говорит:

image.png.a994195328c99fe1f8c3083ff6ef342f.png

Флаг 1 когда буфер не пуст и 0 после прочтения данных из буфера. И нафиг вам вообще этот флаг, если прием идет в прерывании? Что мешает в прерывании сделать flag_data_ready = 1; и обнулить его после обработки данных в цикле? Ну и вообще-то вот тут

while(!(UCSR0A & (1<<RXC0)));

вы как раз таки ждете, пока RXC0 станет 1. А вот до тех пор, пока он 0 цикл не будет завершаться.

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

29 минут назад, BARS_ сказал:

вы как раз таки ждете, пока RXC0 станет 1. А вот до тех пор, пока он 0 цикл не будет завершаться.

Ах да ошибся, выразился наоборот, в таком случае если я подниму его на 1 в другом прерывании запустится цикл или нет сейчас проверю

9 минут назад, Сулейман Мавруханов сказал:

в таком случае если я подниму его на 1 в другом прерывании запустится цикл или нет сейчас проверю

Проверил, не запустился цикл if(flag == 1){
        for(y = 0; data[y] != '\0'; y++){
            uart_transmit(data[y]);
        }

в основном цикле while к сожалению. 

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

А во flag вы где пишите 1? В общем, код должен выглядеть примерно так:

 

/***************************************************************************************/
#define RX_BUF_LEN 32
uint8_t rx_data[RX_BUF_LEN]
uint8_t rx_cnt = 0, rx_data_ready_flag;

ISR(USART0_RX_vect)
{
    rx_data[rx_cnt] = UDR0;
    rx_cnt++; 

    if (rx_cnt == RX_BUF_LEN)
    {
        UCSR0B &= ~((1 << RXCIE0) | (1 << RXEN0)); // отключить прерывания и прием на время обработки данных
        rx_data_ready_flag = 1;
    }
}

int main(void){
 //настройка МК

	while(1){
		if(rx_data_ready_flag){
			//какие-то действия

          	rx_cnt = 0;
			rx_data_ready_flag = 0;
          	UCSR0B |= (1 << RXCIE0) | (1 << RXEN0);
		}
	}
}

 

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

5 часов назад, BARS_ сказал:

А во flag вы где пишите 1?

В прерывании, например ISR(PCINT0_vect) и там же пишу вот это тоже UCSR0A |= (1<<RXC0);

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

5 часов назад, BARS_ сказал:

В общем, код должен выглядеть примерно так:

Да, она так работает пока в цикл while не появится например вот эту строчку char c = uart_receive(); проверь и убедись.

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

В 09.08.2022 в 16:04, Сулейман Мавруханов сказал:
unsigned char uart_receive(void)

 

1 час назад, Сулейман Мавруханов сказал:

char c = uart_receive();

Разные типы данных. Может не влияет, а может влияет...

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

28 минут назад, Огонёк сказал:

Разные типы данных. Может не влияет, а может влияет...

В этом случаи не повлияют поверь, вот пример uart_transmit(uart_receive()); тоже рабочий пример,

для четкого понимания задачи приведу самый короткий пример:

unsigned char c;
uint8_t flag = 0;

ISR(PCINT0_vect){
   if(PINB & (1 << PB0)){
      flag = 1;
   }else{
      flag = 0;
   }
}

int main(){
   interrupt_init();
   sei();
   
   while(1){
      if(flag == 1){	// Надо запустить это условие с циклом for при получнии прерывания и после вернутся в исходное положение.
         for(y = 0; data[y] != '\0'; y++){
            uart_transmit(data[y]);
         }
        flag == 0;
      }
      c = uart_receive();	/* Если отсюда не отвязаться, никак не срабатывает условие выше, чтоб условие выше сработал приходится часто нажимать на какую нибуь клавишу. ЗАДАЧА: КАК ОТВЯЗАТЬСЯ ОТСЮДА ДЛЯ ВЫПОЛНЕНИЯ УСЛОВИЯ ВЫШЕ И СРАЗУ ЖЕ ПОСЛЕ ВЫПОЛНЕНИЯ СЮДА ЖЕ ВЕРНУТСЯ? */
     uart_transmit(с);
   }
   
}

 

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

Уберите while() из uart_receive(), тогда не будет задержки. Если букву получили, то её возвращаем, если не получили, то не ждём и возвращаем 0.

unsigned char uart_receive(void)
{
    if(UCSR0A & (1<<RXC0))    // Если получили
        return UDR0;           // Возврат 8-bit данные
    return 0;                  // Не получили, возврат 0
}

А в самой программе проверяем, если не ноль, то что-то делаем

c = uart_receive();
if(c)
{
    uart_transmit(с);
}

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

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

19 часов назад, Сулейман Мавруханов сказал:

там же пишу вот это тоже UCSR0A |= (1<<RXC0);

Нахрена? Оставьте в покое этот флаг и не трогайте его вообще. ты уже в прерывании, этот флаг нельзя трогать. Я ведь выше уже дал описание его работы, нафиг писать в него 1? Он в принципе недоступен для записи, т.к. read only, и сбрасывается в 0 сразу же после чтения регистра данных:

image.png.8e362a18be51a36f1cbabb6c6b257637.png

 

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

uint8_t rx_data = 0;

ISR(USART0_RX_vect)
{
    rx_data = UDR0;

    rx_data_ready_flag = 1;
}

 

19 часов назад, Сулейман Мавруханов сказал:

c = uart_receive();

Где у меня в коде данная функция?

 

	while(1){
      	if(flag == 1){	// Надо запустить это условие с циклом for при получнии прерывания и после вернутся в исходное положение.
         for(y = 0; data[y] != '\0'; y++){
            uart_transmit(data[y]);
         }
        flag == 0;
      }
     //ЧУШЬ!!!
      c = uart_receive();	/* Если отсюда не отвязаться, никак не срабатывает условие выше, чтоб условие выше сработал приходится часто нажимать на какую нибуь клавишу. ЗАДАЧА: КАК ОТВЯЗАТЬСЯ ОТСЮДА ДЛЯ ВЫПОЛНЕНИЯ УСЛОВИЯ ВЫШЕ И СРАЗУ ЖЕ ПОСЛЕ ВЫПОЛНЕНИЯ СЮДА ЖЕ ВЕРНУТСЯ? */
     uart_transmit(с);
   }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

uint8_t rx_data = 0;

ISR(USART0_RX_vect)
{
    rx_data = UDR0;

    rx_data_ready_flag = 1;
}

int main(void)
{

	while (1)
	{
		if (flag == 1) // Надо запустить это условие с циклом for при получнии прерывания и после вернутся в исходное положение.
		{ 
			for (y = 0; data[y] != '\0'; y++)
				uart_transmit(data[y]);

			flag == 2;
		}
	}

	if (flag == 2 && rx_data_ready_flag) // если была нажата кнопка и пришла данные по uart
	{ 
		uart_transmit(rx_data);

		flag = 0;
		rx_data_ready_flag = 0;
	}
}

 

13 часов назад, Yurkin2015 сказал:

Уберите while() из uart_receive(),

Да никакого uart_receive там вообще быть не должно. На таких камнях прием данных ВСЕГДА должен быть в прерывании и больше нигде. Там уже данные пишутся в глобальный буфер и по достижению необходимого их количества выставляется флаг окончания приема. Ну либо по приему каждого символа, если алгоритм уж настолько кривой, что не использует пакетную передачу данных.

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

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

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

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

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

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

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

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

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

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

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

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