Обсуждаем контроллеры компании Atmel.
Ответить

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

Вт авг 09, 2022 15:52:47

Код:
 #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, как можно эту задачу организовать?

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

Ср авг 10, 2022 08:40:34

Изучайте прерывания и организовывайте обмен по-человечески, без "тупых" задержек.

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

Ср авг 10, 2022 09:51:56

unsigned char uart_receive(void)
{

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

}


Не проще ли организовать прерывание по приёму, чтоб не ждать флаг получения данных?

Добавлено after 20 minutes 49 seconds:
Код:
void USART1_IRQHandler(void)
{
  switch (регистр флагов прерывний(или событий))
  case (флаг принятых данных):
    принимаем данные;
    break; (или retutn данные)
  case (флаг передачи данных):
    делае чего нить после передачи данных (или не делаем);
    break;
  case (флаг пустого ругистра Rx/Tx):
    делае чего нить после (или не делаем);
    break;
  ...
  break;
}

Что-то вроде этого должно быть, нужно только правильно настроить прерывания по UART

Добавлено after 1 minute 20 seconds:
Сорят на АшиПки :)))

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

Ср авг 10, 2022 09:57:07

void USART1_IRQHandler(void)

Что-то вроде этого должно быть, нужно только правильно настроить прерывания по UART

Это же AVR, там у UART отдельный вектор на каждое событие

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

Ср авг 10, 2022 11:15:53

Это же AVR, там у UART отдельный вектор на каждое событие


Тогда вообще париться не нужно. Берёшь книжку Естевтеева про микроконтроллеры AVR (Если не ошибаюсь в фамилии автора) и читаешь что нужно делать. Там всё расписано до мелочей. Ну или наконец прочесть даташит. :))

Добавлено after 1 minute 19 seconds:
Кстати автор не написал каким МК пользуется...

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

Ср авг 10, 2022 11:49:46

AlexandrRa, ардуиной. Думаю, мега328.

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

Ср авг 10, 2022 15:02:54

Это же AVR, там у UART отдельный вектор на каждое событие


Тогда вообще париться не нужно. Берёшь книжку Естевтеева про микроконтроллеры AVR (Если не ошибаюсь в фамилии автора) и читаешь что нужно делать. Там всё расписано до мелочей. Ну или наконец прочесть даташит. :))

Добавлено after 1 minute 19 seconds:
Кстати автор не написал каким МК пользуется...

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

Ср авг 10, 2022 15:19:36

Код:


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


Добрый день! уважаемые форумчане, есть такая необходимость, как выход из ждущего режима например с = uart_receive();


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


Код:
 unsigned char uart_receive(void)
 {
   
   if ((UCSR0A & (1<<RXC0)))
       {             
          // Проверяем без ожидания, если данные получены, выставляем флаг ==1, если не получены сбрасываем флаг.
          bait_prochitan = 1;
        }else
        {
           bait_prichitan = 0; //нового байта нет
         }
         return bait_prochitan;
}

там где было с = uart_receive();
меняете на
if ( uart_receive() )
{
 c =  UDR0;
}

                                         
 }

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

Ср авг 10, 2022 15:33:18

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


Не советую так делать, есть возможность прочитать не тот байт или потерять вообще всю посылку. Т. к. чтение данных будет только один раз за цикл. А если данные приходят несколько раз за цикл и неизвестно когда по времени? Очень легко пропустить посылку.

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

Ср авг 10, 2022 16:04:25

Как на этом сайте вообще цитировать выделенный кусок текста и на этот косок текста ответить?

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

Ср авг 10, 2022 16:29:20

Sulik, надо нажать "редактор", а уже дальше выделять нужный текст и нажимать на цитирование.

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

Ср авг 10, 2022 16:36:19

>TEHb< писал(а):надо нажать "редактор", а уже дальше выделять нужный текст и нажимать на цитирование.

Спасибо! на этом сайте чуть по другому эта система работает.

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

Чт авг 11, 2022 03:07:37

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

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

Чт авг 11, 2022 10:07:21

AlexandrRa писал(а):Берёшь книжку Естевтеева про микроконтроллеры AVR (Если не ошибаюсь в фамилии автора)
если не помнишь фамилию, то прежде, чем её писать, нужно сначала её найти, а не писать хаотический набор букв.

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

Чт авг 11, 2022 11:32:37

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

Если я правильно понял написанное, вы только что подложили себе здоровенную мину. Какие еще циклы в прерываниях?!

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

Чт авг 11, 2022 13:24:00

Если я правильно понял написанное, вы только что подложили себе здоровенную мину.
:shock: :kill:
Согласен! Код в прерываниях должен быть минимальным. Я например в большинстве случаев там флаг сработки обычно ставлю. И НИКАКИХ ЦИКЛОВ В ПРЕРЫВАНИЯХ И ТЕМБОЛЕЕ ЗАДЕРЖЕК!!! Потом кода нужно, смотрю флаг и выполняю от этого флага всё что нужно (или не выполняю :)) ).

Добавлено after 6 minutes 16 seconds:
Код:
union Flags
{
    uint8_t TIM2_Flag: 1;       // сработка прерывания Timer2
    uint8_t TIM1_Flag: 1;       // сработка прерывания Timer1
    unit8_t  EXTI3_Flag: 1;    // сработка прерывания EXTI3
    uint8_t : 5;                // Резерв
} Status;

......

if (Status.EXTI3_Flag)
{
  ......
  Status.EXTI3_Flag= 0;
}

void EXTI3_IRQHandler(void)
{
  Status.EXTI3_Flag= 1;
/* Сброс флагов прерывания */
  EXTI_ClearITPendingBit(EXTI_Line3);
}



Что-то вроде этого...

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

Чт авг 11, 2022 13:49:01

Starichok51 писал(а):Какие еще циклы в прерываниях?!

например таких несколько штук
Код:
for(y = 0; data[y] != '\0'; y++){
            uart_transmit(data[y]);
        }

без каких либо задержек в delay, пока что работает без проблем.

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

Чт авг 11, 2022 14:41:32

Лучше сделать
Код:
  if (!Flag_data)  // Проверка на начало приёма пакета
  {
   uart_transmit(data[0]);  // в первом байте размер пакета
   Flag_data=1;
  }
  else  if (data[0] != y)  // если весь пакет не принят
  {
    y++;  // счётчик байт
    uart_transmit(data[y]);  // запись следующего байта data[y]
    return;
  }
  Flag_data=0;


Добавлено after 4 minutes 34 seconds:
СТОП!!! uart_transmit(data[y]) это же передача. Тогда годится. У меня uart_transmit нужно заменить на uart_receive :)) :)) :))

Добавлено after 2 minutes 48 seconds:
Но лучше "0" пакет не закрывать. Лучше так.
Код:
for(y = 0; y <= SizePack; y++){
            uart_transmit(data[y]);
        }

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

Чт авг 11, 2022 15:04:51

Sulik писал(а):У меня uart_transmit нужно заменить на uart_receive

Вот проверь например в протеусе, уверен не заработает как надо если там будет присутствовать например char c = uart_receive();

Добавлено after 15 minutes 39 seconds:
Код:
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(y = 0; data[y] != '\0'; y++){
            uart_transmit(data[y]);
         }
      }
      c = uart_receive();
   }
   
}


Вот короткий пример кода, вот тут задача такая, как только приходить прерывание и переменная flag равно 1, то надо отвязаться от c = uart_receive(); тогда сразу же заработает условие с циклом for.

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

Чт авг 11, 2022 16:10:08

Код:
char c;
uint8_t flag = 0;
uint8_t Size_data = 12; // например передаём 12 байт

ISR(PCINT0_vect){
   if(PINB & (1 << PB0)) flag = 1; // Разрешение передачи данных
}

int main(){
   interrupt_init();
   sei();
   
   while(1){
      if (flag){
         for (y = 0; y < Size_data ; y++){
            uart_transmit(data[y]);
         }
       flag = 0; // Данные переданы
      }
      c = uart_receive();
   }
   
}


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