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

MSP430 - снова вопросы от чайника

Я не вижу функции инициализации UART, но попробуйте перед тем как разрешать прерывание от приемника UART (по)чистить его флаги.

В строках

 

следует поменять их очередность.

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

Ну, теряться байты перестали, спасибо. Но нули все равно приходят при включении питания. Не могу понять, откуда они берутся :05: а функции, значит, не очень? :)

 

 

А не лучше ли использовать DCO с внешним резистором, если толщина схемы важнее стабильности частоты?

Не, не лучше. Во-первых, хочется все же высокой частоты, от DCO - это 800кГц, а, во-вторых, не важнее, конечно, просто уменьшение размеров желательно

 

Мы используем Муратовские керамические трёхногие SMD-шные резонаторы с установлеными в них емкостями.

CSTCE8M00G55A-R0 - на 8МГц

CSTCR6M00G53-R0 - на 6МГц

И довольны

Спасибо! Я так и думала, что это хорошие :) Надеюсь, мы тоже будем довольны :)

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


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

Ну, теряться байты перестали, спасибо. Но нули все равно приходят при включении питания. Не могу понять, откуда они берутся :05:
Покажите функцию инициализации UART.

Не, не лучше. Во-первых, хочется все же высокой частоты, от DCO - это 800кГц, а, во-вторых, не важнее, конечно, просто уменьшение размеров желательно
Вы опять что-то недочитали в User's Guide ;) Частоту DCO можно изменить программно вплоть до 6,5МГц. А если использовать внешний резистор ROSC, то DCO можно легко разогнать МГц эдак до 50 одной левой. :biggrin: На такой частоте работать кристалл конечно же не сможет, но DCO такую частоту генерировать будет. Самолично проверял :) Проблема с DCO в том, что частота его зависит от температуры и напряжения питания. Для связи требуется стабильность битовой частоты не хуже 1-2%, 0,5% это вообще для любого случая подойдет. Если напряжения питания стабильно, используется внешний резистор ROSC с хорошим ТКС (не хуже скажем 50ppm/°C), DCO при старте калибруется по часовому кварцу (а при возникновении ошибок по связи происходит перекалибровка), то вполне можно обойтись и без внешнего высокочастотного кварца, одним лишь часовым.

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


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

Покажите функцию инициализации 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 ;)

Видимо, да :biggrin:

Частоту DCO можно изменить программно вплоть до 6,5МГц. А если использовать внешний резистор ROSC, то DCO можно легко разогнать МГц эдак до 50 одной левой. :biggrin: На такой частоте работать кристалл конечно же не сможет, но DCO такую частоту генерировать будет. Самолично проверял :) Проблема с DCO в том, что частота его зависит от температуры и напряжения питания. Для связи требуется стабильность битовой частоты не хуже 1-2%, 0,5% это вообще для любого случая подойдет. Если напряжения питания стабильно, используется внешний резистор ROSC с хорошим ТКС (не хуже скажем 50ppm/°C), DCO при старте калибруется по часовому кварцу (а при возникновении ошибок по связи происходит перекалибровка), то вполне можно обойтись и без внешнего высокочастотного кварца, одним лишь часовым.

Спасибо, буду иметь ввиду

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


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

Ну вот она и ошибка. Первой командой инициализации 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;

и все лишние нули пропадут.

post-3882-1222443222_thumb.jpg

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


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

Ну вот она и ошибка. Первой командой инициализации USART должна быть установка бита SWRST, как это и указано в User's Guide. Вставьте в процедуру инициализации первой командой

U0CTL = SWRST;

не-а, не помогло :)

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


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

не-а, не помогло :)

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

Кстати, что у вас такое NData и cData в структуре буфера?

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


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

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

Кстати, что у вас такое 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?

такой вопрос :)

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

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


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

NData - максимальный размер буфера, инициализируется UARTTxBuf.NData = sizeBufTx(16), СData - счетчик.

Шо це таке "sizeBufTx(16)"? :cranky: Функция? Или размер буфера?

Такое дело. Как выяснилось, такая работа буфера тоже занимает кучу лишнего времени, так как байты загружаются в буфер, только после того, как будет отправлена предыдущая посылка

if ((IE1 & UTXIE0) == 0)

Т.е. пока 6(в данном случае) байт не передастся, запись в буфер не произойдет. Это же не правильно? :) Хочу сделать так, что бы запись в буфер и отправка были независимы.

Дык буфер-то один или буферы для записи и для чтения разные? Если даже один, но размер его больше 12, то почему мешает одно другому?

Если делать задержку между посылками, то все нормально, но это же жутко не функционально. тогда вообще нет смысла в буфере :(
Раз у вас канал полнодуплексный и прием с передачей независимы, то сделайте вы два разных буфера и всех делов. :laughing:

а, кстати, не имеет ли смысла перед сбросом IE1 &= ~UTXIE0 проверять бит UTXEPT?
Не имеет. Запрет прерываний не влияет ни на текущую передачу байта, находящегося в сдвиговом регистре, ни на передачу следующего байта, находящегося в буфере передатчика USART.

По поводу кода. Извините, но я уже перестал что-либо понимать в этих огрызках функций :( А отрицательные числа, возвращаемые функцией (как код ошибки?), вместо привычных 0 и 1 или чисел натурального ряда, это вообще нечто :cranky:

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


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

: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, но по большому-то счету есть разница? ;) смысл такой, что не ноль.

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


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

но так получается, что запись следующей посылки идет только после того, как отправится текущая посылка , условие if ((IE1 & UTXIE0) == 0) - куча времени впустую.
Почему впустую? if это ведь не while, т.е. если условие не выполняется идем дальше, а не ждем его выполнения.

но я пониаю, что вам некогда разбираться во всем этом :05: Ну и ладно, и так помогли уже нехило :) разберусь. надеюсь :)
тут уже сам замысел, алгоритм непонятен. То ли вы реализуете пакетный протокол, который подразумевает запрос-ответ? То ли у вас информационный канал с контролем управления, построенный в "обертке" пакетного протокола? Если пакетный протокол точка-точка, то все так и должно быть: сначала передача запроса, затем прием ответа. Если же нужно постоянно гнать поток информации, лишь изредка, получая какие-то команды управления, то при наличии раздельных буферов чтения и записи, прерывание передатчика не нужно запрещать вообще. И опрос бита TXEPT тогда как раз нужен перед тем, как программно установить TXIFG для инициации прерываний.

При передаче работайте непосредственно с кольцевым буфером передатчика записывая в него по факту его опустошения. Т.е. в майне, где формируется пакет, счетчик буфера лишь увеличивается, а в прерывании передатчика счетчик буфера уменьшается. Индекс, естественно, только инкрементируется, учитывая переход его в начало буфера.

С буфером приемника аналогично, но наоборот. В прерывании приемника счетчик буфера увеличивается, а в майне вы буфер вычитываете и уменьшаете счетчик буфера. Прерывания ни приемника, ни передатчика при при этом запрещать не нужно. В прерывании приемника запись в буфер по факту наличия свободного места происходит.

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


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

Почему впустую? if это ведь не while, т.е. если условие не выполняется идем дальше, а не ждем его выполнения.

Да, но данные обновляются очень быстро, а запись в буфер не идет, пока не отправится предыдущая посылка, в результате данные теряются и сам буфер немного теряет смысл :)

тут уже сам замысел, алгоритм непонятен. То ли вы реализуете пакетный протокол, который подразумевает запрос-ответ? То ли у вас информационный канал с контролем управления, построенный в "обертке" пакетного протокола? Если пакетный протокол точка-точка, то все так и должно быть: сначала передача запроса, затем прием ответа. Если же нужно постоянно гнать поток информации, лишь изредка, получая какие-то команды управления, то при наличии раздельных буферов чтения и записи, прерывание передатчика не нужно запрещать вообще.

Будут две платы, на одной пакетный протокол запрос-ответ, на другой - постоянный поток информации, изредка получая команды :biggrin: пока второе

И опрос бита TXEPT тогда как раз нужен перед тем, как программно установить TXIFG для инициации прерываний.

При передаче работайте непосредственно с кольцевым буфером передатчика записывая в него по факту его опустошения. Т.е. в майне, где формируется пакет, счетчик буфера лишь увеличивается, а в прерывании передатчика счетчик буфера уменьшается. Индекс, естественно, только инкрементируется, учитывая переход его в начало буфера.

С буфером приемника аналогично, но наоборот. В прерывании приемника счетчик буфера увеличивается, а в майне вы буфер вычитываете и уменьшаете счетчик буфера. Прерывания ни приемника, ни передатчика при при этом запрещать не нужно. В прерывании приемника запись в буфер по факту наличия свободного места происходит.

ну, вроде работает, спасибо

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

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


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

Да, но данные обновляются очень быстро, а запись в буфер не идет, пока не отправится предыдущая посылка, в результате данные теряются и сам буфер немного теряет смысл :)
Я вам уже объяснял области применения буферов: а) синхронизация асинхронных потоков, б) сглаживание неравномерностей поступления данных в потоках.

Если у вас данные обновляются быстрее, чем уходят в канал связи и при этом требуется "не потерять" их, то это лишь означает, что у вас канал слишком "узкий" и "тормозной". Причем тут буфера?

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


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

Если у вас данные обновляются быстрее, чем уходят в канал связи и при этом требуется "не потерять" их, то это лишь означает, что у вас канал слишком "узкий" и "тормозной". Причем тут буфера?

Буферы, а не буфера :biggrin: канал вроде наладила :)

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


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

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

Там использую циклические "буфера" :-) своего изготовления.

http://electronix.ru/forum/index.php?showt...mp;#entry194257

Может пригодится...

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


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

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

Там использую циклические "буфера" :-) своего изготовления.

http://electronix.ru/forum/index.php?showt...mp;#entry194257

Может пригодится...

Наверняка пригодится! :yeah: Большое спасибо, VAI

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

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


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

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

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

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

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

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

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

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

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

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