Перейти к содержанию
    

LPC2478 UART не принимает и не передает байты

Здравствуйте!

 

Сейчас отлаживаю программу для кита LPC2478STK

 

Проблема следующая: Проинициализировал UART0, функции приема и передачи взял стандартные из BSP

Но UART так и не хочет работать.

Ни HyperTerminal ни другие программы работы с COM-портом ничего не видят.

Проверил кабель, исходники, сам com-порт. Кабель спаян правильно, com - порт работает.

Проверил TXD на разъеме кита осциллографом. У меня частота передачи - 112500.

А он на частоте 2 кГц выдает какие-то непонятныее пилообразные импульсы вместо моих посылок.

 

Пробовал жестко через jtag манипулировать регистрами UART0 - U0RBR и U0THR. Они вообще не модифицируются.

 

Вот исходники UART:

 

 

 

#include <os_cpu.h>
#include <includes.h>
#include <bsp.h>
#include "vic.h"

#define  BSP_PINSEL0_TXD0					 DEF_BIT_04			   
#define  BSP_PINSEL0_RXD0					 DEF_BIT_06
#define  BSP_PINSEL0_U0_CLR				   DEF_BIT_05 | DEF_BIT_04 | \
										  DEF_BIT_07 | DEF_BIT_06 


// --------------------- UART REGISTERS DEFINES ------------		 
// ------- UART LINE CONTROL (LCR) REGISTER BIT DEFINES ----   
#define  BSP_LCR_WLS_5								 0		// 5 bit character length
#define  BSP_LCR_WLS_6								 1		// 6 bit character length
#define  BSP_LCR_WLS_7								 2		// 7 bit character length
#define  BSP_LCR_WLS_8								 3		// 8 bit character length 
#define  BSP_LCR_SBS_1								 0		// 1 stop bit			  
#define  BSP_LCR_SBS_2						DEF_BIT_02		// 2 stop bit  
#define  BSP_LCR_PE						   DEF_BIT_03		// Parity enable	
#define  BSP_LCR_PS_ODD								0		// Parity select: ODD 
#define  BSP_LCR_PS_EVEN					  DEF_BIT_04		// Parity select: EVEN	 
#define  BSP_LCR_PS_STICK_1				   DEF_BIT_05		// Parity select: '1' stick
#define  BSP_LCR_PS_STICK_0				   DEF_BIT_04 | \
										  DEF_BIT_05 
#define  BSP_LCR_DLAB						 DEF_BIT_07		// Divisor Latch Acces bit enable

// ----- UART FIFO CONTROL REGISTER (LCR) BIT DEFINES ------   
#define  BSP_FCR_FIFO_EN					  DEF_BIT_00		// FIFO enable
#define  BSP_FCR_RX_RST					   DEF_BIT_01		// FIFO Rx reset
#define  BSP_FCR_TX_RST					   DEF_BIT_02		// FIFO Tx reset
					// ---- UART LINE STATUS (LSR) REGISTER BITS DEFINES  ------

#define  BSP_LSR_RDR						  DEF_BIT_00		// Receiver Data Ready Flag
#define  BSP_LSR_THRE						 DEF_BIT_05		// Transmiter Holding Register Empty Flag





// Обработчики прерываний нужные для modbus
t_pvfunc hwOnUART0Receive;
t_pvfunc hwOnUART0Transmit;
t_pvfunc hwOnOC1A;

/////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//										SERIAL FUNCTIONS
/////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////////////////////////////////
//										BSP_Ser_Init()
//
//  Description : This function initializes a UART.
//
//  Argument(s) : none.
//
//  Return(s)   : none.
//
//  Caller(s)   : Application.
//
//  Note(s)	 : none.
/////////////////////////////////////////////////////////////////////////////////////////////////////////


void  BSP_Ser_Init (CPU_INT32U baud_rate)
{
CPU_FP32	div_fp;										 // Baud rate divisor floating point precision
CPU_INT16U  div_int;										// Baud rate divisor floating point precision
CPU_INT08U  divlo;
CPU_INT08U  divhi;
CPU_INT32U  pclk_freq;

PCLKSEL0_bit.PCLK_UART0 = BSP_PCLK_UART0;

for (int i = 0; i <10000; i++);

pclk_freq = BSP_CPU_PclkFreq(BSP_PCLK_UART0);			   // Get peripheral clock frequency

div_fp	= (pclk_freq / 16.0 / baud_rate);				 // Compute divisor for desired baud rate 
div_int   = (CPU_INT16U)(div_fp + 0.5);					 // Round the number up

divlo	 = div_int		& 0x00FF;						// Split divisor into LOW and HIGH bytes 
divhi	 = (div_int >> 8) & 0x00FF;


PCONP	|= BSP_PCONP_UART0_EN;							 // Enable the power bit for  UART0

U0LCR	 = BSP_LCR_DLAB;								   // Enable acces to Divisor latches

U0DLL	 =  divlo;										 // Load divisor
U0DLM	 =  divhi;

U0FCR	|= BSP_FCR_FIFO_EN;

U0LCR	 = BSP_LCR_WLS_8
		  | BSP_LCR_SBS_1;

U0LCR	&= (~BSP_LCR_DLAB);								// Disable acces to Divisor latches

U0IER	= (DEF_BIT_00 & DEF_BIT_01);  // включаем прерывания RBR и THRE

PINSEL0  &= ~BSP_PINSEL0_U0_CLR;
PINSEL0  |= BSP_PINSEL0_TXD0								// Enable TXDO function
		  | BSP_PINSEL0_RXD0;							   // Enable RXD0 function


VICINTSELECT	 &= ~(1 << VIC_UART0);					 // Configure the UART interrupt as an IRQ source.
VICVECTPRIORITY6 = 17;									 // Set the vector priority. 
VICINTENABLE	  |= (1 << VIC_UART0); 

}

/////////////////////////////////////////////////////////////////////////////////////////////////////////
//											   BSP_Ser_WrByte()
//
//  Description : Transmit a single byte.
//
//  Argument(s) : byte		The byte that should be transmitted.
//
//  Return(s)   : none.
//
//  Caller(s)   : Application
//
//  Note(s)	 : none.
/////////////////////////////////////////////////////////////////////////////////////////////////////////

void  BSP_Ser_WrByte (CPU_INT08U tx_byte)
{
while ((U0LSR & BSP_LSR_THRE) == 0) {
   ;
}

U0THR = tx_byte;

}

/////////////////////////////////////////////////////////////////////////////////////////////////////////
//											   BSP_Ser_WrStr()
//
//  Description : Transmits a string.
//
//  Argument(s) : tx_str	  The string that will be transmitted.
//
//  Return(s)   : none.
//
//  Caller(s)   : none.
//
//  Note(s)	 : none.
/////////////////////////////////////////////////////////////////////////////////////////////////////////

void  BSP_Ser_WrStr (CPU_CHAR * tx_str)
{
while ((*tx_str) != 0) {
	BSP_Ser_WrByte(*tx_str++);
	OSTimeDly(1);
}
}

/*
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//											   BSP_Ser_RdByte()
//
//  Description : Receive a single byte.
//
//  Argument(s) : none.
//
//  Return(s)   : The received byte
/////////////////////////////////////////////////////////////////////////////////////////////////////////
*/

CPU_INT08U  BSP_Ser_RdByte (void)
{
CPU_INT08U  rx_byte;


while ((U0LSR & BSP_LSR_RDR) == 0) {
	OSTimeDly(1);
}

rx_byte = (CPU_INT08U)(U0RBR & 0x00FF);					 // Remove the data from the holding register 
return (rx_byte);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////
//											   BSP_Ser_RdStr()
//
//  Description : This function reads a string from a UART.
//
//  Argument(s) : s		   A pointer to a buffer at which the string can be stored.
// 
//				len		 The size of the string that will be read.
//
//  Return(s)   : none.
/////////////////////////////////////////////////////////////////////////////////////////////////////////

void  BSP_Ser_RdStr (CPU_CHAR	*rx_str,
				 CPU_INT32U   len)
{
CPU_CHAR  input;
CPU_CHAR  input_ix;


input_ix  = 0;
rx_str[0] = 0;

while (1)
{
	input = BSP_Ser_RdByte();

	if ((input == '\r') ||
		(input == '\n')) {
		BSP_Ser_Printf("\n");
		rx_str[input_ix] = 0;
		break;
	}

	if (input == '\b') {
		if (input_ix > 0) {
			BSP_Ser_Printf("\b \b");
			input_ix--;
			rx_str[input_ix] = 0;
		}
	}

	if (ASCII_IsPrint(input)) {
		BSP_Ser_Printf("%c", input);
		rx_str[input_ix] = input;
		input_ix++;
		if (input_ix >= len) {
		   input_ix = len;
		}
	}
}
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////
//											   BSP_Ser_Printf()
//
//  Description : Formatted outout to the serial port.
//				This funcion reads a string from a serial port. This call blocks until a
//				character appears at the port and the last character is a Carriage
//				Return (0x0D).
//
//  Argument(s) : Format string follwing the C format convention.
//
//  Return(s)   : none.
/////////////////////////////////////////////////////////////////////////////////////////////////////////

void  BSP_Ser_Printf (CPU_CHAR *format, ...)
{
static  CPU_CHAR  buffer[80 + 1];
		va_list   vArgs;


va_start(vArgs, format);
vsprintf((char *)buffer, (char const *)format, vArgs);
va_end(vArgs);

BSP_Ser_WrStr((CPU_CHAR*) buffer);
}


void  BSP_VIC_UART0 (void)
{
CPU_INT32U statusLSR = 0; 
CPU_INT32U statusIIR = 0;   

statusLSR = U0LSR; //для очистки прерывания ошибок UART
statusIIR = U0IIR;		

BSP_VIC_SpuriousInt = VIC_UART0;
if (!(statusIIR & DEF_BIT_00))
{
  if (statusIIR & DEF_BIT_02)  //Receive Data Available (RDA).
  {

	if ((hwOnUART0Receive != NULL ) && (statusLSR & DEF_BIT_00))
	  hwOnUART0Receive();		
  }
  if (statusIIR & DEF_BIT_01)  //THRE.
  {
	if ((hwOnUART0Transmit != NULL) && (statusLSR & DEF_BIT_05))
	  hwOnUART0Transmit();	   
  }	  
}
}






CPU_INT16U  BSP_UART0_BaudRateGet (void)
{
CPU_FP32	div_fp;										 // Baud rate divisor floating point precision 
CPU_INT16U  div_int;										// Baud rate divisor floating point precision 
CPU_INT08U  divlo;
CPU_INT08U  divhi;
CPU_INT32U  pclk_freq;

pclk_freq = BSP_CPU_PclkFreq(BSP_PCLK_UART0);			   // Get peripheral clock frequency	 

divlo = U0DLL;	  //получаем старший и младший байт делителя
divhi = U0DLM;

div_int = (CPU_INT16U)divlo + (((CPU_INT16U)divhi >> 8) & 0xFF00);

div_fp = (CPU_FP32)div_int - 0.5;

return  (CPU_INT32U)(pclk_freq / 16.0 / div_fp);
}




void  BSP_UART0_BaudRateIndexSet(CPU_INT32U baud_rate)
{

CPU_FP32	div_fp;										 // Baud rate divisor floating point precision 
CPU_INT16U  div_int;										// Baud rate divisor floating point precision 
CPU_INT08U  divlo;
CPU_INT08U  divhi;
CPU_INT32U  pclk_freq;

OS_CPU_SR  cpu_sr = 0;

OS_ENTER_CRITICAL();

pclk_freq = BSP_CPU_PclkFreq(BSP_PCLK_UART0);			   // Get peripheral clock frequency

div_fp	= (pclk_freq / 16.0 / baud_rate);				 // Compute divisor for desired baud rate 
div_int   = (CPU_INT16U)(div_fp + 0.5);					 // Round the number up

divlo	 = div_int		& 0x00FF;						// Split divisor into LOW and HIGH bytes 
divhi	 = (div_int >> 8) & 0x00FF;

U0DLL	 =  divlo;										 // Load divisor
U0DLM	 =  divhi;

OS_EXIT_CRITICAL();
}


void  BSP_UART0_ReceiverEnable(void)
{
OS_CPU_SR  cpu_sr = 0;

OS_ENTER_CRITICAL();	

PINSEL0  |= BSP_PINSEL0_RXD0;  // Включаем функцию входа RXD0   

U0IER	= (DEF_BIT_00 & DEF_BIT_01);  // включаем прерывания RBR и THRE 

OS_EXIT_CRITICAL();	
}





void  BSP_UART0_ReceiverDisable(void)
{
OS_CPU_SR  cpu_sr = 0;

OS_ENTER_CRITICAL();	

PINSEL0  &= 0xFFFFFFFF & (~BSP_PINSEL0_RXD0);	 //отключаем вход RXD0   

U0IER	= DEF_BIT_01;  // прерывание только от THRE	
OS_EXIT_CRITICAL();	
}


CPU_INT08U hwUART0StopBitsGet(void)
{
 if (U0LCR & DEF_BIT_02)  //Stop Bit Select
return 2;
 else
return 1;  
}


CPU_BOOLEAN hwUART0StopBitsSet(CPU_INT08U val)
{
 switch (val)
 {
case 1:
   U0LCR &= (~DEF_BIT_02); //not Stop Bit Select
   return DEF_TRUE;
case 2:
   U0LCR |= DEF_BIT_02;
   return DEF_TRUE;
 }
 return DEF_FALSE;
}



CPU_INT32U hwBaudRateIndexToBaudRate(CPU_INT8U val)
{
 switch (val) //взято с индексов com-порта, может быть не правильно
 {
case  0: return 75;
case  1: return 110;
case  2: return 134;
case  3: return 150;  
case  4: return 300;  
case  5: return 600;
case  6: return 1200;
case  7: return 1800; 
case  8: return 2400; 
case  9: return 4800; 
case 10: return 7200; 
case 11: return 9600; 
case 12: return 14400; 
case 13: return 19200; 
case 14: return 48400; 
case 15: return 57600;
case 16: return 115200;
case 17: return 128000;
default: return 0xFFFFFFFF;
 }  
}

 

 

 

Собственно тут еще в конце обработчики прерываний и сервисные ф-ции для modbus.

 

Использую IDE IAR 5.30 + mt-link

 

Буду очень Вам благодарен, если Вы поможете. Отвечу на любые вопросы по остальному коду.

 

Две темы почему-то создалось. Это глюк. Удалите пожалуйста одну из них.

Изменено пользователем Omen_13
Оформление кода. Нарушение Правил п. 3.4

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что-то мне подсказывает, что ответа на вопрос "По прерыванию работаете с UART или по опросу" вы не знаете? Это так?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Эмм))) Знаю конечно) Работаю по прерыванию. В коде функция void BSP_VIC_UART0(void);

 

