реклама на сайте
подробности

 
 
> UART STM32, передача сообщения
ierofant
сообщение Oct 27 2011, 22:12
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 32
Регистрация: 3-02-11
Из: Украина, Киев
Пользователь №: 62 695



Всем привет.
Разбираюсь в UARTe на STM32F100.

UART запутился, передачу и прием реализовал на прерываниях по окончанию передачи и приему.
В связи с этим есть вопросы:

Необходимо: Сделать передачу сообщения по событию, например - установке флага при нажатии на кнопку. (в программе message_must_send=1)

Проблема: Если реализовать это в прерывании, то прерывание по окончанию передачи просто напросто не генерируется и не происходит передача.(даже в обработчик не заходит, смотрел в отладчике) Передача начинается только после того, как был отправлен хотя бы один байт вне обработчика прерывания.
Т.е. нажимаю кнопкку на отладочной - ничего не передается, пока через терминал не пошлю любое примитивное соообщение(возвращается эхо, где и происходит отправка сообщения).

Если же первый элемент строки передавать во время установки флага, а все остальные уже в обработчике - все отлично работает.(хоть что-то записать в регистр данных, чтоыб потмо сработало прерывание по окончанию передачи) Но решать таким образом проблему как-то совсем глупо. Я надеюсь, вы мне подскажете поинтереснее варианты её решения.

Код ниже прилагается:
Инициализация:
Код
//инициализация юарта
void init_uart()
    {
    RCC->APB2ENR|= RCC_APB2ENR_AFIOEN; // Тактирование альтернативных функций GPIO.
    RCC->APB2ENR|= RCC_APB2ENR_USART1EN; // Включение тактирования USART1.
    GPIOA->CRH |= GPIO_CRH_MODE9; // Вывод TX PA.9 - на выход.
    GPIOA->CRH &=~GPIO_CRH_CNF9; GPIOA->CRH |=GPIO_CRH_CNF9_1; // Альтернативный выход.
    USART1->CR1 |=(USART_CR1_RE | USART_CR1_TE); // Разрешить выводы RX, TX.
          // Скорость 9.6 kbps. USARTDIV=FSYS/(16*baud) = 24e6/(16*9600)=156.25
    USART1->BRR=(156<<4); // Целая часть коэффициента деления USART1.
    USART1->BRR|=4; // Дробная часть*16 = 0,25*16 = 4.
    USART1->CR1 |=USART_CR1_UE; // Включение USART1.
    USART1->CR1 |=USART_CR1_TCIE|USART_CR1_RXNEIE; // Разрешить прерывания TC, RXNE.
    NVIC_EnableIRQ(USART1_IRQn); // Разрешить прерывание USART1_IRQn в NVIC.
    NVIC_SetPriority(USART1_IRQn, 3); //задать приоритет прерыванию
    }


Обработчик:
Код
void USART1_IRQHandler (void) // Обработчик прерывания USART1.
     {
          if (USART1->SR & USART_SR_RXNE) USART1->DR=USART1->DR;  // Если прерывание по приёму, то возвращаем эхо
          if (USART1->SR & USART_SR_TC) // Если прерывание по завершению передачи.
          {
            if(message_must_send==1)
            {
               if (message[tmp])
                {
                USART1->DR=message[tmp];
                tmp++;
                }
               else
                {
                tmp=0;
                message_must_send=0;
                }
            }
            USART1->SR&=~(USART_SR_TC|USART_SR_RXNE); // Очистить флаги прерывания.
          }
     }



Теперь вопросы:
1. Есть ли какой-то способ программно сгенерировать прерывание по окончанию передачи? Т.е. установить в статус-регистре SR бит ТС? Перерыл всю документацию - такой инфы не нашел.
2. Каким образом лучше производить передачу сообщения - в обработчике прерывания или же в основном цикле?
3. Если описать передачу в основном цикле - есть ли смысл в прерывании по окончанию передачи? Ведь можно просто отслеживать с таким же успехом состояние битов в статус-регистре.

Возможно, получилось несколько сбито и сумбурно, но столько вопросов и предложений вертится в голове, что сразу все и не вспомнишь. Буду очень благодарен за обьяснения и советы.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Serj78
сообщение Oct 29 2011, 15:02
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 966
Регистрация: 27-05-06
Из: СПб
Пользователь №: 17 499



Есть при использовании TXE один нюанс, связанный с оценкой времени обработки прерываний. Дело в том, что внутри обработчика прерываний мы проверяем, выставлен ли флаг TXE ? и если нам передавать нечего- запрещаем генерацию прерываний по TXE.
Но этот запрет НЕ СБРАСЫВАЕТ ЭТОТ ФЛАГ.
Поэтому, если в прерывание мы попали из-за приемника , то ветка обработки-анализа нужно ли что- нибудь передавать, всегда активна, на ее анализ тратится время. Это следует учитывать.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Oct 31 2011, 08:11
Сообщение #3


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(Serj78 @ Oct 29 2011, 19:02) *
Есть при использовании TXE один нюанс, связанный с оценкой времени обработки прерываний. Дело в том, что внутри обработчика прерываний мы проверяем, выставлен ли флаг TXE ? и если нам передавать нечего- запрещаем генерацию прерываний по TXE.
Но этот запрет НЕ СБРАСЫВАЕТ ЭТОТ ФЛАГ.
Поэтому, если в прерывание мы попали из-за приемника , то ветка обработки-анализа нужно ли что- нибудь передавать, всегда активна, на ее анализ тратится время. Это следует учитывать.
Какой выход предлагаете?
Ведь TXE флаг-то сбрасывается только записью нового байта в data_reg или есть ещё какой-то способ?
Может трансмиттер вообще отключать, но тогда нужно ожидать ТXC флага.
Я так на AVR делал (по UDRE тх-фифо выгребал, по TXC отключал передатчик - работало красиво).
Только тут всё это не поможет - прерывание одно, поэтому число условий останется прежнимsad.gif


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Oct 31 2011, 08:55
Сообщение #4


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(demiurg_spb @ Oct 31 2011, 14:11) *
Какой выход предлагаете?

Можно сначала проверять состояние разрешения/запрета прерываний от TXE, (если каждый раз проверять наличие символов на передачу накладно):
Код
void USART1_IRQHandler (void) {
    uint16_t status = USART1->SR;
    if (status & USART_SR_RXNE) {
      ...
    }

    if (USART1->CR1 & USART_CR1_TXEIE)
    if (status & USART_SR_TXE)) {
        ..
    }
}


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Oct 31 2011, 10:34
Сообщение #5


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(AHTOXA @ Oct 31 2011, 12:55) *
Можно сначала проверять состояние разрешения/запрета прерываний от TXE, (если каждый раз проверять наличие символов на передачу накладно):
Можно так, только всё равно третье условие в обработчике появляется.
А можно и так (и из-за tail-chaining на cm3 будет работать очень даже оптимально и при одновременном приходе RX и TX прерываний):
Код
static __inline void uart_isr(uart_t* const uart)
{
    uint_fast16_t status = uart->sfr->SR;

    if (status & USART_FLAG_RXNE)        // if RX data_reg isn't empty (auto-clr by reading data_reg)
    {  
        uart_rx_isr(uart, status);
    }
    else if (status & USART_FLAG_TXE)      // if TX data_reg is empty (auto-clr by writing data_reg)
    {
        uart_tx_isr(uart);
    }
}


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Oct 31 2011, 11:08
Сообщение #6


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Сдаётся мне, что и с tail-chaining-ом будет проигрыш варианту с тремя проверкамиsm.gif
Но так красивее, да.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Oct 31 2011, 11:12
Сообщение #7


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(AHTOXA @ Oct 31 2011, 15:08) *
Сдаётся мне, что и с tail-chaining-ом будет проигрыш варианту с тремя проверками sm.gif

Да но одновременный приход TX+RX прерываний скорее исключение чем правило, мне так думаетсяsm.gif


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Apr 5 2013, 14:23
Сообщение #8


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Вот уже несколько лет работаю с STM32 и его различной периферией.
А сейчас понадобился RS485 и модбас. Ну думаю раз плюнуть. Делал такое на AVR...
Состряпал я программный модуль-драйвер UARTа с режимом RS485 и словил непонятное поведение.
При отправке байта получаю его ЭХО (loop-back режим). Иногда такое нужно но не сейчас.
Вообщем вопрос... Это я чего-то не понимаю или так и должно быть (что сильно вряд ли).
Код
static INLINE void rs485_set_txe_int(rs485_handle_t* const rs, int x)
{
    if (x)  rs->sfr->CR1 |=  USART_CR1_TXEIE;
    else    rs->sfr->CR1 &= ~USART_CR1_TXEIE;
}

static INLINE void rs485_set_txc_int(rs485_handle_t* const rs, int x)
{
    if (x)  rs->sfr->CR1 |=  USART_CR1_TCIE;
    else    rs->sfr->CR1 &= ~USART_CR1_TCIE;
}

static INLINE void rs485_txe_isr(rs485_handle_t* const rs)
{
    *rs->de = 1;
    if (!fifo_get_byte(&rs->fifo.tx, (uint8_t*)&rs->sfr->DR))
    {
        rs485_set_txc_int(rs, 1);
        rs485_set_txe_int(rs, 0);
    }
}

static INLINE void rs485_txc_isr(rs485_handle_t* const rs)
{
    rs->sfr->SR = (uint16_t)~USART_SR_TC; // clr pending txc
    *rs->de = 0;
}

static INLINE void rs485_isr(rs485_handle_t* const rs)
{
    uint_fast16_t status = rs->sfr->SR;
    if (status & USART_SR_RXNE)      // if RX data_reg isn't empty (auto-clr by reading data_reg)
    {  
        rs485_rx_isr(rs, status);
    }
    else if (status & USART_SR_TC)   // if TC  tx-complete flag (needs to be clr by user)
    {
        rs485_txc_isr(rs);
    }
    else if (status & USART_SR_TXE)  // if TX data_reg is empty (auto-clr by writing data_reg)
    {
        rs485_txe_isr(rs);
    }
}

void rs485_putc(rs485_handle_t* const rs, char c)
{
    fifo_put_byte(&rs->fifo.tx, (uint8_t)c);
    rs485_set_txe_int(rs, 1);
}

int rs485_init(rs485_handle_t* const rs, uint32_t br, uint_fast8_t data_bits, char parity, uint_fast8_t stop_bits, volatile uint32_t* de)  // br-(7,8,9)-(n,e,o)-(1,2)
{
    USART_DeInit(rs->sfr);

    rs->de = de;

    data_bits += (parity=='e' || parity=='o'); // in stm32 USART data_bits means data_bits+parity_bit

    if (stop_bits==2 && data_bits==7)
    {
//        stop_bits--;  // 1
//        data_bits++;  // 8

        return 0; //todo: 7bit + 2SB convert to 8bit and 1SB and put manually SB into Bit7=1 before send and
    }

    if (   (br>=9600UL && br<=115200UL)       // guard_time timits
        && (data_bits==8U || data_bits==9U))  // 7bit w/o parity is forbiden !!!
    {
        rs485_init_rcc(rs);

        rs485_flush(rs);

        USART_InitTypeDef USART_InitStruct =
        {
            .USART_BaudRate            = br,
            .USART_WordLength          = (data_bits==9U)? USART_WordLength_9b : USART_WordLength_8b,
            .USART_StopBits            = (stop_bits==2U)? USART_StopBits_2 : USART_StopBits_1,
            .USART_Parity              = (parity=='e')? USART_Parity_Even : ((parity=='o')? USART_Parity_Odd : USART_Parity_No),
            .USART_Mode                = USART_Mode_Tx | USART_Mode_Rx,
            .USART_HardwareFlowControl = USART_HardwareFlowControl_None
        };

        USART_Init(rs->sfr, &USART_InitStruct);

        USART_ITConfig(rs->sfr, USART_IT_RXNE, ENABLE); // rx-interrupt only allowed by default

        USART_Cmd(rs->sfr, ENABLE);

        rs485_init_nvic(rs); // enable irq

        return 1;
    }

    return 0;
}


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Apr 5 2013, 19:09
Сообщение #9


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Что-то я не вижу управления направлением передачи.
Если вы не отключаете RE, то эхо должно приниматься, по крайней мере это так на всех драйверах RS485, с которыми я работал.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- ierofant   UART STM32   Oct 27 2011, 22:12
- - AHTOXA   Вместо прерывания по окончанию передачи удобнее ис...   Oct 28 2011, 04:32
|- - ierofant   Цитата(AHTOXA @ Oct 28 2011, 07:32) Вмест...   Oct 28 2011, 19:30
|- - Apollo   Цитата(ierofant @ Oct 28 2011, 22:30) Сре...   Oct 31 2011, 07:17
- - Tolyaha   Цитата(ierofant @ Oct 28 2011, 01:12) Нео...   Oct 28 2011, 06:22
- - Apollo   Дружище, а подскажите какая у вас среда разработки...   Oct 28 2011, 11:20
- - kan35   STM32F10x_StdPeriph использую уже пару лет, с 1 по...   Oct 29 2011, 09:07
||- - demiurg_spb   Цитата(AHTOXA @ Apr 5 2013, 23:09) Что-то...   Apr 6 2013, 07:14
|- - kolobok0   Цитата(demiurg_spb @ Apr 5 2013, 18:23) ....   Apr 5 2013, 19:20
- - Apollo   Повторил пример из видеоурока. Всё заработало. Поп...   Oct 31 2011, 09:27


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd June 2025 - 08:18
Рейтинг@Mail.ru


Страница сгенерированна за 0.01505 секунд с 7
ELECTRONIX ©2004-2016