Konan 0 22 февраля, 2010 Опубликовано 22 февраля, 2010 (изменено) · Жалоба Здравствуйте! Сейчас отлаживаю программу для кита 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 Буду очень Вам благодарен, если Вы поможете. Отвечу на любые вопросы по остальному коду. Две темы почему-то создалось. Это глюк. Удалите пожалуйста одну из них. Изменено 22 февраля, 2010 пользователем Omen_13 Оформление кода. Нарушение Правил п. 3.4 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DpInRock 0 22 февраля, 2010 Опубликовано 22 февраля, 2010 · Жалоба Что-то мне подсказывает, что ответа на вопрос "По прерыванию работаете с UART или по опросу" вы не знаете? Это так? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Konan 0 22 февраля, 2010 Опубликовано 22 февраля, 2010 · Жалоба Эмм))) Знаю конечно) Работаю по прерыванию. В коде функция void BSP_VIC_UART0(void); Она - обработчик прерывания UART0 и она запускает обработчики прерывания для протокола modbus. Дело то в том, что посылка от контроллера на com - порт должна проходить если я что-то пишу в регистр THR. Ну то есть сначала заполняется буфер FIFO - 16 байтов. А потом посылается пакет. Но ничего этого не происходит. И прерывание по приему также не генерируется. И осциоллограф при перердаче ничего толкового не показывает на выводе TXD, кроме непонятных непрерывных пилообразных импульсов. Кстати - буфер передачи - FIFO заполняется полностью а передача все-равно не происходит. Может я чего-то путаю, но осциллограф, хотябы должен показать некую последовательность прямоугольных импульсов... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DpInRock 0 23 февраля, 2010 Опубликовано 23 февраля, 2010 (изменено) · Жалоба Код программы там для обоих случаев. С прерыванием и без. У себя я просто убрал код который без прерывания. Воизбежание. Ибо вы например, можете ДУМАТЬ, что работаете по прерываниям... Проверьте для начала прием. Т.е. PC -> ARM. Я ставлю в прерывании инверсию какого-нибудь пина (искл. или). ---- Еще у вас там какая-то ОС торчит... Изменено 23 февраля, 2010 пользователем DpInRock Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Konan 0 23 февраля, 2010 Опубликовано 23 февраля, 2010 (изменено) · Жалоба Да. Торчит 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 Изменено 23 февраля, 2010 пользователем Konan Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ave 0 28 февраля, 2013 Опубликовано 28 февраля, 2013 · Жалоба Необходимо правильно установить скорость обмена. Расчет скорости на prototalk.net/forums/showthread.php?t=11. :smile3046: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SyncLair 0 28 февраля, 2013 Опубликовано 28 февраля, 2013 · Жалоба Еще заметил очень интересные штуки 1) с подключенным j-linkом UART не работает вообще. Т.е. регистры в IARе видны, но ни приема, ни передачи нет. Если j-link отключть - то UART сразу начинает работать. Жаль только отладку приходится делать через мигание светодиодов и вывод текста на LCD. Чтение периферийных регистров из отладчика -- плохая практика ибо операция чтение часто изменяет состояние перифириного устройства. Действительно советую разобраться с частотой. Попробуйте посылать байт 10 раз в секунду и замерьте частоту посыла в порт то есть если за 10 секунд у вас 20 символов а должно быть 10*10 значит в пять раз у вас частоты перепутаны. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться