Daria 0 25 сентября, 2008 Опубликовано 25 сентября, 2008 · Жалоба Я не вижу функции инициализации UART, но попробуйте перед тем как разрешать прерывание от приемника UART (по)чистить его флаги. В строках следует поменять их очередность. Кроме того, функции работы с буфером у вас не полностью реентерабельные. Они не обеспечивают атомарности доступа к переменным индекса и счетчика. Ну, теряться байты перестали, спасибо. Но нули все равно приходят при включении питания. Не могу понять, откуда они берутся :05: а функции, значит, не очень? :) А не лучше ли использовать DCO с внешним резистором, если толщина схемы важнее стабильности частоты? Не, не лучше. Во-первых, хочется все же высокой частоты, от DCO - это 800кГц, а, во-вторых, не важнее, конечно, просто уменьшение размеров желательно Мы используем Муратовские керамические трёхногие SMD-шные резонаторы с установлеными в них емкостями. CSTCE8M00G55A-R0 - на 8МГц CSTCR6M00G53-R0 - на 6МГц И довольны Спасибо! Я так и думала, что это хорошие :) Надеюсь, мы тоже будем довольны :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 25 сентября, 2008 Опубликовано 25 сентября, 2008 · Жалоба Ну, теряться байты перестали, спасибо. Но нули все равно приходят при включении питания. Не могу понять, откуда они берутся :05:Покажите функцию инициализации UART. Не, не лучше. Во-первых, хочется все же высокой частоты, от DCO - это 800кГц, а, во-вторых, не важнее, конечно, просто уменьшение размеров желательноВы опять что-то недочитали в User's Guide ;) Частоту DCO можно изменить программно вплоть до 6,5МГц. А если использовать внешний резистор ROSC, то DCO можно легко разогнать МГц эдак до 50 одной левой. На такой частоте работать кристалл конечно же не сможет, но DCO такую частоту генерировать будет. Самолично проверял :) Проблема с DCO в том, что частота его зависит от температуры и напряжения питания. Для связи требуется стабильность битовой частоты не хуже 1-2%, 0,5% это вообще для любого случая подойдет. Если напряжения питания стабильно, используется внешний резистор ROSC с хорошим ТКС (не хуже скажем 50ppm/°C), DCO при старте калибруется по часовому кварцу (а при возникновении ошибок по связи происходит перекалибровка), то вполне можно обойтись и без внешнего высокочастотного кварца, одним лишь часовым. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Daria 0 26 сентября, 2008 Опубликовано 26 сентября, 2008 · Жалоба Покажите функцию инициализации UART. U0CTL |= CHAR; // 8-bit character U0TCTL = SSEL0; // UCLK = ACLK U0BR0 = 0xA0; // 8.00Mhz 19200 bps (416) U0BR1 = 0x01; U0MCTL = 0x00; // no modulation U0CTL &= ~SWRST; ME1 |= UTXE0 + URXE0; // Enable USART0 TXD/RXD IE1 |= URXIE0; Флаги не сбрасываю, потому что не помогло :) Вы опять что-то недочитали в User's Guide ;) Видимо, да Частоту DCO можно изменить программно вплоть до 6,5МГц. А если использовать внешний резистор ROSC, то DCO можно легко разогнать МГц эдак до 50 одной левой. На такой частоте работать кристалл конечно же не сможет, но DCO такую частоту генерировать будет. Самолично проверял :) Проблема с DCO в том, что частота его зависит от температуры и напряжения питания. Для связи требуется стабильность битовой частоты не хуже 1-2%, 0,5% это вообще для любого случая подойдет. Если напряжения питания стабильно, используется внешний резистор ROSC с хорошим ТКС (не хуже скажем 50ppm/°C), DCO при старте калибруется по часовому кварцу (а при возникновении ошибок по связи происходит перекалибровка), то вполне можно обойтись и без внешнего высокочастотного кварца, одним лишь часовым. Спасибо, буду иметь ввиду Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 26 сентября, 2008 Опубликовано 26 сентября, 2008 · Жалоба Ну вот она и ошибка. Первой командой инициализации USART должна быть установка бита SWRST, как это и указано в User's Guide. Вставьте в процедуру инициализации первой командой U0CTL = SWRST; А дальше по вашему тексту. U0CTL |= CHAR; // 8-bit character U0TCTL = SSEL0; // UCLK = ACLK U0BR0 = 0xA0; // 8.00Mhz 19200 bps (416) U0BR1 = 0x01; U0MCTL = 0x00; // no modulation ME1 |= UTXE0 | URXE0; // Enable USART0 TXD/RXD U0CTL &= ~SWRST; IE1 |= URXIE0; и все лишние нули пропадут. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Daria 0 29 сентября, 2008 Опубликовано 29 сентября, 2008 · Жалоба Ну вот она и ошибка. Первой командой инициализации USART должна быть установка бита SWRST, как это и указано в User's Guide. Вставьте в процедуру инициализации первой командой U0CTL = SWRST; не-а, не помогло :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 29 сентября, 2008 Опубликовано 29 сентября, 2008 · Жалоба не-а, не помогло :) Делайте функции работы с буфером реентерабельными. Потому, что работа с ними в том числе из прерываний идет. По крайней мере атомарность доступа к указателям и счетчику буфера обеспечить нужно. Кстати, что у вас такое NData и cData в структуре буфера? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Daria 0 30 сентября, 2008 Опубликовано 30 сентября, 2008 (изменено) · Жалоба Делайте функции работы с буфером реентерабельными. Потому, что работа с ними в том числе из прерываний идет. По крайней мере атомарность доступа к указателям и счетчику буфера обеспечить нужно. Кстати, что у вас такое NData и cData в структуре буфера? NData - максимальный размер буфера, инициализируется UARTTxBuf.NData = sizeBufTx(16), СData - счетчик. Такое дело. Как выяснилось, такая работа буфера тоже занимает кучу лишнего времени, так как байты загружаются в буфер, только после того, как будет отправлена предыдущая посылка if ((IE1 & UTXIE0) == 0) Т.е. пока 6(в данном случае) байт не передастся, запись в буфер не произойдет. Это же не правильно? :) Хочу сделать так, что бы запись в буфер и отправка были независимы. Т.е. теперь int WriteTxbuf(int* data, char size) { unsigned char a, j; // BufferReset(&UARTTxBuf); if((UARTTxBuf.NData-UARTTxBuf.cData)<6)return -1; BufferWrite(&UARTTxBuf, 0xC0); for(j = 0; j < size; j++) { a = data[j] & 0xFF; switch (a) { case 0xC0: { BufferWrite(&UARTTxBuf, 0xDB); BufferWrite(&UARTTxBuf, 0xDC); break; } case 0xDB: { BufferWrite(&UARTTxBuf, 0xDB); BufferWrite(&UARTTxBuf, 0xDD); break; } default: BufferWrite(&UARTTxBuf, a); } a = data[j] >> 8; switch (a) { case 0xC0: { BufferWrite(&UARTTxBuf, 0xDB); BufferWrite(&UARTTxBuf, 0xDC); break; } case 0xDB: { BufferWrite(&UARTTxBuf, 0xDB); BufferWrite(&UARTTxBuf, 0xDD); break; } default: BufferWrite(&UARTTxBuf, a); } } BufferWrite(&UARTTxBuf, 0x3F); return 0; } А в основной порграмме if(state!=(-1)){ ReadRxbuf(&rxdata); txsize = 0; txdata[txsize++] = -4; txdata[txsize++] = -6; } if(WriteTxbuf(txdata, txsize)) state=-1; else state=0; if ((IE1 & UTXIE0) == 0) { IFG1 |= UTXIFG0; IE1 |= UTXIE0; } Почему <6? Потому, что сейчас посылки по 6 байт. Т.е., запись происходит только если есть место для следующей посылки(6 байт), а отправка начинается, если предыдущая посылка отправлена - эти два действия независимы. Но - в отладчике все хорошо, а на практике, при большой скорости передачи(т.е. когда идет непрерывная загрузка в буфер), последний байт в посылке теряется. Отчего это происходит? :07: Если делать задержку между посылками, то все нормально, но это же жутко не функционально. тогда вообще нет смысла в буфере :( а, кстати, не имеет ли смысла перед сбросом IE1 &= ~UTXIE0 проверять бит UTXEPT? такой вопрос :) Изменено 30 сентября, 2008 пользователем Daria Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 30 сентября, 2008 Опубликовано 30 сентября, 2008 · Жалоба NData - максимальный размер буфера, инициализируется UARTTxBuf.NData = sizeBufTx(16), СData - счетчик. Шо це таке "sizeBufTx(16)"? :cranky: Функция? Или размер буфера? Такое дело. Как выяснилось, такая работа буфера тоже занимает кучу лишнего времени, так как байты загружаются в буфер, только после того, как будет отправлена предыдущая посылка if ((IE1 & UTXIE0) == 0) Т.е. пока 6(в данном случае) байт не передастся, запись в буфер не произойдет. Это же не правильно? :) Хочу сделать так, что бы запись в буфер и отправка были независимы. Дык буфер-то один или буферы для записи и для чтения разные? Если даже один, но размер его больше 12, то почему мешает одно другому? Если делать задержку между посылками, то все нормально, но это же жутко не функционально. тогда вообще нет смысла в буфере :(Раз у вас канал полнодуплексный и прием с передачей независимы, то сделайте вы два разных буфера и всех делов. :laughing: а, кстати, не имеет ли смысла перед сбросом IE1 &= ~UTXIE0 проверять бит UTXEPT?Не имеет. Запрет прерываний не влияет ни на текущую передачу байта, находящегося в сдвиговом регистре, ни на передачу следующего байта, находящегося в буфере передатчика USART. По поводу кода. Извините, но я уже перестал что-либо понимать в этих огрызках функций :( А отрицательные числа, возвращаемые функцией (как код ошибки?), вместо привычных 0 и 1 или чисел натурального ряда, это вообще нечто :cranky: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Daria 0 30 сентября, 2008 Опубликовано 30 сентября, 2008 · Жалоба :05: typedef struct CharBuffer { unsigned char* Data; int NData; int cData; int pWrite; int pRead; } CharBuffer; #define sizeBufTx 16 struct CharBuffer UARTTxBuf; unsigned char bufTx[sizeBufTx]; #define sizeBufRx 16 struct CharBuffer UARTRxBuf; unsigned char bufRx[sizeBufRx]; почти весь код два сообщения назад :) Раньше делала отправку примерно так, как вы советовали(ссобщений эдак 7-8 назад), if ((IE1 & UTXIE0) == 0) запись в буфер IFG1 |= UTXIFG0; IE1 |= UTXIE0; В обработчике прерываний #pragma vector = USART0TX_VECTOR __interrupt void usart0_tx (void) { unsigned char data; if (!BufferRead(&UARTTxBuf, &data)) U0TXBUF = data; else IE1 &= ~UTXIE0; } но так получается, что запись следующей посылки идет только после того, как отправится текущая посылка , условие if ((IE1 & UTXIE0) == 0) - куча времени впустую. но я пониаю, что вам некогда разбираться во всем этом :05: Ну и ладно, и так помогли уже нехило :) разберусь. надеюсь :) А что касается return -1... случайно :) return 1, но по большому-то счету есть разница? ;) смысл такой, что не ноль. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 30 сентября, 2008 Опубликовано 30 сентября, 2008 · Жалоба но так получается, что запись следующей посылки идет только после того, как отправится текущая посылка , условие if ((IE1 & UTXIE0) == 0) - куча времени впустую.Почему впустую? if это ведь не while, т.е. если условие не выполняется идем дальше, а не ждем его выполнения. но я пониаю, что вам некогда разбираться во всем этом :05: Ну и ладно, и так помогли уже нехило :) разберусь. надеюсь :)тут уже сам замысел, алгоритм непонятен. То ли вы реализуете пакетный протокол, который подразумевает запрос-ответ? То ли у вас информационный канал с контролем управления, построенный в "обертке" пакетного протокола? Если пакетный протокол точка-точка, то все так и должно быть: сначала передача запроса, затем прием ответа. Если же нужно постоянно гнать поток информации, лишь изредка, получая какие-то команды управления, то при наличии раздельных буферов чтения и записи, прерывание передатчика не нужно запрещать вообще. И опрос бита TXEPT тогда как раз нужен перед тем, как программно установить TXIFG для инициации прерываний. При передаче работайте непосредственно с кольцевым буфером передатчика записывая в него по факту его опустошения. Т.е. в майне, где формируется пакет, счетчик буфера лишь увеличивается, а в прерывании передатчика счетчик буфера уменьшается. Индекс, естественно, только инкрементируется, учитывая переход его в начало буфера. С буфером приемника аналогично, но наоборот. В прерывании приемника счетчик буфера увеличивается, а в майне вы буфер вычитываете и уменьшаете счетчик буфера. Прерывания ни приемника, ни передатчика при при этом запрещать не нужно. В прерывании приемника запись в буфер по факту наличия свободного места происходит. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Daria 0 1 октября, 2008 Опубликовано 1 октября, 2008 (изменено) · Жалоба Почему впустую? if это ведь не while, т.е. если условие не выполняется идем дальше, а не ждем его выполнения. Да, но данные обновляются очень быстро, а запись в буфер не идет, пока не отправится предыдущая посылка, в результате данные теряются и сам буфер немного теряет смысл :) тут уже сам замысел, алгоритм непонятен. То ли вы реализуете пакетный протокол, который подразумевает запрос-ответ? То ли у вас информационный канал с контролем управления, построенный в "обертке" пакетного протокола? Если пакетный протокол точка-точка, то все так и должно быть: сначала передача запроса, затем прием ответа. Если же нужно постоянно гнать поток информации, лишь изредка, получая какие-то команды управления, то при наличии раздельных буферов чтения и записи, прерывание передатчика не нужно запрещать вообще. Будут две платы, на одной пакетный протокол запрос-ответ, на другой - постоянный поток информации, изредка получая команды пока второе И опрос бита TXEPT тогда как раз нужен перед тем, как программно установить TXIFG для инициации прерываний. При передаче работайте непосредственно с кольцевым буфером передатчика записывая в него по факту его опустошения. Т.е. в майне, где формируется пакет, счетчик буфера лишь увеличивается, а в прерывании передатчика счетчик буфера уменьшается. Индекс, естественно, только инкрементируется, учитывая переход его в начало буфера. С буфером приемника аналогично, но наоборот. В прерывании приемника счетчик буфера увеличивается, а в майне вы буфер вычитываете и уменьшаете счетчик буфера. Прерывания ни приемника, ни передатчика при при этом запрещать не нужно. В прерывании приемника запись в буфер по факту наличия свободного места происходит. ну, вроде работает, спасибо Изменено 1 октября, 2008 пользователем Daria Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rezident 0 1 октября, 2008 Опубликовано 1 октября, 2008 · Жалоба Да, но данные обновляются очень быстро, а запись в буфер не идет, пока не отправится предыдущая посылка, в результате данные теряются и сам буфер немного теряет смысл :)Я вам уже объяснял области применения буферов: а) синхронизация асинхронных потоков, б) сглаживание неравномерностей поступления данных в потоках. Если у вас данные обновляются быстрее, чем уходят в канал связи и при этом требуется "не потерять" их, то это лишь означает, что у вас канал слишком "узкий" и "тормозной". Причем тут буфера? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Daria 0 2 октября, 2008 Опубликовано 2 октября, 2008 · Жалоба Если у вас данные обновляются быстрее, чем уходят в канал связи и при этом требуется "не потерять" их, то это лишь означает, что у вас канал слишком "узкий" и "тормозной". Причем тут буфера? Буферы, а не буфера канал вроде наладила :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VAI 0 3 октября, 2008 Опубликовано 3 октября, 2008 · Жалоба Кстати, по уартам, я как-то выкладывал свои исходники работы с последовательными портами по прерыванию. Там использую циклические "буфера" :-) своего изготовления. http://electronix.ru/forum/index.php?showt...mp;#entry194257 Может пригодится... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Daria 0 4 октября, 2008 Опубликовано 4 октября, 2008 (изменено) · Жалоба Кстати, по уартам, я как-то выкладывал свои исходники работы с последовательными портами по прерыванию. Там использую циклические "буфера" :-) своего изготовления. http://electronix.ru/forum/index.php?showt...mp;#entry194257 Может пригодится... Наверняка пригодится! :yeah: Большое спасибо, VAI Изменено 4 октября, 2008 пользователем Daria Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться