Хотите остановить UART_RxChar (), ожидая данных, полученных UART_RxChar () примерно через 1 секунду, и запускать, пока (1) l oop непрерывно - PullRequest
0 голосов
/ 26 января 2020

UART_RxChar () ожидает все время, пока не будут получены данные. Но я хочу перестать ждать полученных данных и запустить свой while (1) l oop непрерывно. Поэтому я хочу остановить UART_RxChar () примерно через 1 секунду ожидания и запустить, пока (1) l oop непрерывно. Это мой код Как я должен изменить это ... Может кто-нибудь помочь мне с этим.


    #define F_CPU 8000000UL         /* Define frequency here its 8MHz */
    #include <avr/io.h>
    #include <util/delay.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #define USART_BAUDRATE 9600
    #define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)


    void UART_init(void)
    {
        UBRRH = (BAUD_PRESCALE >> 8);   /* Load upper 8-bits*/
        UBRRL = BAUD_PRESCALE;      /* Load lower 8-bits of the baud rate value */
        UCSRB |= (1 << RXEN) | (1 << TXEN);/* Turn on transmission and reception */
        UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1);/* Use 8-bit character sizes */


    }

    unsigned char UART_RxChar(void)
    {
        while ((UCSRA & (1 << RXC)) == 0);/* Wait till data is received */
        return UDR;         /* Return the byte*/
    }

    void UART_TxChar(uint8_t data)
    {
        while (! (UCSRA & (1<<UDRE)));  /* Wait for empty transmit buffer*/
        UDR = data ;
    }

    void UART_SendString(char *str)
    {
        for(int i=0;i<strlen(str);i++){
            UART_TxChar(str[i]);
        }
    }

    int main()
    {
        char RecievedByte;
        UART_init();
        DDRA=0x00;// for input port-LED
        DDRB=0xff;// for output port-Switch
        while(1)
        {
            if((PINA==0x01))// checking the status of PIN  PA0 (whether push button is pressed), if it is '1', turns on the LED
            {
                _delay_ms(100); // for debouncing of switch
                PORTB=0x01;   // Turning on the LED PB0
                _delay_ms(200);
                PORTB=0x00;

            }

            else if( (UART_RxChar()=='s'))// else checking whether 's'  is received, if it is '1', turns on the LED
            {       
                //want to ignore UART_RxChar()=='s' is waiting untill 's' is received after sometime and continiously run while(1) loop

                _delay_ms(100); // for debouncing of switch
                PORTB=0x02;   // Turning on the LED PB1
                _delay_ms(200);
                PORTB=0x00;

            }
        }   
    }

1 Ответ

0 голосов
/ 30 января 2020

У вас есть несколько проблем с дизайном в вашем коде:

delay_ms и подобное блокирует выполнение других частей вашего кода. В то время как такие задержки заманчивы для запуска простой программы в первый раз, сохранение таких проблем проектирования будет настоящей болью, поскольку ваше приложение будет расти и решать более сложные задачи. Примером является блокирующая реализация ключа debounce. Лучше запустить прерывание по таймеру, а затем на основе этой проверки PORTA каждые, скажем, 10 мс. 20 мс (при 50 Гц .. 100 Гц). Этого достаточно для разоблачения. В зависимости от прочитанного значения основная программа решает, будет ли это короткое или длинное нажатие клавиши или же двойной щелчок.

while(wait_for_event) также блокирует ваше приложение. Например,

while ((UCSRA & (1 << RXC)) == 0);/* Wait till data is received */

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

В общем случае структура вашего основного l oop будет

while (1)
{
    if (condition_1)
    {
       reset_condition_1();
       nonblocking_action_for_condition_1();
    }
    if (condition_2)
    {
       reset_condition_2();
       nonblocking_action_for_condition_2();
    }
}

Например, иногда я использую опрос для простого приема UART следующим образом (на вашем устройстве могут быть разные SFR):

int uart_getc_nowait (void)
{
    return (UCSRA & (1 << RXC)) ? 0xff & UDR : -1;
}

Это не блокирует: другие части кода будут выполнять только действия если эта функция возвращает 0 ... 255.

Когда вы передаете данные, вы можете рассмотреть возможность использования FIFO : вы бы записали строку в FIFO, а ISR выбрал бы индивидуальный байты и отправьте их. Псевдокод:

ISR (uart-dataregister-is-empty)
{
    if (fifo-is-empty)
    {
        disable-uart-dataregister-is-empty-interrupt;
    }
    else
    {
        byte = read-one-byte-from-fifo;
        uart-dataregister = byte;
    }
}

void uart_putc (byte)
{
    if (fifo-is-full)
    {  
        do-something-if-fifo-is-full;
    }
    else
    {
        write-byte-to-fifo;
        // Following action is no problem if respective IRQ is already enabled.
        enable-uart-dataregister-is-empty-interrupt;
    }
}
...