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

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

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

Сообщение 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;
}
Реклама
Аватара пользователя
igor-x
Мудрый кот
Сообщения: 1817
Зарегистрирован: Пн ноя 29, 2010 15:58:43

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

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

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

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

Сообщение servio »

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

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

void write (char *t) 
{
   char С;

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

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

Сообщение servio »

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

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

Сообщение 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;
}
Реклама
Аватара пользователя
iplogger
Грызет канифоль
Сообщения: 262
Зарегистрирован: Пн дек 15, 2008 19:28:38
Откуда: Омск

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

Сообщение iplogger »

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

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

Сообщение Vitaliyli »

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

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

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