Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: LPC2103
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
toweroff
Добрый день!
Что-то не соображу как сделать. Есть протокол MDB, он использует 9 бит данных. Этот 9й бит не контроль четности, он используется как выбор режима.
В LPC2103 нет как таковых 9 бит в UART,зато есть возможность включения Parity Enable с двумя режимами - Forced "1" stick parity и Forced "0" stick parity.
Я так понимаю, эти 0 или 1 будут всегда в этом режиме вставляться в 9й бит

Хорошо, передавать данные смогу. Но как принимать? Ведь с таким контролем я могу не принять данные...

Или я что-то упустил и долблюсь не в ту дверь?
Nixon
Сможете принять. Вот вам пример инициализации и функций уарта для работы с 9-битными посылками (для mdb) на LPC2xxx

CODE
#include "error.h"
#include "global.h"
#include "uart3.h"
#include "irq.h"

// указатель на mailbox для UART3 модуля
u32* uart3_mbx;

/* Обработчик прерывания UART3 */
void uart3_isr (void) __irq
{
u32 tmp = U3LSR;

tmp = ((tmp & 0x04) << 6) + U3RBR;

if (isr_mbx_check(uart3_mbx) != 0) isr_mbx_send(uart3_mbx, (void*)tmp); // если uart3_mbx не переполнен послали в uart2_mbx принятый байт и четность
VICVectAddr = 0; // завершили прерывание
}

/* Функция инициализации UART3 */
/* Параметры : baudrate - скорость обмена */
/* Результат : mailbox - указатель на ящик обмена */
void uart3_init(u32 baudrate, u32* mailbox)
{
uart3_mbx = mailbox; // сохранили указатель на mailbox

PINSEL0 &= ~((u32)3 << 0);
PINSEL0 |= (u32)2 << 0; // P0.0 включен как TXD3
PINSEL0 &= ~((u32)3 << 2);
PINSEL0 |= (u32)2 << 2; // P0.1 включен как RXD3

U3LCR = 0x2B; // 8 бит, с четностью = 1, 1 стоп бит
U3LCR |= 0x80; // установили DLAB
U3DLM = ((PCLK / 16) / baudrate) / 256; // установили baudrate
U3DLL = ((PCLK / 16) / baudrate) % 256;
U3LCR &= ~0x80; // сбросили DLAB
U3FCR = 0x07; // разрешаем и сбрасываем TX и RX FIFO

set_irq_isr(UART3_INT, (void *)uart3_isr, 0); // установка вектора прерывания UART2

U3IER = UART_IER_RBR; // разрешили прерывания по приему
}


/* Функция передачи блока данных по UART2 */
/* Параметры : data - передаваемый байт данных */
/* nine - девятый бит данных */
void uart3_send (u08 data, u08 nine)
{
if (nine) U3LCR = 0x2B;
else U3LCR =0x3B;
U3THR = data; // передача данных из буфера
while (!(U3LSR & UART_LSR_TEMT)); // ожидание завершения текущей передачи
}


Думаю из кода все понятно будет
mempfis_
Цитата(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);




toweroff
Всем спасибо!
буду разбираться
toweroff
Что-то не пойму, где наступил на граблю

Код
#define PARITY_ENABLE            0x08
#define    ODD_PARITY            (0x00|PARITY_ENABLE)
#define    EVEN_PARITY            (0x10|PARITY_ENABLE)
#define    FORCED_1_PARITY            (0x20|PARITY_ENABLE)
#define    FORCED_0_PARITY            (0x30|PARITY_ENABLE)


Код
//переключение в режим чётности форсированая 1
void UART0_PAR_1(void)
{
  U0LCR = STOP_BITS_1|BITS_8|FORCED_1_PARITY;   /* 8 bits, Parity forced 1, 1 Stop bit */
}

//переключение в режим чётности форсированый 0
void UART0_PAR_0(void)
{
  U0LCR = STOP_BITS_1|BITS_8|FORCED_0_PARITY;   /* 8 bits, Parity forced 0, 1 Stop bit */
}

Код
void putbyte0 (U16 c)
{
    while (!(U0LSR& 0x20));

    //проверка режима
    if(c & MDB_MODE_MSK)
    {
        //передача команды
        UART0_PAR_1();
    }
    else
    {
        //передача данных
        UART0_PAR_0();
    }

    U0THR = c;             /* transmit a character                 */
    
    return;                                
}


и функция, отправляющая пакет:

Код
void send_packet0 (U16 *buf, int length)
{
    while (length--)
    {
        putbyte0(*buf++);
    }
    return;
}


выполняю пошагово - все четко, 9-й бит корректно выставляется. Как только выполнение без отладки - 9й бит никак не хочет выставляться sad.gif
редактор
Может быть прежде чем менять четность, стоит дождаться окончания передачи?? Не уверен, что для каждого байта данных в ФИФО она запоминается.
toweroff
Цитата(редактор @ Jun 29 2012, 11:01) *
Может быть прежде чем менять четность, стоит дождаться окончания передачи??

так оно и дожидается в while (!(U0LSR& 0x20)); laughing.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.