реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Проблемы с UART
Chupa
сообщение Sep 13 2012, 16:22
Сообщение #1





Группа: Новичок
Сообщений: 2
Регистрация: 9-01-10
Пользователь №: 54 692



Доброго времени суток.

Битый день промучался с UART, пытаясь заставить его нормально работать. Методом тыка выяснил, что работает при скорости 14400 бод (пробовал также 9600 и 19200). Но имеется несколько проблем, которые так побороть и не удалось:
1) Отправляемые с ПК символы принимаются не все (с потерями).
2) Отправляемые с МК символы приходят на ПК в виде "ааа" (любые).
3) В каком виде приходят на МК символы неизвестно, но похоже тоже не те, что нужно.

В чем может быть причина? Код:

CODE
#define F_CPU 8000000L
#define LED1 0
#define LED2 1
#define LED_PORT PORTB
#define LED_DDR DDRB

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

ISR(USART_RX_vect)
{
switch(UDR)
{
case '1': LED_PORT |= 1<<LED2; break;
case '0': LED_PORT &= ~(1<<LED2); break;
default: break;
}
}

int main(void)
{
#define baudrate 14400L
#define bauddivider (F_CPU/(16*baudrate)-1)
#define HI(x) ((x)>>8)
#define LO(x) ((x) & 0xFF)

UBRRL = HI(bauddivider);
UBRRH = LO(bauddivider);
UCSRA = 0;
UCSRB = 1<<RXEN|1<<TXEN|1<<RXCIE|0<<TXCIE;
UCSRC = 0<<UMSEL|1<<UCSZ0|1<<UCSZ1;

LED_DDR = 1<<LED1|1<<LED2;
LED_PORT = 0xFF;

sei();

while(1)
{
LED_PORT ^= 1<<LED1;
_delay_ms(1000);
}

return 0;
}


P.S. В качестве USB-UART использую программатор USBASP с прошивкой AVR-Doper, в качестве терминала - avrdebug.

Сообщение отредактировал IgorKossak - Sep 13 2012, 20:27
Причина редактирования: [codebox] для длинного кода!!!
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Sep 13 2012, 16:26
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Chupa @ Sep 13 2012, 19:22) *
Код
    #define HI(x) ((x)>>8)
    #define LO(x) ((x) & 0xFF)

    UBRRL = HI(bauddivider);
    UBRRH = LO(bauddivider);


P.S. В качестве USB-UART использую программатор USBASP с прошивкой AVR-Doper, в качестве терминала - avrdebug.

Может так:
Код
    UBRRL = LO(bauddivider);
    UBRRH = HI(bauddivider);

?
Go to the top of the page
 
+Quote Post
Chupa
сообщение Sep 13 2012, 16:38
Сообщение #3





Группа: Новичок
Сообщений: 2
Регистрация: 9-01-10
Пользователь №: 54 692



biggrin.gif В лучших традициях. Главное, видел, что в UBRR какая-то ерунда выставляется, но не догадался, что мог так перепутать. Все проблемы отпадают, работает на 19200 бод. Спасибо!
Go to the top of the page
 
+Quote Post
adel
сообщение Nov 18 2012, 08:53
Сообщение #4





Группа: Новичок
Сообщений: 1
Регистрация: 15-11-12
Пользователь №: 74 403



День добрый, уважаемые форумчане,
Не хотел создавать отдельного топика, поэтому решил, что уместно написать сюда.
Начал изучать С++ (прочел книжку Лафоре и делал упражения в MS VC++ 6) и попытался применить его в AVR, начав с USART. В основном вся идея была взята с http://waterproofman.wordpress.com/2007/03...uart-c-example/ , изменений почти нет: т к аппаратный usart в ATmega8 в единственном экземпляре, переделал реализацию в синглтон, сделал этому классу абстрактоного предка, изменил пару методов. Отлаживал в Proteus, где было выявлено, что передача нескольких байт идет успешно а вот с приемом беда, и не могу понять почему (подозреваю что в реальном железе будет аналогично).

uart.h:
CODE

#if !defined _C_UART_H_
#define _C_UART_H_

#include <ioavr.h>
#include <intrinsics.h>
#include "C_IO.h"
#include "_string.h"

#define XTAL 8000000L
#define baudrate 9600L
#define bauddivider (XTAL/(16*baudrate)-1)

// синглтон класс UART.
class C_UART : public C_IO
{
private:
// Буфер данных для передачи.
char* pTxBuffer;
// Буфер принятых данных.
char* pRxBuffer;
// Счетчик и объем передаваемых данных.
// Когда они равны передатчик готов передавать следующие данные.
volatile unsigned int uiTxCounter;
volatile unsigned int uiTxSize;
// Счетчик и объем принимаемых данных.
// Когда равны приемник получил необходимый объем данных.
volatile unsigned int uiRxCounter;
volatile unsigned int uiRxSize;
// Конструктор и инициализация USART.
C_UART();
// чтобы нельзя было передавать как параметр функции.
C_UART(const C_UART&);
// для запрета присваивания одного объекта другому
C_UART& operator = (const C_UART&);
// Обработчики прерываний.
#pragma vector = USART_TXC_vect
__interrupt static void TxHandler(void);
#pragma vector = USART_RXC_vect
__interrupt static void RxHandler(void);

public:
// функция, с помощью которой осуществляется ВЕСЬ доступ
// к методам и данным класса.
// Пример синтаксиса вызова: C_UART::instance()->some_function();
static C_UART* Instance();
// Передача заданного и незаданного кол. байт.
bool Send(char* pBuffer, unsigned int uiSize);
bool Send(char* pBuffer);
// Прием заданного количества байт.
bool Receive(char* pBuffer, unsigned int uiSize);
};
#endif


uart.cpp:
CODE

#include "uart.h"

/***********************************МЕТОДЫ*************************************/
// Конструктор с инициализацией USART
C_UART::C_UART()
{
UBRRL = bauddivider & 0x00FF;
UBRRH = (bauddivider>>8)&0x00FF;
UCSRC = (1<<UCSZ1) | (1<<UCSZ0);
uiTxCounter = 0;
uiTxSize = 0;
uiRxCounter = 0;
uiRxSize = 0;
}

// благодаря static объект создается единственный
// раз при первом обращении к instance()
C_UART* C_UART::Instance()
{
static C_UART SingleUART;
return &SingleUART;
}

// Копирование в буфер данных с заданным числом байт, разрешение прерываний
// на передачу, копирование 0-го байта в UDR
bool C_UART::Send(char *pBuffer, unsigned int uiSize)
{
if(!uiSize || !pBuffer || uiTxSize) return false;
uiTxSize = uiSize;
pTxBuffer = pBuffer;
uiTxCounter = 1;
UCSRB |= (1<<TXEN) | (1<<TXCIE);
UDR = pTxBuffer[0];
while(uiTxSize); // ожидание готовности передачи всех данных
return true;
}

// Копирование в буфер данных, разрешение прерываний
// на передачу, копирование 0-го байта в UDR
bool C_UART::Send(char *pBuffer)
{
unsigned int uiSize = strlength(pBuffer);
return (Send(pBuffer,uiSize));
}

// Установка кол. принимаемых байт, адреса приемного буфера, разрешение
// прерываний на прием
bool C_UART::Receive(char *pBuffer, unsigned int uiSize)
{
if(!uiSize || !pBuffer || uiRxSize) return false;
uiRxSize = uiSize;
pBuffer = pRxBuffer;
*pRxBuffer = 0;
uiRxCounter = 0;
UCSRB |= (1<<RXEN) | (1<<RXCIE);
while(uiRxSize); // ожидание готовности приема заданного кол. байт
return true;
}

/******************************ОБРАБОТЧИКИ ПРЕРЫВАНИЙ**************************/
// Копирование в приемный буфер через статический указатель экземпляра принятых
// данных, при достижении требуемого кол. байт запрещение прерываний на прием и
// обнуление размера буфера
#pragma vector = USART_RXC_vect
__interrupt void C_UART::RxHandler(void)
{
C_UART::Instance()->pRxBuffer[C_UART::Instance()->uiRxCounter++] = UDR;
if(C_UART::Instance()->uiRxCounter == C_UART::Instance()->uiRxSize)
{
C_UART::Instance()->uiRxSize = 0;
UCSRB &= ~((1<<RXEN) | (1<<RXCIE));
}
}

// Копирование след. байт находящихся в буферепосле отправки 1-го, при
// достижении требуемого кол. передаваемых байт запрещение прерываний на
// передачу и обнуление размера буфера
#pragma vector = USART_TXC_vect
__interrupt void C_UART::TxHandler(void)
{
if(C_UART::Instance()->uiTxCounter == C_UART::Instance()->uiTxSize)
{
C_UART::Instance()->uiTxSize = 0;
UCSRB &= ~((1<<TXEN) | (1<<TXCIE));
}
else UDR = C_UART::Instance()->pTxBuffer[C_UART::Instance()->uiTxCounter++];
}



Буду очень рад, если подскажите в чем здесь может быть проблема, и как можно улучшить реализацию USART под AVR (возможно, уже есть типовая реализация класса, но я к сожалению нигде не нашел таковую, и было бы здорово если бы кто то ею поделился).
Попробую приложить сюда архив с проектом в EWAVR и Proteus.
Прикрепленный файл  USART_singleton.rar ( 91.29 килобайт ) Кол-во скачиваний: 99
Go to the top of the page
 
+Quote Post
badik
сообщение Dec 11 2012, 05:16
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 48
Регистрация: 29-11-06
Из: Екатеринбург
Пользователь №: 22 890



Была у меня подобная проблема с PIC - это железо. На PC посылаю всё без проблем. Обратно - С PC на PIC каша. Это контроллер не успевает. В проге на PC после посылки каждого байта вставил задержку и всё пошло. Возможно так.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 08:35
Рейтинг@Mail.ru


Страница сгенерированна за 0.01375 секунд с 7
ELECTRONIX ©2004-2016