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

Автоматический выход из ждущего режима 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, как можно эту задачу организовать?

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

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

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

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

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

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

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

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

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

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

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

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

Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств. Подробнее параметры и результаты тестов новой серии PLM по ссылке.

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

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

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

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

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

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

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

по этому поводу у геймеров есть хорошая поговарка: "Если играя за мага на 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 пользователей онлайн

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

    • Romanchek82, не советую.    Но сам мажу все свои 29 лет всё синтетикой. Даже настенные часы и будильники. Всё работает. Да, ещё. Мазать надо мягким тонким чем то. Я использую спичку, убрав опилки. Чтобы не царапать поверхность. И ещё, тонко надо. Без фанатизма. Масло жидкое и растекается. Как раз под 0,1 микрон.  А масло всегда остаётся на дне канистры.. после замены.
    • 100х100 понятно, что не помещается. По 600 руб. за плату ещё более менее. Если 4 платы удастся продать, то вообще шикарно будет.
    • Я такой собирал на макетке: http://labkit.ru/html/show_meter?id=476
    • Прошу помощи Прачитал всю ветку. От 12 страницы - ещё два раза. В электронике не силён, в Ардуийно 0, но учусь уже месяц. Пока собрал всё по 2.0 версии, схема подключения провод к проводу как на первой странице https://cxem.net/arduino/images/arduino245-2.png Двигатель намотки kh42jm2, на укладчик Mitsumi M49SP-2K  шагом 7,5 гр.  Драйвера А4988. Оба двигателя проверенны, работали на простом стече с библиотеки АлехГивер. Энкодер чужой, WAVGAT(MJKDZ), такой же как в последнем сообщение 13 стр. Переход делал по информации в интернете https://i.postimg.cc/ZnjKmGN8/Rotary-encoder-module-Blue-Pinout.jpg То есть, земля и питание 1:1,     S1-CLK    S2-DT     KEY-SW Повторюсь, обвязка как на первой странице, то есть на вход энкодера напаеные резистора и конденсаторы 10нФ ХОТЯ на странице 14, последнее сообщение, Александр в п.4 пишет, что этого не надо делать. Если так - уберу. Плата Ардуино МЕГА, просто она есть  наличие. Все пишут про CNC shield, у меня его нет, но могу купить, просто посылка займёт 2 дня. У меня всё подключенно по проводам. Повторюсь, как на 1 странице.  Дисплей. Уже был у меня LCD2004 IIC I2C, правильно ли я понимаю, что I2C это некий модуль с другой стороны, он у меня уже подключен (напаен). Третий раз повторю, что у меня подключенно как на первой странице. То есть, LCD проводами напаен как есть: с левой стороны 4,6 и 11,12,13,14 пины прямо на плату Ардуино.  Понимаю, что можно подключать от  I2C , но мне пока не понятно как, делал так, как вижу на рисунке. ПРОБЛЕМА: нет жизни вообще. Никакого движения. Нет подсветки в LCD. Ничего. Просба помочь задействовать не большими кусками. То есть, с перва разобратся с LCD. Свет в нём и хероглифы было бы уже достижением.  Потом идти к энкодеру, чтоб передвигал стрелку в LCD.  А потом и до двигателей доеду. Уменя уже есть намоточный станок. В двух словах, всё собранно на простых двигателях, они почти не зависит друг от друга. Скорость укладчика выставлена как есть, резьба М6 шаг 1. А скорость намоточного подстраиваю под движение каретки укладчика, подбирается оптыным путём, на регуляторе на НЕ555 миикросхеме. Минус - нету плавного старта. https://youtu.be/cFGK5TLnlno?si=Ju31bsIpXNEGINxx
    • Есть такое, 3к руб., выходит по 600р плата. А 100*100 в хантек не лезет, я максимум 75мм намерил.
    • Я в таком размере даже не пытался в Китае заказывать. У них же всё, что более 100х100, имеет не гуманную цену. 
    • там не просто шим-ка, а  "Выпаиваем вон ту круглую херню и аккуратно распаковываем из боченка. В руках у нас плата залитая как бы компаундом который легко отковыривается. Внутрях платка с одной стороны шим о 6 ногах с другой ключик и токовый датчик" (с) с одного из форумов. SG2368-48. можно заменить на TOP226y с оптроном.
×
×
  • Создать...