Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: UART 8535 в режиме аппаратного контроля
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
bungler
Господа разработчики, подскажите пожалуйста:
Необходимо связать два микроконтроллера, один - ATmega8535, другой на базе WAVECOM Q24. Обмен предполагается по RS232 через UART'ы на обоих мк. Однако мк. на базе WAVECOM Q24 может работать через UART только с аппаратным контролем потока, т.е. могут использоваться линии RTS, CTS, DTR, DSR, DCD.
Как реализовать работу UART'а ATmega8535 с аппаратным контролем потока? Линий RTS, CTS, DTR, DSR, DCD у ATmega8535 нет. Эти линии придется реализовывать программно. Возможно есть примеры-прототипы?
С компьютером оба мк. работают нормально - один с аппаратным, другой с программным контролем. Попытка коротить линии RTS, CTS и DTR, DSR, DCD для WAVECOM Q24 не проходит.
SysRq
ATMega128, rx\tx\cts\rts\gnd, WinAVR, прерывания, FIFO:
CODE
#ifndef _USART0_H_
#define _USART0_H_

#include "main.h"

void USART0_Initialize(void);

uint8_t USART0_ReceiveByte(void);

void USART0_TransmitByte(uint8_t data);

uint8_t USART0_IsDataReceived(void);

void USART0_Flush(void);

#endif
CODE
#include "usart0.h"

////////////////////////////////////////////////////////////////////////////////////////////////////////

#define UART_RX_BUFFER_SIZE 128
#define UART_RX_BUFFER_MASK (UART_RX_BUFFER_SIZE - 1)

static uint8_t UART_RxBuf[UART_RX_BUFFER_SIZE];
static volatile uint8_t UART_RxHead;
static volatile uint8_t UART_RxTail;

////////////////////////////////////////////////////////////////////////////////////////////////////////

#define UART_TX_BUFFER_SIZE 128
#define UART_TX_BUFFER_MASK (UART_TX_BUFFER_SIZE - 1)

static uint8_t UART_TxBuf[UART_TX_BUFFER_SIZE];
static volatile uint8_t UART_TxHead;
static volatile uint8_t UART_TxTail;

////////////////////////////////////////////////////////////////////////////////////////////////////////

#define UART_RX_BUFFER_SIZE_4 32 // (16 + 1) bytes min

////////////////////////////////////////////////////////////////////////////////////////////////////////

#define CTSS 2 // This is CTSS# really (not CTSS)
#define RTSS 3 // This is RTSS# really (not RTSS)

////////////////////////////////////////////////////////////////////////////////////////////////////////

static uint8_t USART0_GetRxBufFreeSz(void)
{
return (UART_RxHead >= UART_RxTail? (UART_RX_BUFFER_SIZE - UART_RxHead + UART_RxTail) : (UART_RX_BUFFER_SIZE - UART_RxTail + UART_RxHead));
}

////////////////////////////////////////////////////////////////////////////////////////////////////////

static void RTS_SetHigh(void)
{
// This is RTS#, so we MUST invert signals
PORTE &= ~_BV(RTSS);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////

static void RTS_SetLow(void)
{
// This is RTS#, so we MUST invert signals
PORTE |= _BV(RTSS);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////

static uint8_t CTS_GetState(void)
{
// This is CTS#, so we MUST invert signals
if(PINE & _BV(CTSS)) return FALSE;
else return TRUE;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////

//UART0 initialize
// desired baud rate: 500000
// actual: baud rate:500000 (0,0%)
// char size: 8 bit
// parity: Disabled
void USART0_Initialize(void) // initialization
{
UART_RxTail = 0; // reset buffer counters
UART_RxHead = 0;
UART_TxTail = 0;
UART_TxHead = 0;

UCSR0B = 0x00; //disable while setting baud rate

UCSR0A = 0x00;

UCSR0C = (_BV(UCSZ01) | _BV(UCSZ00));

UBRR0L = 0x01; //set baud rate lo
UBRR0H = 0x00; //set baud rate hi

UCSR0B = (_BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0));

RTS_SetHigh();

DDRE &= ~_BV(CTSS); // Configure CTS pin as input
DDRE |= _BV(RTSS); // Configure RTS pin as output
}

////////////////////////////////////////////////////////////////////////////////////////////////////////

ISR(USART0_RX_vect) // interrupt on RXC0
{
uint8_t data;
uint8_t tmphead;

if(UCSR0A & (_BV(FE0) | _BV(DOR0))) // if any error is detected
{
data = UDR0; // just read UDR0
}
else // no errors, receive data
{
data = UDR0;

tmphead = (UART_RxHead + 1) & UART_RX_BUFFER_MASK;
UART_RxHead = tmphead;

if(USART0_GetRxBufFreeSz() < UART_RX_BUFFER_SIZE_4) // ERROR! Receive buffer could be overflown, pause dataflow
{
RTS_SetLow();
}

UART_RxBuf[tmphead] = data;
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////

ISR(USART0_UDRE_vect) // interrupt on UDRE0
{
if(CTS_GetState())
{
uint8_t tmptail;

if(UART_TxHead != UART_TxTail)
{
tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;
UART_TxTail = tmptail;

UDR0 = UART_TxBuf[tmptail];
}
else
{
UCSR0B &= ~_BV(UDRIE0);
}
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////

uint8_t USART0_ReceiveByte(void)
{
uint8_t data;
uint8_t tmptail;

while (UART_RxHead == UART_RxTail);

tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
UART_RxTail = tmptail;

data = UART_RxBuf[tmptail];

if(UART_RxHead == UART_RxTail) RTS_SetHigh(); // Buffer is empty now, so we can receive data again

return data;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////

void USART0_TransmitByte(uint8_t data)
{
uint8_t tmphead;

tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;

while (tmphead == UART_TxTail);

UART_TxBuf[tmphead] = data;

UART_TxHead = tmphead;

UCSR0B |= _BV(UDRIE0);

}

////////////////////////////////////////////////////////////////////////////////////////////////////////

uint8_t USART0_IsDataReceived(void)
{
if(UART_RxHead == UART_RxTail) return FALSE;
else return TRUE;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////

void USART0_Flush(void)
{
while(USART0_IsDataReceived()) USART0_ReceiveByte();
}
bungler
Здравствуйте уважаемый SysRg! Огромное спасибо за содержательный ответ.
Однако хотелось бы дополнительно узнать:
1. Приведенный пример обкатывался? С какими мк. кроме ATmega128 ?
2. Какая схема задействования линий rx, tx, cts, rts ( с учетом микросхемы преобразования уровней RS232 - TTL)?
Какие пины ATmega128 использовались для задействования rts, cts ?
SysRq
Цитата(bungler @ Jul 22 2009, 13:26) *
Приведенный пример обкатывался? С какими мк. кроме ATmega128 ?
Да, это из рабочего проекта. Железка в работе больше года. С другими МК не было необходимости запускать, но не вижу проблем...

Цитата(bungler @ Jul 22 2009, 13:26) *
Какая схема задействования линий rx, tx, cts, rts ( с учетом микросхемы преобразования уровней RS232 - TTL)?
Обычная: вЫходные сигналы первого устройства на соответствующие входные второго (rx<>tx, cts<>rts, gnd<>gnd).

Цитата(bungler @ Jul 22 2009, 13:26) *
Какие пины ATmega128 использовались для задействования rts, cts ?
Из исходника ж очевидно:
Код
#define CTSS 2 // This is CTSS# really (not CTSS)
#define RTSS 3 // This is RTSS# really (not RTSS)

DDRE &= ~_BV(CTSS); // Configure CTS pin as input
DDRE |= _BV(RTSS); // Configure RTS pin as output
Единственное что необходимо учесть, так это то что у меня эти сигналы приходят инвернсыми (в коде есть комментарий).
defunct
Цитата(bungler @ Jul 19 2009, 01:25) *
Попытка коротить линии RTS, CTS и DTR, DSR, DCD для WAVECOM Q24 не проходит.

Тупо коротить не пойдет, - ничего не даст, т.к. по-умолчанию WAVECOM держит все сигналы в неактивном состоянии "1".
Вам необходимо подать на __вход__ "RTS" и __вход__ "DTR" WAVECOM'а активный уровень "0", и этого уже достаточно для работы.

Можно также мониторить __выход__ WAVECOM'а - CTS. Если сигнал на этой линии неактивный "1" - слать данные нельзя, если активный "0" - можно.
Еще можно просигналить WAVECOM'у чтобы тот прекратил слать Вам данные, установив RTS в неактивное состояние (это если Ваш МК не будет успевать обрабатывать входные данные).

Вот собсно и все.

PS:
"1" - соответствует TTL уровню +5V, RS232 уровню -12V.
"0" - соответствует TTL уровню 0V, RS232 уровню +12V.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.