Она - обработчик прерывания UART0 и она запускает обработчики прерывания для протокола modbus. Дело то в том, что посылка от контроллера на com - порт должна проходить если я что-то пишу в регистр THR. Ну то есть сначала заполняется буфер FIFO - 16 байтов. А потом посылается пакет.

 

Но ничего этого не происходит. И прерывание по приему также не генерируется. И осциоллограф при перердаче ничего толкового не показывает на выводе TXD, кроме непонятных непрерывных пилообразных импульсов.

 

Кстати - буфер передачи - FIFO заполняется полностью а передача все-равно не происходит. Может я чего-то путаю, но осциллограф, хотябы должен показать некую последовательность прямоугольных импульсов...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Код программы там для обоих случаев. С прерыванием и без.

У себя я просто убрал код который без прерывания. Воизбежание.

 

Ибо вы например, можете ДУМАТЬ, что работаете по прерываниям...

 

Проверьте для начала прием. Т.е. PC -> ARM.

Я ставлю в прерывании инверсию какого-нибудь пина (искл. или).

 

----

Еще у вас там какая-то ОС торчит...

Изменено пользователем DpInRock

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Да. Торчит uOS-II и uCGUI;

 

Согласен с Вами. Я ДУМАЛ что работаю по прерываниям.

 

Код исправил.

 

Пришлось написать свою функцию инициализации делителя частоты UART для заданного Бодрейта.

Ну и подправить обработчик прерывания и ф-цию инициализации UART0.

 

Исправленный код приложил к сообщению.

 

Еще заметил очень интересные штуки

1) с подключенным j-linkом UART не работает вообще. Т.е. регистры в IARе видны, но ни приема, ни передачи нет.

Если j-link отключть - то UART сразу начинает работать. Жаль только отладку приходится делать через мигание светодиодов и вывод текста на LCD.

 

2) Регистр UART IER (U0IER) - регистр включения прерываний - через или-рвно (|=) - не записывается. Только через битовое объединенеие. Т.е. чтобы включть прерывание по заполнению FIFO надо было писать U0IER_bit.RDAIE = 1;

 

Возникли следующие проблемы:

1) Контроллер принимает посылку. Но вместо текста, символов - абракадабра.

 

Например: отправляю 0xFF - контроллер выдает 0. 0xFD -> 0, 0xFC -> 2; "11111111" -> ">"i>'i>" и т.д. Это не инверсия кода. Я проверял. Что такое - пока не знаю.

 

2) Хочу сделать передачу. Но оять же - абракадабра выходит.

После приема посылки - отправляю на PC строку "preved_medved" (почти шутка)

но терминал на PC показывает что-то вроде "111q11cqq"

 

Вот что это такое не знаю. Может в тактировании где ошибся. А может и не ошибся. Вроде проверял, там по алгоритму в User Manual все так и получается.

uart.rar

Изменено пользователем Konan

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Необходимо правильно установить скорость обмена.

Расчет скорости на prototalk.net/forums/showthread.php?t=11.

:smile3046:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще заметил очень интересные штуки

1) с подключенным j-linkом UART не работает вообще. Т.е. регистры в IARе видны, но ни приема, ни передачи нет.

Если j-link отключть - то UART сразу начинает работать. Жаль только отладку приходится делать через мигание светодиодов и вывод текста на LCD.

Чтение периферийных регистров из отладчика -- плохая практика ибо операция чтение часто изменяет состояние перифириного устройства.

 

Действительно советую разобраться с частотой. Попробуйте посылать байт 10 раз в секунду и замерьте частоту посыла в порт

то есть если за 10 секунд у вас 20 символов а должно быть 10*10 значит в пять раз у вас частоты перепутаны.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...