|
Снова UART |
|
|
|
Jan 25 2007, 18:09
|
Группа: Новичок
Сообщений: 14
Регистрация: 17-01-07
Пользователь №: 24 520

|
Здравствуйте, недавно начал осваивать программирование микроконтроллеров, в частности msp430F169, столкнулся с проблемой передачи данных с него на компьютер. При передаче странно работает флаг UTXIFG0, т.е. он абсолютно не реагирует на помещение данных в U0TXBUF(хотя судя по руководству, должен сбрасываться), сбрасываеися лишь после вызова обработчика прерываний, и потом так и остается в нуле до PUC или SWRST=1.
Научите уму-разуму)), подскажите где ошибка. Спасибо.
Источник тактирования DCO (800kHz)
#include "msp430x16x.h"
int TransmitPacket(char *pData, int nDataSize);
int main() { // Остановить WatchDog timer WDTCTL = WDTPW + WDTHOLD;
/** Сбросить модуль USART (SWRST=1), Настроить порт: 8 бит в пакете, без контроля четности, 1 стоп-бит */ U0CTL = SWRST;
// Установить длину данных - 8 бит U0CTL |= CHAR;
// Источник тактирования - SMCLK U0TCTL |= SSEL1;
// Установить скорость работы порта 9600 бод U0BR0 = 0x53;
U0BR1 = 0x00;
U0MCTL = 0x03;
// Включить модуль USART через SFR (прием и передача) ME1 |= UTXE0 | URXE0;
// Разрешить прерывания по приему IE1 |= URXIE0;
// Очищаем SWRST бит U0CTL &= ~SWRST;
/*____________________Проверка_отправки_данных_на_компьютер______________________ _____*/
char aCheckData[] = {0x31,0x32,0x33};
int nCheckDataLen = 3;
for (;;) { TransmitPacket(aCheckData,nCheckDataLen); }
}//main
/** \fn int TransmitPacket(char *pData, int nDataSize) \param pData - указатель на передаваемый буфер nDataSize - размер передаваемых данных \brief Отправить данные в порт */
int TransmitPacket(char *pData, int nDataSize) { // Разрешить прерывания по приему IE1 |= UTXIE0;
// Переменная для хранения очередного байта данных (для ускорения операции доступа к данным массива) char *pTmpData = pData;
// Цикл передачи данных for (int nCount=nDataSize; nCount>0; nCount--) { // Разрешить маскированные прерывания (прерывания от периферийных модулей) _EINT();
// Дождаться готовности передатчика к приему новых данных while ( !(IFG1 & UTXIFG0) );
// Буфер готов к приему, записать очередной байт данных U0TXBUF = *pTmpData++;
// Дождаться завершения предыдущей операции записи while ( !(U0TCTL & TXEPT) ); }
// Передача завершена, прекратить вызов обработчика прерываний IE1 ^= UTXIE0;
return 0;
}// end of TransmitPacket()
#pragma vector = UART0TX_VECTOR
/** \fn void Uart0_TX (void) \brief Функция-обработчик прерываний от UART0 (при передаче) */ __interrupt void Uart0_TX (void) { // Прерывание обработано, сбросить GIE-бит _BIC_SR_IRQ(GIE); }
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 23)
|
Jan 25 2007, 22:13
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Во-первых, в опциях создания сообщения есть тэги цитирования и оформления кода, не могли бы вы ими пользоваться для лучшего восприятия вашего исходного кода другими читателями? Во-вторых, не вижу в приведенном вами коде команд настройки пинов микроконтроллера на выполнение ими функций UART. В-третьих, вы определитесь как все-таки вы желаете работать с UART: по прерываниям или по опросу флагов? Если по прерываниям, то оформляйте процедуру передачи и приема символа в самих прерываниях. Если же по опросу флага, то зачем вообще разрешать и запрещать прерывания? Флаги готовности конечно связаны с прерываниями, но устанавливаются они независимо от того разрешены или запрещены соответствующие источники прерываний. Тем более не нужно постоянно дергать глобальный флаг прерываний GIE. Он-то вообще тут никак не мешает и не помогает. Достаточно его установить после инициализации модуля UART и далее уже оперировать с битами управления прерываниями конкретного периферийного модуля (USART в данном случае). И вообще вы хоть какие-то примеры использования UART смотрели? На сайте производителя, например?
|
|
|
|
|
Jan 26 2007, 12:09
|
Группа: Новичок
Сообщений: 14
Регистрация: 17-01-07
Пользователь №: 24 520

