Easyelectronics.ru

Электроника для всех
Текущее время: 24 окт 2020, 20:42

Часовой пояс: UTC + 5 часов



JLCPCB – Прототипы печатных плат за $2/5шт. два слоя. $5/5шт. четыре слоя
Крупнейший производитель печатных плат и прототипов. Более 600000 клиентов и свыше 10000 заказов в день!
Получите скидку на почтовую отправку при первом заказе в JLCPCB!

Начать новую тему Ответить на тему  [ Сообщений: 13 ] 
Автор Сообщение
 Заголовок сообщения: stm32 uart rs485
СообщениеДобавлено: 21 апр 2012, 11:08 
Только пришел

Зарегистрирован: 21 апр 2012, 11:05
Сообщения: 7
ситуация такая, нужно написать прерывание на прием в буфер и в зависимости от значения первого байта в ответ отправить другой буфер (около 20 байт). ниже кусок прерывания для одного байта. как его переделать для буфера??? помогите!!!



Код:
[size=85]void USART1_IRQHandler(void)
{
    //Receive Data register not empty interrupt
      if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
   {
       rx=1;
       USART_ClearITPendingBit(USART1, USART_IT_RXNE);
       tmp=USART_ReceiveData (USART1);

   }
      //Transmission complete interrupt
      if(USART_GetITStatus(USART1, USART_IT_TC) != RESET)
      {
          USART_ClearITPendingBit(USART1, USART_IT_TC);
          tx_end=1;
      }[/size][size=85][/size]


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: stm32 uart rs485
СообщениеДобавлено: 21 апр 2012, 23:59 
Старожил

Зарегистрирован: 25 апр 2010, 10:13
Сообщения: 1927
Откуда: Томск
Вот для буфера, из примеров Keil'а:
Код:
/* Private define ------------------------------------------------------------*/
#define TxBufferSize   (countof(TxBuffer) - 1)
#define RxBufferSize   0x20

/* Private macro -------------------------------------------------------------*/
#define countof(a)   (sizeof(a) / sizeof(*(a)))

/* Private variables ---------------------------------------------------------*/
u8 TxBuffer[] = "\n\rUSART Hyperterminal Interrupts Example: USART-Hyperterminal\
communication using Interrupt\n\r";
u8 RxBuffer[RxBufferSize];
u8 NbrOfDataToTransfer = TxBufferSize;
u8 NbrOfDataToRead = RxBufferSize;
u8 TxCounter = 0;
u16 RxCounter = 0;


/*******************************************************************************
* Function Name  : USART1_IRQHandler
* Description    : This function handles USART1 global interrupt request.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void USART1_IRQHandler(void)
{
  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
  {
    /* Read one byte from the receive data register */
    RxBuffer[RxCounter++] = (USART_ReceiveData(USART1) & 0x7F);         

    if(RxCounter == NbrOfDataToRead)
    {
      /* Disable the USART Receive interrupt */
      USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
    }
  }

  if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
  {   
    /* Write one byte to the transmit data register */
    USART_SendData(USART1, TxBuffer[TxCounter++]);                   

    if(TxCounter == NbrOfDataToTransfer)
    {
      /* Disable the USART1 Transmit interrupt */
      USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
    }   
  }
}

вот описание:
Example description
===================
This example provides a description of how to use the USART1 Transmit and Receive
interrupts to communicate with the hyperterminal.

First, the USART1 sends the TxBuffer to the hyperterminal and still waiting for
a string from the hyperterminal that you must enter.
The string that you have entered is stored in the RxBuffer array. The receive
buffer have a RxBufferSize bytes as maximum (the reception is stopped when this
maximum receive value is reached).

_________________
Какое небо голубое....(с) лиса Алиса


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: stm32 uart rs485
СообщениеДобавлено: 22 апр 2012, 12:02 
Только пришел

Зарегистрирован: 21 апр 2012, 11:05
Сообщения: 7
hardegor писал(а):
Вот для буфера, из примеров Keil'а:
Код:
/* Private define ------------------------------------------------------------*/
#define TxBufferSize   (countof(TxBuffer) - 1)
#define RxBufferSize   0x20

/* Private macro -------------------------------------------------------------*/
#define countof(a)   (sizeof(a) / sizeof(*(a)))

