Цитата(toweroff @ Apr 20 2012, 12:11)

Добрый день!
Что-то не соображу как сделать. Есть протокол MDB, он использует 9 бит данных. Этот 9й бит не контроль четности, он используется как выбор режима.
В LPC2103 нет как таковых 9 бит в UART,зато есть возможность включения Parity Enable с двумя режимами - Forced "1" stick parity и Forced "0" stick parity.
Я так понимаю, эти 0 или 1 будут всегда в этом режиме вставляться в 9й бит
Хорошо, передавать данные смогу. Но как принимать? Ведь с таким контролем я могу не принять данные...
Или я что-то упустил и долблюсь не в ту дверь?
Используется режим форсированной чётности при передаче. При приёме включаете контроль чётности и по ошибке чётности определяете что там в этом 9м бите.
Единственный недостаток что fifo для данных уарта не 8 а 16 бит. Но там не так много данных. И вообще это у меня так сделано. Может Вы сможете модернизировать код.
CODE
/*****************************************************************************
* uart.h: Header file for NXP LPC23xx Family Microprocessors
*
* Copyright© 2006, NXP Semiconductor
* All rights reserved.
*
* History
* 2006.09.01 ver 1.00 Prelimnary version, first Release
*
******************************************************************************/
#ifndef __UART2_H
#define __UART2_H
#define IER_RBR 0x01
#define IER_THRE 0x02
#define IER_RLS 0x04
#define IIR_PEND 0x01
#define IIR_RLS 0x03
#define IIR_RDA 0x02
#define IIR_CTI 0x06
#define IIR_THRE 0x01
#define LSR_RDR 0x01
#define LSR_OE 0x02
#define LSR_PE 0x04
#define LSR_FE 0x08
#define LSR_BI 0x10
#define LSR_THRE 0x20
#define LSR_TEMT 0x40
#define LSR_RXFE 0x80
//-------------------------------------------
//включение модуля uart2
#define PCUART2 (1ul<<24)
//-------------------------------------------
//-------------------------------------------
//альтернативные ф-ии пинов
#define TXD2_line_on (1ul<<20)
#define RXD2_line_on (1ul<<22)
#define TXD2_line_off (~(1ul<<20))
#define RXD2_line_off (~(1ul<<22))
//-------------------------------------------
//-------------------------------------------
//делитель тактовой частоты
#define PCLK_UART2_div4 (0ul<<16)
#define PCLK_UART2_div1 (1ul<<16)
#define PCLK_UART2_div2 (2ul<<16)
#define PCLK_UART2_div8 (3ul<<16)
#define PCLK_UART2_div PCLK_UART2_div2
#define Fcclk_UART2_div 2ul
//-------------------------------------------
//-------------------------------------------
//параметры uart
#define CHL_5 (0ul<<0) //длина символа
#define CHL_6 (1ul<<0)
#define CHL_7 (2ul<<0)
#define CHL_8 (3ul<<0)
#define STOP_1 (0ul<<2) //кол-во стоповых бит
#define STOP_2 (1ul<<2)
#define PAR_OFF (0ul<<3) //контрорль чётности
#define PAR_ON (1ul<<3)
#define PAR_ODD (0ul<<4) //тип проверки чётности - нечётная
#define PAR_EVEN (1ul<<4) //тип проверки чётности - чётная
#define PAR_1 (2ul<<4) //тип проверки чётности - форсированая 1
#define PAR_0 (3ul<<4) //тип проверки чётности - форсированый 0
#define DLC_ENA (1ul<<7) //разрешение доступа к Divisor Latch
//-------------------------------------------
//-------------------------------------------
//контроль fifo
#define FIFO_ENA (1ul<<0) //разрешение fifo
#define RES_RX_FIFO (1ul<<1) //сброс RX fifo
#define RES_TX_FIFO (1ul<<2) //сброс TX fifo
#define FIFO_LEV_0 (0ul<<6) //уровень RX fifo 1 байт
#define FIFO_LEV_1 (1ul<<6) //уровень RX fifo 2 байта
#define FIFO_LEV_2 (2ul<<6) //уровень RX fifo 8 байт
#define FIFO_LEV_3 (3ul<<6) //уровень RX fifo 14 байт
//-------------------------------------------
//-------------------------------------------
#define US2_RXBUFSIZE 256
#define US2_TXBUFSIZE 256
//Глобальные переменные
volatile unsigned int Rx2Buf[US2_RXBUFSIZE];// the receiver buffer.
unsigned int Rx2Head = 0;// the circular buffer index
unsigned int Rx2Tail = 0;
volatile unsigned int Tx2Buf[US2_TXBUFSIZE];// the transmit buffer.
unsigned int Tx2Head = 0;// the circular buffer index
unsigned int Tx2Tail = 0;
//-------------------------------------------
#define MDB_MODE_MSK (1ul<<16) //маска типа данных - команда/данные
void _putcharMDB(unsigned int data);
void UART2_PAR_EVEN(void);
void UART2_PAR_1(void);
void UART2_PAR_0(void);
#endif /* end __UART_H */
CODE
/*****************************************************************************
* uart.c: UART API file for NXP LPC23xx/24xx Family Microprocessors
*
* Copyright© 2006, NXP Semiconductor
* All rights reserved.
*
* History
* 2006.07.12 ver 1.00 Prelimnary version, first Release
*
******************************************************************************/
/*****************************************************************************
** Function name: UART0Handler
**
** Descriptions: UART0 interrupt handler
**
** parameters: None
** Returned value: None
**
*****************************************************************************/
__irq __arm void UART2_Handler (void)
{
unsigned char IIRValue, LSRValue;
volatile unsigned int Dummy;
IIRValue = U2IIR;
IIRValue >>= 1; /* skip pending bit in IIR */
IIRValue &= 0x07; /* check bit 1~3, interrupt identification */
if ( IIRValue == IIR_RLS ) /* Receive Line Status */
{
LSRValue = U2LSR;
/* Receive Line Status */
if( ( LSRValue & LSR_PE ) /*&& ( LSRValue & LSR_RXFE) */)
{
//ошибка четности, ложим байт в фифо
Dummy = U2RBR & 0xff;
Rx2Buf[Rx2Head++] = Dummy|MDB_MODE_MSK;
if (Rx2Head >= US2_RXBUFSIZE) Rx2Head = 0;
VICADDRESS = 0; /* Acknowledge Interrupt */
return;
}
if( LSRValue & (LSR_RXFE&LSR_OE|LSR_FE|LSR_BI) )
{
/* There are errors or break interrupt */
/* Read LSR will clear the interrupt */
Dummy = U2RBR; /* Dummy read on RX to clear interrupt, then bail out */
VICADDRESS = 0; /* Acknowledge Interrupt */
return;
}
if ( LSRValue & LSR_RDR ) /* Receive Data Ready */
{
/* If no error on RLS, normal ready, save into the data buffer. */
/* Note: read RBR will clear the interrupt */
//приём завершён, ложим байт в фифо
Rx2Buf[Rx2Head++] = U2RBR;
if (Rx2Head >= US2_RXBUFSIZE) Rx2Head = 0;
}
}
else if ( IIRValue == IIR_RDA ) /* Receive Data Available */
{
/* Receive Data Available */
LSRValue = U2LSR;
volatile unsigned int DUMMY=0;
DUMMY = U2RBR;
if( LSRValue & LSR_PE )
{
DUMMY |= MDB_MODE_MSK;
}
//приём завершён, ложим байт в фифо
Rx2Buf[Rx2Head++] = DUMMY;
if (Rx2Head >= US2_RXBUFSIZE) Rx2Head = 0;
}
else if ( IIRValue == IIR_CTI ) /* Character timeout indicator */
{
/* Character Time-out indicator */
/* Bit 9 as the CTI error */
}
else if ( IIRValue == IIR_THRE ) /* THRE, transmit holding register empty */
{
/* THRE interrupt */
LSRValue = U2LSR; /* Check status in the LSR to see if valid data in U3THR or not */
if ( LSRValue & LSR_THRE )
{
//передача байта завершена
if (Tx2Tail != Tx2Head)
{
//проверка режима
if( (Tx2Buf[Tx2Tail]&MDB_MODE_MSK) != 0 )
{
//передача команды
UART2_PAR_1();
}
else
{
//передача данных
UART2_PAR_0();
}
U2THR = Tx2Buf[Tx2Tail++];
if (Tx2Tail >= US2_TXBUFSIZE) Tx2Tail = 0;
}
else
{
//запрещаем прерывания по опустошению передающего буффера
U2IER &= ~IER_THRE;
//переключение в режим форсированный 0
UART2_PAR_0();
}
}
}
VICADDRESS = 0; /* Acknowledge Interrupt */
return;
}
/*****************************************************************************
** Function name: UARTInit
**
** Descriptions: Initialize UART0 port, setup pin select,
** clock, parity, stop bits, FIFO, etc.
**
** parameters: UART baudrate
** Returned value: true or false, return false only if the
** interrupt handler can't be installed to the
** VIC table
**
*****************************************************************************/
void UART2_init( unsigned int baudrate )
{
//разрешаем переферийное питание uart3
PCONP |= PCUART2;
//определяем делитель тактовой частоты uart3
if(PCLK_UART2_div == 0)
{
PCLKSEL1 &= ~PCLK_UART2_div;
}
else
{
PCLKSEL1 |= PCLK_UART2_div;
}
//выбираем альтернативные ф-ии выводов
PINSEL0 |= TXD2_line_on|RXD2_line_on; /* RxD0 and TxD0 */
unsigned int Fdiv;
U2LCR = DLC_ENA|STOP_1|CHL_8|PAR_0; /* 8 bits, Parity odd, 1 Stop bit */
//!!!(Fcclk/4) т.к. PCLK_UART3_div1
Fdiv = ( (Fcclk/Fcclk_UART2_div) / 16) / baudrate ; /*baud rate */
U2DLM = Fdiv / 256;
U2DLL = Fdiv % 256;
U2LCR = STOP_1|CHL_8|PAR_0; /* 8 bits, no Parity, 1 Stop bit */
U2FCR = FIFO_LEV_0|RES_TX_FIFO|RES_RX_FIFO|FIFO_ENA; /* Enable and reset TX and RX FIFO. */
//инсталлируем обработчик прерываний
install_irq( UART2_INT, (void *)UART2_Handler, HIGHEST_PRIORITY );
U2IER = IER_RBR /*| IER_RLS*/; /* Enable UART0 interrupt */
}
/*****************************************************************************/
/*****************************************************************************/
//переключение в режим проверки нечётности
void UART2_PAR_EVEN(void)
{
U2LCR = STOP_1|CHL_8|PAR_ON; /* 8 bits, Parity odd, 1 Stop bit */
}
/*****************************************************************************/
/*****************************************************************************/
//переключение в режим чётности форсированая 1
void UART2_PAR_1(void)
{
U2LCR = STOP_1|CHL_8|PAR_ON|PAR_1; /* 8 bits, Parity forced 1, 1 Stop bit */
}
/*****************************************************************************/
/*****************************************************************************/
//переключение в режим чётности форсированый 0
void UART2_PAR_0(void)
{
U2LCR = STOP_1|CHL_8|PAR_ON|PAR_0; /* 8 bits, Parity forced 0, 1 Stop bit */
}
/*****************************************************************************/
/*********************************************************/
signed int _getcharMDB(void)
{
__disable_interrupt();
signed int temp = -1;
if (Rx2Tail != Rx2Head)
{
temp = Rx2Buf[Rx2Tail++];
if (Rx2Tail >= US2_RXBUFSIZE) Rx2Tail = 0;
}
__enable_interrupt();
return(temp);
}
/**************************************************************/
/**************************************************************/
void _putcharMDB(unsigned int data)
{
__disable_interrupt();
if ( (U2IER & IER_THRE) == 0)
{
//прерывания по опустошению передающего регистра запрещены
//проверка режима
if( (data&MDB_MODE_MSK) != 0 )
{
//передача команды
UART2_PAR_1();
}
else
{
//передача данных
UART2_PAR_0();
}
//разрешаем прерывание
U2IER |= IER_THRE;
U2THR = (unsigned char) data;
}
else
{
//ложим байт в fifo
Tx2Buf[Tx2Head++] = data;
if (Tx2Head >= US2_TXBUFSIZE) Tx2Head = 0;
}
__enable_interrupt();
}
/**************************************************************/
void _putstringMDB_size( const int *pData, unsigned int size)
{
for(unsigned int i=0; i<size; i++)
{
_putcharMDB( *pData++);
}
}
void _putstringMDB_( const int *pData) { while(*pData != 0x00) _putcharMDB( *pData++ ) ; }
#define pPutStringMDB(x) do{static const int str[]=x; _putstringMDB(str);}while(0);