|
Спасибо за дельные замечания, постараюсь учесть на будующее )), но все таки основной вопрос почему UTXIFG0 не реагирует на помещение данных в буфер передатчика, т.е. всегда ==1 (прерывания убрал, PIN настроил).
|
|
|
|
|
Jan 29 2007, 21:11
|
Группа: Новичок
Сообщений: 14
Регистрация: 17-01-07
Пользователь №: 24 520

|
Подрихтовал исходники )), проблемма все таже: флаг UTXIFG0 никак не реагирует на помещении байта данных в буфер передатчика, т.е. всегда ==1, соответственно до окна терминала, вызванного на подключенном к мк ООД данные, посланные в UART не доходят. Источник тактирования: по-умолчанию (DCO, 800kHz). Внимание, вопрос: почему?  . Спасибо. Код int main() { // Остановить WatchDog timer WDTCTL = WDTPW + WDTHOLD;
/*___________________________Инициализация_UART0__________________________*/
// P3.3,4 = USART0 TXD/RXD P3SEL = 0x30;
// Разрешить маскированные прерывания (прерывания от периферийных модулей) // _EINT();
/** Сбросить модуль USART (SWRST=1), Настроить порт: 8 бит в пакете, без контроля четности, 1 стоп-бит */ U0CTL = SWRST;
// Установить длину данных - 8 бит U0CTL |= CHAR;
// Источник тактирования - SMCLK U0TCTL |= SSEL1;
// Установить скорость работы порта 9600 бод U0BR0 = 0x53;
U0BR1 = 0x00;
U0MCTL = 0x03;
// Включить модуль USART через SFR (только передача) ME1 |= UTXE0;
// Очищаем SWRST бит U0CTL &= ~SWRST;
/*___________________________Передача_данных________________________________*/
for (;;) { // Дождаться готовности передатчика к приему новых данных while ( !(IFG1 & UTXIFG0) );
// Буфер готов к приему, записать очередной байт данных U0TXBUF = 0x31; }
}//main
|
|
|
|
|
Jan 30 2007, 04:09
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Так и будете в час, точнее в день по чайной ложке или все-таки прочитаете этот RTFM?  Цитата UTXIFG0 is set when U0TXBUF is empty. Установленный флаг UTXIFG0 свидетельствует о том, что UART готов к передаче (записи в буфер TXBUF) следующего байта, а не о том что он занят. Поскольку у него двойная буферизация, то два байта подряд он хавает на ура. Если бы проблема была только в этом флаге, то на терминале вы получили бы как минимум два символа. Поскольку вы не получаете ни одного, то проблема не там, где вы ее ищете. Если используете винусовый гипертерминал, то такое вполне может быть. Он по умолчанию требует handshake. Попробуйте вот с этим терминалом. P.S. а осциллографом вы смотрели сигналы? Может просто скорость передачи сильно отличается от ожидаемой?
|
|
|
|
|
Jan 30 2007, 20:47
|
Группа: Новичок
Сообщений: 14
Регистрация: 17-01-07
Пользователь №: 24 520

|
Ну на счет manual могу чесно сказать, что прочитал от корки до корки  ) и вот строка, из-за которой весь сыр-бор (английского с собой сейчас нет, но там также)) ) UTXIFGx автоматически сбрасывается, если запрос прерывания обслужен или если символ записан в UxTXBUF.А мой флаг при занесении данных в буфер передатчика игнорировал это правило, но как оказалось действительно это была не суть проблеммы, ошибка была в конструкции, связывающей мой мк с компьютером. Теперь наслаждаюсь трансляцией трафика с мк в терминал и обратно, несмотря на всегда равный 1 UTXIFGx  ). Спасибо за потраченное на меня время.
|
|
|
|
|
Jan 30 2007, 21:31
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(!Roma! @ Jan 30 2007, 22:47)  А мой флаг при занесении данных в буфер передатчика игнорировал это правило, Да не игнорировал он его  Думаю вы просто не успевали отследить его изменение. Как наблюдали/трассировали? С помощью USB-FET или LPT-FET? Можете сами убедиться, посылая строку из неповторяющихся символов с последовательно возрастающим кодом, например, 0x30, 0x31, 0x32, 0x33 и т.д. Если бы ваш вывод был верен, то на терминале вы бы не увидели всю последовательность символов по порядку. Первый был бы правильно, а последующие с большими пропусками. Типа такой последовательности 0x30, 0x39, 0x53, 0x67.... Цитата(!Roma! @ Jan 30 2007, 22:47)  но как оказалось действительно это была не суть проблеммы, ошибка была в конструкции, связывающей мой мк с компьютером. Наверное соединили одноименные сигналы, TxD MSP430 с TxD RS-232, а? ;)
|
|
|
|
|
Jan 30 2007, 21:41
|
Частый гость
 
Группа: Свой
Сообщений: 182
Регистрация: 5-10-06
Пользователь №: 21 031

|
Цитата(rezident @ Jan 30 2007, 21:31)  Как наблюдали/трассировали? С помощью USB-FET или LPT-FET? В чём может проявиться различие (не имея ввиду время отклика po USB&LPT)? Два JTAGa но один core (msp430)
|
|
|
|
|
Jan 30 2007, 22:09
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Lucky:) @ Jan 30 2007, 23:41)  Цитата(rezident @ Jan 30 2007, 21:31)  Как наблюдали/трассировали? С помощью USB-FET или LPT-FET?
В чём может проявиться различие (не имея ввиду время отклика po USB&LPT)? Два JTAGa но один core (msp430) Не понял, что вы подразумеваете под "различием", но чтобы обнаружить сброс флага UTXIFGx после записи в UxTXBUF нужно кроме установки breakpoint на этой команде одновременно еще и тактирование UART останавливать. Что дебаггер не делает. Если уж так хочется подловить этот "подлый" флаг, то выберите источником тактирования внешний сигнал UCLKx и тактируйте UART одиночными импульсами от кнопки, подключенной, например, к RS-триггеру. Вот тогда после записи в UxTXBUF флаг будет сброшен, пока до UARTа (при условии, что сдвиговый регистр пуст) не пройдет первый импульс BITCLK. Цитата The data is then moved to the transmit shift register on the next BITCLK after the TX shift register is empty, and transmission begins.
|
|
|
|
|
Jan 30 2007, 22:40
|
Частый гость
 
Группа: Свой
Сообщений: 182
Регистрация: 5-10-06
Пользователь №: 21 031

|
Цитата(rezident @ Jan 30 2007, 22:09)  Не понял, что вы подразумеваете под "различием" Я имел ввиду общие отличия JTAG по LPT и USB (вопрос не имеет отношение к проблеме ловли влага). Существует ли что-то такое, что LPT-JTAG проигрывае?
|
|
|
|
|
Feb 3 2007, 11:55
|
Группа: Новичок
Сообщений: 14
Регистрация: 17-01-07
Пользователь №: 24 520

|
Цитата Да не игнорировал он его Что ж на это мне ответить нечего, достаточно доходчиво  . При дальнейшем углублении в перепитии UARTA, созрел еще вопрос: (надеюсь, что более интеллектуальный чем с флагом  ) можно ли как-то работать напрямую со сдвигающим приемным буфером UARTa или хотя бы настроить его по аналогии с виндоусным регистром FIFO? Просто при отправке пакета данных, скажем из 6 байт, процедура обработки прерывания вызывается только для последнего байта, который в UXRXBUFe уже успел затереть 5 своих предшественников (выставлен флаг переполнения OE). Если не трудно, подскажите... Спасибо.
|
|
|
|
|
Feb 3 2007, 16:10
|
Участник

Группа: Участник
Сообщений: 65
Регистрация: 7-02-05
Из: Уфа
Пользователь №: 2 474

|
[quote name='!Roma!' date='Feb 3 2007, 13:55' post='205860'] При дальнейшем углублении в перепитии UARTA, созрел еще вопрос: (надеюсь, что более интеллектуальный чем с флагом  ) [/quote] [quote можно ли как-то работать напрямую со сдвигающим приемным буфером UARTa или хотя бы настроить его по аналогии с виндоусным регистром FIFO? Просто при отправке пакета данных, скажем из 6 байт, процедура обработки прерывания вызывается только для последнего байта, который в UXRXBUFe уже успел затереть 5 своих предшественников (выставлен флаг переполнения OE). Если не трудно, подскажите... Спасибо. [/quote] было бы идеальным решением для контроллеров кинул 20 байт и забыл  даже без прерываний, а зачем отвлекаться то  . Хотя думаю, что если использовать DMA, то это вполне осуществимо. А так использовать буфер на передачу и прием, что вообщем-то освобождает от рутины
|
|
|
|
|
Feb 3 2007, 19:41
|
Частый гость
 
Группа: Свой
Сообщений: 182
Регистрация: 5-10-06
Пользователь №: 21 031

|
Цитата(!Roma! @ Feb 3 2007, 11:55)  При дальнейшем углублении в перепитии UARTA, созрел еще вопрос: (надеюсь, что более интеллектуальный чем с флагом  ) можно ли как-то работать напрямую со сдвигающим приемным буфером UARTa или хотя бы настроить его по аналогии с виндоусным регистром FIFO? Просто при отправке пакета данных, скажем из 6 байт, процедура обработки прерывания вызывается только для последнего байта, который в UXRXBUFe уже успел затереть 5 своих предшественников (выставлен флаг переполнения OE). Если не трудно, подскажите... Спасибо. Думаю можно сделать "свой UART" на основе таймера и с FIFO.
|
|
|
|
|
Feb 3 2007, 20:58
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(!Roma! @ Feb 3 2007, 12:55)  При дальнейшем углублении в перепитии UARTA, созрел еще вопрос: (надеюсь, что более интеллектуальный чем с флагом  ) можно ли как-то работать напрямую со сдвигающим приемным буфером UARTa или хотя бы настроить его по аналогии с виндоусным регистром FIFO? Просто при отправке пакета данных, скажем из 6 байт, процедура обработки прерывания вызывается только для последнего байта, который в UXRXBUFe уже успел затереть 5 своих предшественников (выставлен флаг переполнения OE). Если не трудно, подскажите... Спасибо. Как-то не очень глубоко Вы углубились в понимании буфера. Там нет ничего для программиста! А для облегчения работы, когда скорость отправки не критична, а программировать лень, обычно создают циклический буфер, в который будет добавляться символ по putchar, a считываться и отправляться в системном тике таймера. Тогда этой ботвой с прерываниями по порту можно не заниматься. Успехов ;)
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Feb 3 2007, 23:29
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(!Roma! @ Feb 3 2007, 12:55)  При дальнейшем углублении в перепитии UARTA, созрел еще вопрос: (надеюсь, что более интеллектуальный чем с флагом  ) можно ли как-то работать напрямую со сдвигающим приемным буфером UARTa или хотя бы настроить его по аналогии с виндоусным регистром FIFO? Просто при отправке пакета данных, скажем из 6 байт, процедура обработки прерывания вызывается только для последнего байта, который в UXRXBUFe уже успел затереть 5 своих предшественников (выставлен флаг переполнения OE). Если не трудно, подскажите... Спасибо. Вот была похожая тема, там примеры кода приводились. Цитата(Dog Pawlowa @ Feb 3 2007, 19:58)  a считываться и отправляться в системном тике таймера. Тогда этой ботвой с прерываниями по порту можно не заниматься. Хм. Но с прерываниями по порту как-то естественнее :-)
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Feb 4 2007, 20:05
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(!Roma! @ Feb 3 2007, 13:55)  можно ли как-то работать напрямую со сдвигающим приемным буфером UARTa или хотя бы настроить его по аналогии с виндоусным регистром FIFO? Просто при отправке пакета данных, скажем из 6 байт, процедура обработки прерывания вызывается только для последнего байта, который в UXRXBUFe уже успел затереть 5 своих предшественников (выставлен флаг переполнения OE). Если не трудно, подскажите... Спасибо. Напрямую со сдвиговым регистром - нет, нельзя. Да и не нужно оно. Ведь гораздо сложнее отловить момент когда весь символ попал в сдвиговый регистр, чем прочитать его уже готовый из буферного регистора RXBUF. Но я опять не понял, что за проблемы? Теперь уже с приемом данных? Что за чудеса такие? У всех работает, а у вас кристалл "заколдованный" какой-то  Может у вас другие лишние прерывания вызываются? Или частоту тактирования ядра слишком низкую установили? У меня был проект где при тактовой частоте 4915,2кГц пакетный обмен (прием/передача) через UART (который на RS-485 работал) на скорости 115200 по прерываниям плюс системные 10мс тики все успешно работало. Цитата(Dog Pawlowa @ Feb 3 2007, 22:58)  А для облегчения работы, когда скорость отправки не критична, а программировать лень, обычно создают циклический буфер, в который будет добавляться символ по putchar, a считываться и отправляться в системном тике таймера. Тогда этой ботвой с прерываниями по порту можно не заниматься. Цитата(Dog Pawlowa @ Feb 4 2007, 18:43)  Вот и делаю в системном тике. А чтобы буфер не переполнялся, вставляю задержки между записями строк в буфер. Чтобы циклический буфер не переполнялся, по уму нужно два указателя и счетчик байт к нему присовокупить. P.S. точнее не для того чтобы буфер не переполнялся, а для того чтобы он нормально функционировал. Для того чтобы не переполнялся буфер должен быть "нужного" размера ;)
|
|
|
|
|
Feb 5 2007, 17:10
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(rezident @ Feb 4 2007, 21:05)  Цитата(Dog Pawlowa @ Feb 4 2007, 18:43)  Вот и делаю в системном тике. А чтобы буфер не переполнялся, вставляю задержки между записями строк в буфер.
Чтобы циклический буфер не переполнялся, по уму нужно два указателя и счетчик байт к нему присовокупить. P.S. точнее не для того чтобы буфер не переполнялся, а для того чтобы он нормально функционировал. Для того чтобы не переполнялся буфер должен быть "нужного" размера  Не-а, не согласен ! 1) Разве по разнице указателей нельзя сделать вывод о количестве байт в буфере? 2) "Нужного"? Если скорость записи больше скорости отправки, размера не хватит никогда, тем более в микроконтроллерах. Нужно просто не гнать коней, то бишь притормаживать запись в буфер.
--------------------
Уходя, оставьте свет...
|
|
|
|
|
Feb 6 2007, 01:10
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(Dog Pawlowa @ Feb 5 2007, 19:10)  Не-а, не согласен ! 1) Разве по разнице указателей нельзя сделать вывод о количестве байт в буфере? Если буфер действительно циклический, а не по типу стека, то разница между указателями сообщает количество находящихся там данных с точностью до размера самого буфера. Т.е. если буфер полностью заполнен, то указатели будут равны и разница их даст значение ноль, в то время как реальное количество данных будет равно размеру буфера. Разницу между указателями в качестве счетчика данных иногда можно использовать в буфере организованному по типу стека. Но и то при условии, что каждый из указателей изменяет свое значение предсказуемо, а не в процедуре прерывания, например. Цитата(Dog Pawlowa @ Feb 5 2007, 19:10)  2) "Нужного"? Если скорость записи больше скорости отправки, размера не хватит никогда, тем более в микроконтроллерах. Нужно просто не гнать коней, то бишь притормаживать запись в буфер.  Если скорость поступления постоянного потока данных в буфер значительно больше скорости передачи, то да. Но это лишь означает, что вы неправильно спроектировали всю систему обмена данными. В реальности же чаще всего данные поступают порциями, пакетами (что-то оцифровали, посчитали, сформировали строку, опросили состояние датчиков и т.п.) и пропускная способность канала известна тоже заранее. Но на этапе передачи данных возникают какие-то задержки/коллизии, например, нужно включить драйвер RS-485 на передачу и выждать паузу до начала передачи. Или получили данные от нескольких каналов АЦП по SPI на высокой скорости, а передать далее нужно через UART. Вот для таких случаев и применяется буфер, но отнюдь не безразмерный, замечу.
|
|
|
|
|
Feb 7 2007, 17:39
|
Гуру
     
Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823

|
Цитата(rezident @ Feb 6 2007, 02:10)  ... Но это лишь означает, что вы неправильно спроектировали всю систему обмена данными... О, правильные слова. Мы же говорим не о кодировании, а о системе. Неоптимально, я бы только предпочел говорить. Раз я не использую прерывания на передачу, значит канал не используется полностью, с другой стороны, я подтормаживаю контроллер при записи в циклический буфер. Вопрос открыт, сейчас заниматься этим времени нет. Может молодое поколение подгружу. В том же системном таймерном прерывании можно проверять количество символов в буфере, и если оно больше нуля, или намного больше нуля, запускать отправку по прерыванию передачи.
--------------------
Уходя, оставьте свет...
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|