AVR на C, траблы с UART

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Родился
Сообщения: 3
Зарегистрирован: Чт май 31, 2012 13:02:57

Сообщение Vitaliyli »

Доброго времени суток. Я новичок в программировании, и в МК. Пытаюсь написать прогу, но не совсем то выходит.
Через терминал (например ГиперТерминал) набираю слово, затем жму 'Enter' и он мне должен вернуть это же слово.
С символом все просто, а вот с массивами никак. Он возвращает, но зараза возвращает слово без первого элемента, например, пишу "Privet", а он мне "rivet". Дело в том, что у него в массиве нулевой элемент почему-то r, а не P. Помогите чем можете. Если не в ту тему, то извиняюсь.

Код:

Код: Выделить всё

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define XTAL 3686400L                               //Задал частоту
#define baudrate 9600L                              //Скорость
#define bauddivider (XTAL/(16*baudrate)-1)

unsigned char c[255];          //Создаю функцию, в которой данные UDR переписываются в массив c[] (буфер)
void read ()
{
   unsigned char i;
   for (i=0;i<255;i++)
   {
      if (UDR =='\n')
         return;
      else
         while (!(USR&(1<<RXC)));
         c[i] = UDR;
   }
}

void write (char *t)      //создаю функцию, в которой из буфера скидываю в UDR на отправку
{
   unsigned char i;
   for (i=0;i<255;i++)
   {
      if (t[i]==0)
         return;
      else
         while (!(USR&(1<<UDRE)));
         UDR = t[i];
   }
}

ISR (UART_RX_vect) 
{
  read ();
  write(c); 
}

int main (void)
{
  UCR = 1<<RXEN|1<<TXEN|1<<RXCIE|0<<TXCIE;
  UBRR = bauddivider;
  sei();
  while (1)
  {   
  }
  return 0;
}
Реклама
Мудрый кот
Аватара пользователя
Сообщения: 1817
Зарегистрирован: Пн ноя 29, 2010 15:58:43

Сообщение igor-x »

как то непонятно - зачем write(c); находится в обработке прерывания приема?
может правильно сделать - сначала все принять, выставить признак что прием строки закончен, а потом всю принятую строку передать?
это если самостоятельно делать. я в свое время поленился - взял за основу образец из CV с приемным буфером- работает .
Реклама
Родился
Аватара пользователя
Сообщения: 19
Зарегистрирован: Пт окт 21, 2011 18:27:34
Откуда: Киев

Сообщение servio »

Все дело в передаче аргумента в функцию write. Лучше будет сделать так:

Код: Выделить всё

void write (char *t) 
{
   char С;

   for (;;)
   {
     C = *t;
     if (C==0)
       break;
     else
     {
        while (!(USR&(1<<UDRE)));
        UDR = C;
        t++;
     };
   };
}
Контактная информация:
Родился
Аватара пользователя
Сообщения: 19
Зарегистрирован: Пт окт 21, 2011 18:27:34
Откуда: Киев

Сообщение servio »

igor-x писал(а):как то непонятно - зачем write(c); находится в обработке прерывания приема?
может правильно сделать - сначала все принять, выставить признак что прием строки закончен, а потом всю принятую строку передать
Это очень хорошая идея. Нужно в обработчике прерывания приема каждый принятый символ складывать в буфер (глобальная переменная - массив) увеличивая при этом индекс последнего принятого символа (другая глобальная переменная, желательно volatile). Как только обработчик прерывания натыкается на символ \n, то проверяется наличие символов на передачу (индекс последнего принятого символа должен быть более 0) и далее выполняется функция write. Единственное что нужно в данном случае добавить в эту функцию это остановку при передаче принятого количества символов и обнуление переменной индекса последнего принятого символа.
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Родился
Сообщения: 3
Зарегистрирован: Чт май 31, 2012 13:02:57

Сообщение Vitaliyli »

Завтра попробую залью этот код.. авось заведется.

Код: Выделить всё

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define XTAL 3686400L                              
#define baudrate 9600L                              
#define bauddivider (XTAL/(16*baudrate)-1)

unsigned char c[255];          
unsigned char cnt = 0;
volatile unsigned char ready = 0;

void write (char *t)      
{
  while ('\0'!=*t)
  {
    while (!(USR&(1<<UDRE)));
    UDR=*t;
    ++t;
  }
}

ISR (UART_RX_vect)
{
  c[cnt]=UDR;
  if ('\n'=c[cnt])
  {
    ready = 1;
    c[cnt+1]='\0';
  }
  cnt++;
}

int main (void)
{
  UCR = 1<<RXEN|1<<TXEN|1<<RXCIE|0<<TXCIE;
  UBRR = bauddivider;
  sei();
  while (1)
  {   
    if(ready)
    {
      cli();
      cnt=0;
      write(c);
      ready=0;
      sei();
    }
  }
  return 0;
}
Реклама
Грызет канифоль
Аватара пользователя
Сообщения: 262
Зарегистрирован: Пн дек 15, 2008 19:28:38
Откуда: Омск

Сообщение iplogger »

if ('\n'=c[cnt]) -> if ('\n'==c[cnt])
Реклама
Родился
Сообщения: 3
Зарегистрирован: Чт май 31, 2012 13:02:57

Сообщение Vitaliyli »

Данный код ведет себя следующим образом:
ввожу в терминале '123' и жму Enter, он мне выдает 123 (все нормально), потом ввожу 'abc' и Enter, он мне пишет '123' Enter 'abc'. и т.д., если вводить дальше, то он сначала пишет то, что было до этого. Я уже ставил cnt=0 и пперед вызовом функции write(c) и после.. все одно и то же(

Хааааа, все заработало. над было действительно записать переменную cnt как volatile=).
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»