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

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

Чт авг 11, 2022 16:15:46

AlexandrRa писал(а):так правильней.

Да хоть так, главная тут задача, отвязаться от c = uart_receive(); на время выполнения условия с циклом for, вот никак не смог отвязать разве что часто нажатием какой нибудь клавиши
Последний раз редактировалось Sulik Чт авг 11, 2022 21:14:51, всего редактировалось 3 раз(а).

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

Чт авг 11, 2022 16:23:22

Код:
void uart_handler_RX(void)
{
if (y < Size_data)  // если весь пакет не принят
  {
    data[y] = UDR0;  // запись следующего байта data[y]
    y++;  // счётчик байт
    return;
  }
  y=0;
}

И добавь прерывание по приёму

Добавлено after 2 minutes 18 seconds:
Код:
uint8_t flag = 0;
uint8_t Size_data = 12; // например передаём 12 байт

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

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


и с на фиг ненужно стало

Добавлено after 3 minutes 10 seconds:
Что за МК хоть?
Последний раз редактировалось AlexandrRa Чт авг 11, 2022 16:26:00, всего редактировалось 1 раз.

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

Чт авг 11, 2022 16:29:34

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

Иногда очень необходимо бывает закрыться именно "\0", есть такие моменты в коде где именно так необходимо учитывая, что количество символов в одном массиве данных могут быть разной длины, то увеличится эта длина то уменьшится.

Добавлено after 2 minutes 34 seconds:
AlexandrRa писал(а):Что за МК хоть?
Atmega 328P

Добавлено after 2 minutes 59 seconds:
AlexandrRa писал(а):И добавь прерывание по приёму

Это у меня добавлено, просто код я привел как пример
Последний раз редактировалось Sulik Чт авг 11, 2022 21:07:56, всего редактировалось 1 раз.

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

Чт авг 11, 2022 16:31:09

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

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

Чт авг 11, 2022 16:42:22

AlexandrRa писал(а):и с на фиг ненужно стало

Он нужен в другом коде, просто приведенном мною примере он не нужен, но он нужен это для приема неких команд и отправка этих команд в нужное условие с данными

Добавлено after 6 minutes 32 seconds:
Задача тут очень понятная, например консоль putty будет постоянно открыть по UART с МК, ждет ввода команд с клавы, но в то же время как только придет нужное прерывание отвязаться от uart_receive(); и начал обрабатывать другое условие с циклом с выводом данных на консоль и после обработки вернулась в тот же режим uart_receive();
Последний раз редактировалось Sulik Чт авг 11, 2022 21:07:09, всего редактировалось 1 раз.

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

Чт авг 11, 2022 18:52:34

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

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

Пт авг 12, 2022 07:46:36

Задача тут очень понятная, например консоль putty будет постоянно открыть по UART с МК, ждет ввода команд с клавы, но в то же время как только придет нужное прерывание отвязаться от uart_receive(); и начал обрабатывать другое условие с циклом с выводом данных на консоль и после обработки вернулась в тот же режим uart_receive();

Нафига сидеть и ждать приёма? За этим прекрасно сможет следить флаг прерывания. А нужное прерывание смотри по флагу или данным в основном цикле. В этом случае ты всегда будешь отвязан от uart_receive(). И я бы лучше уходил в сон во время ожидания приёма, вместо того чтобы жрать энергию.

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

Пт авг 12, 2022 14:25:10

Sulik писал(а):Задача тут очень понятная,
Вам командная консоль нужна или как?
А команды какого вида, по символьные или пакетные, заканчивающие определенным символом или еще как?

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

Пт авг 12, 2022 14:54:10

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

Расскажите это тем кто написал и тем кто применяет software serial.

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

Приведенный код будет работать, но если есть аппаратная поддержка, то не применять аппаратные прерывания нет смысла.

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

Пт авг 12, 2022 16:17:40

Sulik писал(а):Задача тут очень понятная,
Вам командная консоль нужна или как?
А команды какого вида, по символьные или пакетные, заканчивающие определенным символом или еще как?

Да именно консоль, а команды могут быть и те и другие, по ситуации.

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

Пт авг 12, 2022 18:09:14

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

код написан под компилятор CVAVR, то есть под компилятор winavr (interrupt [USART_RXC] void usart_rx_isr(void)) надо поменять на ISR(USART_RX_vect) и #asm("sei") на sei();

по умолчанию строка вида '0' - turn off LED располагается в RAM ее надо перенести во FLASH
Код:
#include <mega328p.h>

// Standard Input/Output functions
#include <stdio.h>

// Declare your global variables here

#define DATA_REGISTER_EMPTY (1<<UDRE0)
#define RX_COMPLETE (1<<RXC0)
#define FRAMING_ERROR (1<<FE0)
#define PARITY_ERROR (1<<UPE0)
#define DATA_OVERRUN (1<<DOR0)

// USART Receiver buffer
#define MAX_DMA_BUFFERS_COUNT 32     // 4 8 16 32 64 128
#define BUFFER_MASK (MAX_DMA_BUFFERS_COUNT-1)
volatile unsigned char BUFF_RX_BUF[MAX_DMA_BUFFERS_COUNT]={0};
volatile unsigned char DMA_WR_BUF = 0;
volatile unsigned char DMA_RD_BUF = 0;

// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSR0A;
data=UDR0;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
   { 
      BUFF_RX_BUF[DMA_WR_BUF] = data;
      DMA_WR_BUF++;
     DMA_WR_BUF &= BUFFER_MASK;   
   }
}


#include <string.h>

char b_start=0, b_end=0, len_buff=0, len=0;
bit flag=0;
char buff[24]; // максимальная длинна команды
unsigned long main_p=0;

unsigned long my_atoi(char *str)
{
   unsigned long result = 0;

   if ('0'>*str || *str>'9')
   {
      str++;
   }
   while (*str != '\0')
   {
      if ('0'> *str || *str>'9')
         break;
      else
         result = result * 10 + (*str++ - '0');
   }
   return result;
}

static char respcmp(char *s, const char  *resp){
   while(*resp)
      if(*resp++ != *s++) return 0;
   return 1;
}

void usart_send_str(const char* str)
{
    while(*str) {
    while (!(UCSR0A & (1<<UDRE0))) {}
       UDR0 = *str++;
    }
}

#define SEND(str) usart_send_str(str)

void help(void)      // HELP
{
   SEND("\r\n");
   SEND("\t'0' - turn off LED\r\n");
   SEND("\t'1' - turn on LED\r\n");
   SEND("\t'LED ON' - turn on LED\r\n");
   SEND("\t'LRD OFF' - turn off LED\r\n");
   SEND("\t'TOGGLE' - turn toggle LED\r\n");
   SEND("\t'COUNT=N' - set all value by N (decimal):\r\n");
   SEND("\tSTAT - shows which mode the automatic/off mode is in\r\n");

   SEND("\tHELP - help\r\n");
   SEND("\r\n");
}

// print 32bit unsigned int
void printu(unsigned long val){
    char bufa[11];
    char bufb[10];
    int i;
    int l = 0, bpos = 0;
    if(!val){
        bufa[0] = '0';
        l = 1;
    }else{
        while(val){
            bufb[l++] = val % 10 + '0';
            val /= 10;
        }
        bpos += l;
        for(i = 0; i < l; ++i){
            bufa[--bpos] = bufb[i];
        }
    }
    bufa[l + bpos] = 0;
    SEND(bufa);
}

void main(void)

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART0 Mode: Asynchronous
// USART Baud Rate: 9600
UCSR0A=(0<<RXC0) | (0<<TXC0) | (0<<UDRE0) | (0<<FE0) | (0<<DOR0) | (0<<UPE0) | (0<<U2X0) | (0<<MPCM0);
UCSR0B=(1<<RXCIE0) | (0<<TXCIE0) | (0<<UDRIE0) | (1<<RXEN0) | (1<<TXEN0) | (0<<UCSZ02) | (0<<RXB80) | (0<<TXB80);
UCSR0C=(0<<UMSEL01) | (0<<UMSEL00) | (0<<UPM01) | (0<<UPM00) | (0<<USBS0) | (1<<UCSZ01) | (1<<UCSZ00) | (0<<UCPOL0);
UBRR0H=0x00;
UBRR0L=0x67;

// Global enable interrupts
#asm("sei")

while (1)
      {
      // Place your code here

        while (DMA_RD_BUF != (DMA_WR_BUF)) {
       
            b_start =  DMA_RD_BUF;  // Копируем позиции начала           
            DMA_RD_BUF++;
         DMA_RD_BUF &= BUFFER_MASK;
            b_end = DMA_RD_BUF;    // и конца буфера 
           
            // сборка команды
           len_buff = strlen((void*)buff); // определяем длину
           
            if(b_start < b_end) {
           len = b_end-b_start;
           memcpy(&buff[len_buff],(void*)&BUFF_RX_BUF[b_start],len);
           buff[len_buff+len]=0;
           }

           if(b_start > b_end) {
           len = MAX_DMA_BUFFERS_COUNT-b_start;
           memcpy(&buff[len_buff],(void*)&BUFF_RX_BUF[b_start],len);
           memcpy(&buff[len],BUFF_RX_BUF,b_end);
           buff[len_buff+len+b_end]=0;
           }

           // если BkSp - сдвигаем назад
           len_buff = strlen((void*)buff)-1; // определяем длину
           if((buff[len_buff] == 0x08)|| (buff[len_buff] == 0x7f)){
           // стираем символ
           // но не левее начала буфера
           if(len_buff > 0) buff[len_buff-1]=0; else buff[len_buff]=0;
           }

           // если Enter - ввод закончен
           if(((buff[len_buff] == '\n') || (buff[len_buff] == '\r'))) {
           flag=1; buff[len_buff]='\0'; // стираем символ Enter, заменяем концом строки \0
           }
        }
       
        // поиск обработчика
       if(flag) {
       
        len_buff = strlen((void*)buff); // определяем длину команды
        // если не использовать по символьные команды, то len_buff не нужен

       if(respcmp((void*)buff, "1") && len_buff == strlen("1")) { // это просто пример
            PORTB |= (1<<(0));
       }       

        if(respcmp((void*)buff, "0")&& len_buff == strlen("0")) {
            PORTB &= ~(1<<(0));
       }         
               
       if(respcmp((void*)buff, "LED ON") && len_buff == strlen("LED ON")) {
            PORTB |= (1<<(0));
       }
      
        if(respcmp((void*)buff, "LED OFF") && len_buff == strlen("LED OFF")) {
            PORTB &= ~(1<<(0));
       }
      
        if(respcmp((void*)buff, "TOGGLE") && len_buff == strlen("TOGGLE")) {
            PORTB ^= (1<<(0));
       }
                   
       if(respcmp((void*)buff, "COUNT=")) {
            main_p = my_atoi((buff + sizeof("COUNT=")-1));
       }
       
        if(respcmp((void*)buff, "PRINT") && len_buff == strlen("PRINT")) {
           SEND("\r\nPRINT= "); printu(main_p);SEND("\r\n");
       }
       
       if(respcmp((void*)buff, "HELP") && len_buff == strlen("HELP")) {
            help();
       }       
       
        buff[0]=0;
       flag=0;             
      }
  }

}
на CVAVR этот код занимает 405 байт RAM и 2156 байт FLASH
Ответить