/* Private variables ---------------------------------------------------------*/
u8 TxBuffer[] = "\n\rUSART Hyperterminal Interrupts Example: USART-Hyperterminal\
communication using Interrupt\n\r";
u8 RxBuffer[RxBufferSize];
u8 NbrOfDataToTransfer = TxBufferSize;
u8 NbrOfDataToRead = RxBufferSize;
u8 TxCounter = 0;
u16 RxCounter = 0;


/*******************************************************************************
* Function Name  : USART1_IRQHandler
* Description    : This function handles USART1 global interrupt request.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void USART1_IRQHandler(void)
{
  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
  {
    /* Read one byte from the receive data register */
    RxBuffer[RxCounter++] = (USART_ReceiveData(USART1) & 0x7F);         

    if(RxCounter == NbrOfDataToRead)
    {
      /* Disable the USART Receive interrupt */
      USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
    }
  }

  if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
  {   
    /* Write one byte to the transmit data register */
    USART_SendData(USART1, TxBuffer[TxCounter++]);                   

    if(TxCounter == NbrOfDataToTransfer)
    {
      /* Disable the USART1 Transmit interrupt */
      USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
    }   
  }
}

вот описание:
Example description
===================
This example provides a description of how to use the USART1 Transmit and Receive
interrupts to communicate with the hyperterminal.

First, the USART1 sends the TxBuffer to the hyperterminal and still waiting for
a string from the hyperterminal that you must enter.
The string that you have entered is stored in the RxBuffer array. The receive
buffer have a RxBufferSize bytes as maximum (the reception is stopped when this
maximum receive value is reached).



спасибо!!! с приемом все понятно!!! прерывание осуществляется в случае прихода очередного байта и записывается в буфер. а с передатчиком не понятно... в каком случае возникает это прерывание (или как запустить передачу)...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: stm32 uart rs485
СообщениеДобавлено: 22 апр 2012, 19:02 
Старожил

Зарегистрирован: 25 апр 2010, 10:13
Сообщения: 1927
Откуда: Томск
прерывание возникает от устройства UART,
а чтобы узнать кто в UART его вызвал надо проверять флаги:
при приёме байта: if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
при окончании передачи байта if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)

А чтобы начать передачу надо просто послать байт USART_SendData(USART1, TxBuffer[TxCounter++]);

Но если у тебя RS-485 надо еще переключать прием/передачу на трансивере.

_________________
Какое небо голубое....(с) лиса Алиса


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: stm32 uart rs485
СообщениеДобавлено: 22 апр 2012, 20:09 
Только пришел

Зарегистрирован: 21 апр 2012, 11:05
Сообщения: 7
hardegor писал(а):
прерывание возникает от устройства UART,
а чтобы узнать кто в UART его вызвал надо проверять флаги:
при приёме байта: if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
при окончании передачи байта if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)

А чтобы начать передачу надо просто послать байт USART_SendData(USART1, TxBuffer[TxCounter++]);

Но если у тебя RS-485 надо еще переключать прием/передачу на трансивере.



т.е количество входов в прерывание будет меньшее на 1 чем чем размер буфера для передачи....


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: stm32 uart rs485
СообщениеДобавлено: 22 апр 2012, 21:07 
Старожил

Зарегистрирован: 25 апр 2010, 10:13
Сообщения: 1927
Откуда: Томск
dimka2001 писал(а):
т.е количество входов в прерывание будет меньшее на 1 чем чем размер буфера для передачи....

почему?

_________________
Какое небо голубое....(с) лиса Алиса


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: stm32 uart rs485
СообщениеДобавлено: 22 апр 2012, 23:25 
Только пришел

Зарегистрирован: 21 апр 2012, 11:05
Сообщения: 7
hardegor писал(а):
dimka2001 писал(а):
т.е количество входов в прерывание будет меньшее на 1 чем чем размер буфера для передачи....

почему?


потому что как вы сказали первый байт отсылается USART_SendData(USART1, TxBuffer[TxCounter++]); а потом работает прерывание!!!


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: stm32 uart rs485
СообщениеДобавлено: 22 апр 2012, 23:40 
Старожил

Зарегистрирован: 25 апр 2010, 10:13
Сообщения: 1927
Откуда: Томск
Это пример! Тебе надо разобраться как он работает и применить полученные знания к своей задаче.
Ты вообще-то понимаешь код который был в примере? У меня есть сомнения......

Что происходит при передачи байта:
1. функция USART_SendData() записывает 1(один) байт в регистр DR UART.
2. UART начинает передавать этот байт в провод
3. после окончания передачи UART вызывает прерывание USART1_IRQHandler()
4. в прерывании опять вызывается функция USART_SendData(), см. пункт 1
5. как только кончится счетчик TxCounter, после проверки if(TxCounter == NbrOfDataToTransfer) отключается прерывание.

Да, вдруг ты не знаешь - конструкция "TxCounter++" увеличивает переменную TxCounter на 1.

_________________
Какое небо голубое....(с) лиса Алиса


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: stm32 uart rs485
СообщениеДобавлено: 23 апр 2012, 00:17 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 14 июл 2011, 01:36
Сообщения: 72
Откуда: Москва
hardegor писал(а):
А чтобы начать передачу надо просто послать байт USART_SendData(USART1, TxBuffer[TxCounter++]);
.....
1. функция USART_SendData() записывает 1(один) байт в регистр DR UART.
2. UART начинает передавать этот байт в провод
3. после окончания передачи UART вызывает прерывание USART1_IRQHandler()

Малость поправлю. Если разговор идет о прерывании по флагу TXE, то последовательность проще:

В прерывании проверяем источник прерывания и если это TXE, то отправляем в DR новый байт. Если при этом мы отправили последний байт, то прерывание запрещаем.
Для начала отправки достаточно просто разрешить прерывание по TXE и программа сразу уйдет в прерывани: буфер же пустой.
Флаг TXE указывает, что буфер передачи пуст, но не указывает, что пуст и сдвиговый регистр. Поэтому в случае RS485 надо так-же следить за флагом TC, так как только по нему можно отключать передатчик трансивера.

ЗЫЖ Но отправку проще с DMA сделать :)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: stm32 uart rs485
СообщениеДобавлено: 23 апр 2012, 21:32 
Только пришел

Зарегистрирован: 21 апр 2012, 11:05
Сообщения: 7
md5sum писал(а):
hardegor писал(а):
А чтобы начать передачу надо просто послать байт USART_SendData(USART1, TxBuffer[TxCounter++]);
.....
1. функция USART_SendData() записывает 1(один) байт в регистр DR UART.
2. UART начинает передавать этот байт в провод
3. после окончания передачи UART вызывает прерывание USART1_IRQHandler()

Малость поправлю. Если разговор идет о прерывании по флагу TXE, то последовательность проще:

В прерывании проверяем источник прерывания и если это TXE, то отправляем в DR новый байт. Если при этом мы отправили последний байт, то прерывание запрещаем.
Для начала отправки достаточно просто разрешить прерывание по TXE и программа сразу уйдет в прерывани: буфер же пустой.
Флаг TXE указывает, что буфер передачи пуст, но не указывает, что пуст и сдвиговый регистр. Поэтому в случае RS485 надо так-же следить за флагом TC, так как только по нему можно отключать передатчик трансивера.

ЗЫЖ Но отправку проще с DMA сделать :)



спасибо!!!
а как сделать с dma


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: stm32 uart rs485
СообщениеДобавлено: 23 апр 2012, 22:05 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 14 июл 2011, 01:36
Сообщения: 72
Откуда: Москва
Например так:
Инициализация
Код:
   usart_init.USART_BaudRate=115200UL;
   usart_init.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
   usart_init.USART_Mode=USART_Mode_Tx;
   usart_init.USART_Parity=USART_Parity_No;
   usart_init.USART_StopBits=USART_StopBits_1;
   usart_init.USART_WordLength=USART_WordLength_8b;
   USART_Init(USART1,&usart_init);

   dma_init.DMA_BufferSize=0;
   dma_init.DMA_DIR=DMA_DIR_PeripheralDST;
   dma_init.DMA_M2M=DMA_M2M_Disable;
   dma_init.DMA_MemoryBaseAddr=(uint32_t)&usartTXBuff;
   dma_init.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
   dma_init.DMA_MemoryInc=DMA_MemoryInc_Enable;
   dma_init.DMA_Mode=DMA_Mode_Normal;
   dma_init.DMA_PeripheralBaseAddr=(uint32_t)&(USART1->DR);
   dma_init.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
   dma_init.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
   dma_init.DMA_Priority=DMA_Priority_High;
   DMA_Init(USART_DMA_CH_TX,&dma_init);
   USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
   USART_Cmd(USART1,ENABLE);

Функция отправки
Код:
void send_str_with_dma(const char * p1) {
      /*ждем завершения предыдущей передачи */
   while (DMA_GetCurrDataCounter(DMA1_Channel4));
      /*DISABLE обязательно! */
   DMA_Cmd(DMA1_Channel4,DISABLE);
   strncpy(usartTXBuff,p1,80);
      /*указываем сколько отправлять*/
   DMA_SetCurrDataCounter(DMA1_Channel4,strlen(p1));
      /*запускаем отправку - DMA отправит указанное кол-во байт*/
   DMA_Cmd(DMA1_Channel4,ENABLE);
}


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: stm32 uart rs485
СообщениеДобавлено: 24 апр 2012, 21:15 
Только пришел

Зарегистрирован: 21 апр 2012, 11:05
Сообщения: 7
md5sum писал(а):
Например так:
Инициализация
Код:
   usart_init.USART_BaudRate=115200UL;
   usart_init.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
   usart_init.USART_Mode=USART_Mode_Tx;
   usart_init.USART_Parity=USART_Parity_No;
   usart_init.USART_StopBits=USART_StopBits_1;
   usart_init.USART_WordLength=USART_WordLength_8b;
   USART_Init(USART1,&usart_init);

   dma_init.DMA_BufferSize=0;
   dma_init.DMA_DIR=DMA_DIR_PeripheralDST;
   dma_init.DMA_M2M=DMA_M2M_Disable;
   dma_init.DMA_MemoryBaseAddr=(uint32_t)&usartTXBuff;
   dma_init.DMA_MemoryDataSize=DMA_MemoryDataSize_Byte;
   dma_init.DMA_MemoryInc=DMA_MemoryInc_Enable;
   dma_init.DMA_Mode=DMA_Mode_Normal;
   dma_init.DMA_PeripheralBaseAddr=(uint32_t)&(USART1->DR);
   dma_init.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
   dma_init.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
   dma_init.DMA_Priority=DMA_Priority_High;
   DMA_Init(USART_DMA_CH_TX,&dma_init);
   USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
   USART_Cmd(USART1,ENABLE);

Функция отправки
Код:
void send_str_with_dma(const char * p1) {
      /*ждем завершения предыдущей передачи */
   while (DMA_GetCurrDataCounter(DMA1_Channel4));
      /*DISABLE обязательно! */
   DMA_Cmd(DMA1_Channel4,DISABLE);
   strncpy(usartTXBuff,p1,80);
      /*указываем сколько отправлять*/
   DMA_SetCurrDataCounter(DMA1_Channel4,strlen(p1));
      /*запускаем отправку - DMA отправит указанное кол-во байт*/
   DMA_Cmd(DMA1_Channel4,ENABLE);
}


можно чуть пояснить как это работает и как будет выглядеть прием???


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: stm32 uart rs485
СообщениеДобавлено: 24 апр 2012, 21:40 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 14 июл 2011, 01:36
Сообщения: 72
Откуда: Москва
Работает просто:
При инициализации настроили DMA на копирование байтов из памяти в регистр данных USART.
Кстати - буфер не обязательно статичный - можно его менять по ходу программы.

Для отправки загоняем нужные данные в буфер, указываем DMA сколько всего отправить и включаем DMA. Он будет запихивать в регистр данных USART новый байт как только тот освободится.

Преимущества: ядро не отвлекается на пересылку каждого байта - не надо каждый раз сохранять регистры, стек и адрес возврата при входе в прерывание и восстанавливать при выходе из прерывания.

dimka2001 писал(а):
и как будет выглядеть прием???
А про прием я не говорил :)
Прием ничем отличатся от обычного не будет...
Можно конечно DMA и на прием прикрутить, но сразу встает проблема как обрабатывать данные переменной длинны и как обрабатывать ошибки при приеме....


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 13 ] 


Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB