Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Проблема с UART'ом
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
CSB
В симуляторе все работает отлично, но на железе передача идет одним коротким пакетом и затыкается (не устанавливается флаг готовности передатчика UART). Чего это может быть?
rezident
Исходный код в студию!
CSB
Что за... я же цеплял исходник!

Сейчас проверяю, а файлы не цепляются sad.gif

Код
#include  <msp430x12x.h>
#include  <stdlib.h>
#include  <data_type.h>

#define XTAL 8000000L
#define SIZE_MESSAGE 4    // длина входного сообщения, без учета заголовка сообщения
#define SIZE 10           // размер буферов FIFO

struct
{
    byte FIFO_full   : 1; // флаг переполнения FIFO
    byte end_receive : 1; // флаг окончания приема пакета данных
} status_flags;

// кольцевая очередь FIFO для передачи информации в ПК
typedef struct
{
    byte *const home;     // указатель на начало буфера
    byte *head;           // указатель на голову буфера
    byte *tail;           // указатель на хвост буфера
    byte *const end;      // указатель на конец буфера
} out_circular_buffer;

// кольцевая очередь FIFO для приема информации из ПК
typedef struct
{
    byte *const home;     // указатель на начало очереди
    byte *tail;           // указатель на хвост очереди
    byte *const end;      // указатель на конец очереди
} in_circular_buffer;

byte                    UART_out[SIZE];    // выходной буфер (от МК к ПК)
byte                    UART_in[SIZE];     // входной буфер (от ПК к МК)

in_circular_buffer      in_buffer =
{
    UART_in,
    NULL,
    UART_in + (SIZE - 1)
};

out_circular_buffer     out_buffer =
{
    UART_out,
    NULL,
    NULL,
    UART_out + (SIZE - 1)
};

byte UART_getchar();
void UART_putchar(byte value);

//-----------------------------------------------------------------------------------------------------------------------------------------------
void main(void)
{
    byte state;                 // текущее состояние конечного автомата
    volatile word ct;

    WDTCTL =   WDTPW            // Пароль для доступа к сторожевому таймеру
             + WDTHOLD;         // Останов сторожевого таймера

    IE1 |= OFIE;                // Разрешение прерывания при возникновении ошибки осцилятора

    // инициализация USART0: режим UART
    P3SEL |= 0x30;              // для ног P3.4,5 выбирается функция периферийного модуля USART0 TXD/RXD
    ME2 |= UTXE0 /*+ URXE0*/;       // Включение передачи и приема USART0
    UCTL0 |= CHAR;              // Контроль четности отключен; один стоповый бит; 8-разрядные даные;
    UTCTL0 |= SSEL0;            // UCLK = ACLK
    UBR00 = 0x45;               // 8 MHz 115200
    UBR10 = 0x00;               // 8 MHz 115200
    UMCTL0 = 0x00;              // 8 MHz 115200 modulation
    UCTL0 &= ~ SWRST;           // инициализация конечного автомата USART
    //IE2 |= URXIE0;              // разрешить прерывание при приеме

    // инициализация буферов FIFO
    out_buffer.head = out_buffer.tail = out_buffer.home;
    in_buffer.tail = in_buffer.home;

    _EINT();                    // Разрешить маскируемые прерывания

    //
    for (;;)
    {
        if (! status_flags.FIFO_full)
          UART_putchar('1');
/*
        for (ct = 0; ct < 0xFFFF; ct++);
        for (ct = 0; ct < 0xFFFF; ct++);
        for (ct = 0; ct < 0xFFFF; ct++);
        for (ct = 0; ct < 0xFFFF; ct++);
*/
    };
}

//-----------------------------------------------------------------------------------------------------------------------------------------------
#pragma vector = NMI_VECTOR
__interrupt void osc_fault(void)
{
//
// Прерывание при возникновении ошибки осциллятора
//

    volatile unsigned int i;

    BCSCTL1 |= XTS;             // ACLK = LFXT1 = HF XTAL - режим высокой частоты
    do
    {
        IFG1 &= ~ OFIFG;
        for (i = 0xFF; i; i--);    // Ожидание в течении ~50 мкс
    }
    while (IFG1 & OFIFG);    // Пока OFIFG установлен цикл будет повторяться, выход произойдет при стабилизации частоты
    BCSCTL2 |= SELM_3;          // MCLK = LFXT1 - источник тактирования для главного тактирования - XT1
    IE1 |= OFIE;                // Возобновить разрешение прерывания при возникновении ошибки осцилятора
}

//-----------------------------------------------------------------------------------------------------------------------------------------------
#pragma vector = UART0TX_VECTOR
__interrupt void usart0_tx(void)
{
//
//  Прерывание при передаче символа
//
    // Если буфер пуст, то запретим дальнейшие прерывания по флагу UTXIFG0
    if (out_buffer.head == out_buffer.tail)
    {
        status_flags.FIFO_full = 0;
        U0IE &= ~ UTXIE0;
    }
    else
    {
        TXBUF0 = *out_buffer.head;    // Cчитываем значение из головы буфера, пишем в UART это значение и увеличиваем
                                      //  указатель головы
        out_buffer.head++;

        // Если голова достигла конца буфера, то перемещаем указатель в начало буфера
        if (out_buffer.head > out_buffer.end)
          out_buffer.head = out_buffer.home;
    };
}

//-----------------------------------------------------------------------------------------------------------------------------------------------
void UART_putchar(byte value)
{
//
// Запись байта в буфер FIFO
//
    U0IE &= ~ (UTXIE0 + URXIE0);     // Запретим прерывания от UART

    // Если буфер не заполнен, то записываем в буфер value и сбрасываем FIFO_full
    if (   (out_buffer.tail == out_buffer.end && out_buffer.head == out_buffer.home)
        || (out_buffer.tail + 1 == out_buffer.head)
       )
      status_flags.FIFO_full = 1;
    else
    {
        *(out_buffer.tail) = value;
        status_flags.FIFO_full = 0;
        out_buffer.tail++;              // Увеличиваем указaтель хвоста очереди

        // Если хвост больше конца буфера, то вернем хвост в начало.
        if (out_buffer.tail > out_buffer.end)
          out_buffer.tail = out_buffer.home;
    };

    U0IE |= UTXIE0/* + URXIE0*/;         // Разрешим прерывания от UART
}
rezident
Ну все правильно. Вызов прерывания с вектором UART0TX_VECTOR сбрасывает флаг UTXIFG0. А у вас по окончании пакета при выполняющемся условии
Код
if (out_buffer.head == out_buffer.tail)

в TXBUF0 ничего не записывается. Чтобы UTXIFG0 был установлен для вызова прерывания нужно либо его установить программно, либо что-то записать в TXBUF0.
Т.е. вместо (или вместе) с
Код
U0IE |= UTXIE0/* + URXIE0*/;         // Разрешим прерывания от UART

нужно выполнить
Код
IFG0 |= UTXIFG0;
VAI
Выдрал из работающего проекта прием-передачу символов и свой кольцевой буфер.
При работе с буфером предприняты попытки разрешения конфликта одновременной записи в буфер принятого по прерыванию байта и считывания из этого же буфера.
Версия для работы без RTOS.
CSB
2rezident: спасибо за помощь. На железе посмотрю только завтра sad.gif
Поправочка: вместо IFG0 нужно IFG2. (это будущим поколения)

2VAI: спасибо за исходники.
rezident
Цитата(CSB @ Nov 27 2006, 18:59) *
2rezident: спасибо за помощь. На железе посмотрю только завтра sad.gif
Поправочка: вместо IFG0 нужно IFG2. (это будущим поколения)

Сорри! В спешке промахнулся. Нужно IFG1 или IFG2. Зависит от конкретного типа кристалла MSP430.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.