Страница 1 из 1

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

Добавлено: Чт май 31, 2012 13:14:13
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;
}

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

Добавлено: Чт май 31, 2012 14:04:07
igor-x
как то непонятно - зачем write(c); находится в обработке прерывания приема?
может правильно сделать - сначала все принять, выставить признак что прием строки закончен, а потом всю принятую строку передать?
это если самостоятельно делать. я в свое время поленился - взял за основу образец из CV с приемным буфером- работает .

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

Добавлено: Чт май 31, 2012 14:48:49
servio
Все дело в передаче аргумента в функцию write. Лучше будет сделать так:

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

void write (char *t) 
{
   char С;

   for (;;)
   {
     C = *t;
     if (C==0)
       break;
     else
     {
        while (!(USR&(1<<UDRE)));
        UDR = C;
        t++;
     };
   };
}

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

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

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

Добавлено: Чт май 31, 2012 18:05:25
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;
}

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

Добавлено: Пт июн 01, 2012 05:31:47
iplogger
if ('\n'=c[cnt]) -> if ('\n'==c[cnt])

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

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

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