Как отправить строку в последовательной связи в AVR-C

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

//tx serial
#include <avr/io.h> 

#define F_CPU 16000000 
#define BUAD 9600 
#define BUAD_RATE_CALC ((F_CPU/16/BUAD) - 1)  


int main(void){  

    char ar[]= "hello";

    //High and low bits
    UBRR0H = (BUAD_RATE_CALC >> 8); 
    UBRR0L = BUAD_RATE_CALC; 
    //////////////// 
    //transimit and recieve enable
    UCSR0B = (1 << TXEN0)| (1 << TXCIE0) | (1 << RXEN0) | (1 << RXCIE0); 
    UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);  //8 bit data format
    ////////////////////////////////////////////////////////////////
    int i = 0;

    while (1){  

    while (( UCSR0A & (1<<UDRE0))  == 0){};
        for (i = 0; i < strlen(ar); i++){ 
            UDR0 = ar[i]; 
        }
    }
}

В чем проблема?

Ответы (3)

Не совсем уверен, просто предположил. Возможно, вам следует поместить while(UDRE0 == 0){}промежуточные символы отправки. Я считаю, что нужно подождать, пока не будет отправлен один символ.

for (i = 0; i < strlen(ar); i++){ 
   while (( UCSR0A & (1<<UDRE0))  == 0){};
   UDR0 = ar[i]; 
}
Ты прав. Каждый раз, когда вы обновляете регистр «UDR0», MCU начинает новую передачу. И программист должен гарантировать, что регистр не будет обновляться до тех пор, пока регистр «UDR0» не станет пустым (символ отправлен), в противном случае произойдет «ошибка конфликта данных», и MCU не отправит ни один из них.
Хорошо, вы имеете в виду, что в моем цикле for я должен включить еще один цикл ожидания, чтобы дождаться регистра перед увеличением, это имеет смысл, спасибо, я проверю, работает ли это как можно скорее
Итак, я попробовал ваш код, и он работает! Однако, когда я это сделал, как и ожидалось, он продолжал печатать приветствие непрерывно, однако я заставил его возвращать ноль, чтобы он печатал приветствие, как только вот код
Вы должны увидеть мой другой «ответ», который решит проблему с непрерывной печатью «привет». Это также дает вам несколько лучших обработчиков/функций для отправки символов и настройки uart.
Я хотел бы отметить, что это while((блокирует и может тратить довольно много «процессорного времени», обычно больше на более низких скоростях. Использование прерываний передачи позволит вам выполнять запись «в фоновом режиме».

Итак, я попробовал ваш код, и он работает! Однако, когда я это сделал, как и ожидалось, он продолжал печатать приветствие непрерывно, однако я заставил его возвращать ноль, чтобы он печатал приветствие, как только вот код:

            //data_buffer 

            //tx serial

            #include <avr/io.h> 

            #define F_CPU 16000000 
            #define BUAD 9600 
            #define BUAD_RATE_CALC ((F_CPU/16/BUAD) - 1)  
            #define buffer_size 128
            #define boolen 0
            int main(void){  
                char br;
                char ar[]= "hello";
                char buffer[10]; 
                //High and low bits
                UBRR0H = (BUAD_RATE_CALC >> 8); 
                UBRR0L = BUAD_RATE_CALC; 
                //////////////// 
                //transimit and recieve enable
                UCSR0B = (1 << TXEN0)| (1 << TXCIE0) | (1 << RXEN0) | (1 << RXCIE0); 
                UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);  //8 bit data format
                ////////////////////////////////////////////////////////////////
                int i = 0;

                while (1){  
                /*while( (UCSR0A & (1<<RXC0))  == 0 ){}; 
                    br = UDR0;
                */

                while (( UCSR0A & (1<<UDRE0))  == 0){};

                        for (i = 0; i < strlen(ar); i++){ 
                            while (( UCSR0A & (1<<UDRE0))  == 0){};
                            UDR0 = ar[i]; 
                            if (i == (strlen(ar) - 1)){ 
                                return 0;
                            }
                        } 
                }

            }   

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

Кстати, еще один вопрос, как мне остановить непрерывную передачу чипа без использования возврата 0; в моем коде? Потому что я хочу попытаться отправить несколько строк за раз или поместить логику массива в функцию, которую затем я могу запустить после того, как пользователь что-то сделает, например, если пользователь что-то вводит, когда когда-либо он что-то вводит, чип будет передавать массив привет, есть идеи? Должен ли я использовать прерывания tx?
Вот еще одна вещь, которую я хочу сделать. Я хочу иметь возможность предотвратить передачу приветствия чипом без возврата 0; код. Я думаю об использовании прерывания TXCIEn. Но я немного смущен тем, что это прерывание срабатывает, срабатывает ли оно, когда регистр пуст или когда он заполнен?
Я не уверен, но (на ардуино, я думаю), если вы выходите из основного, он начинает работать в случайном порядке.
К вашему сведению. С моей установкой WinAVR (инструментарий GNU C) мне пришлось добавить #include <string.h> из-за предупреждения, возникающего при сборке, в котором говорилось: предупреждение: неявное объявление функции 'strlen' предупреждение: несовместимое неявное объявление встроенного функция 'strlen'

Вы должны сделать новый вопрос для каждого другого вопроса, который у вас есть... Но ладно. Код ниже (может быть немного в стиле arduino, но это может помочь спрашивающему).

Код Setupзапускается только один раз, в начале вашей программы. Отлично подходит для инициализации любых периферийных устройств и / или отправки приветственного сообщения / процедуры запуска. Код Loopработает непрерывно, обычно он содержит программу, например, мигающие светодиоды... или систему безопасности атомной электростанции. Тем не менее, он не предназначен для возврата, он предназначен для вечной работы. Хотя мой код поймает вас через некоторое время (навсегда); если бы вы вернулись из него.

Я не тестировал код, но думаю, что это будет так:

#include <avr/io.h> 
#define F_CPU 16000000 
#define BUAD 9600 
#define BUAD_RATE_CALC ((F_CPU/16/BUAD) - 1)  

//Function definitions
void Setup(void);
void Loop(void);
void serialSetup(void);
void serialSend(char* sendString);

//Global variables.
char ar[]= "hello";

void Setup(){
//Code to be run once (At start).
    serialSetup();
    serialSend(ar);
}

void Loop(){
    //Code to be run continiously.
}

void serialSetup(){
    //Register settings
    //High and low bits
    UBRR0H = (BUAD_RATE_CALC >> 8); 
    UBRR0L = BUAD_RATE_CALC; 
    //transimit and recieve enable
    UCSR0B = (1 << TXEN0)| (1 << TXCIE0) | (1 << RXEN0) | (1 << RXCIE0); 
    UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);  //8 bit data format
}

void serialSend(char* sendString){
     for (int i = 0; i < strlen(sendString); i++){ 
         while (( UCSR0A & (1<<UDRE0))  == 0){};
         UDR0 = sendString[i]; 
     } 
}

int main(void){  
    Setup();
    while(1){
       Loop();
    }
while(1){}//If you ever return from Loop(); This while will catch you, so it won't continue doing randomness.           
}