Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Тема закрыта

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

Чт май 31, 2012 13:14:13

Доброго времени суток. Я новичок в программировании, и в МК. Пытаюсь написать прогу, но не совсем то выходит.
Через терминал (например ГиперТерминал) набираю слово, затем жму '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

как то непонятно - зачем write(c); находится в обработке прерывания приема?
может правильно сделать - сначала все принять, выставить признак что прием строки закончен, а потом всю принятую строку передать?
это если самостоятельно делать. я в свое время поленился - взял за основу образец из CV с приемным буфером- работает .

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

Чт май 31, 2012 14:48:49

Все дело в передаче аргумента в функцию 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

igor-x писал(а):как то непонятно - зачем write(c); находится в обработке прерывания приема?
может правильно сделать - сначала все принять, выставить признак что прием строки закончен, а потом всю принятую строку передать


Это очень хорошая идея. Нужно в обработчике прерывания приема каждый принятый символ складывать в буфер (глобальная переменная - массив) увеличивая при этом индекс последнего принятого символа (другая глобальная переменная, желательно volatile). Как только обработчик прерывания натыкается на символ \n, то проверяется наличие символов на передачу (индекс последнего принятого символа должен быть более 0) и далее выполняется функция write. Единственное что нужно в данном случае добавить в эту функцию это остановку при передаче принятого количества символов и обнуление переменной индекса последнего принятого символа.

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

Чт май 31, 2012 18:05:25

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

Код:
#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

if ('\n'=c[cnt]) -> if ('\n'==c[cnt])

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

Пт июн 01, 2012 13:30:30

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

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