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

 
 
 
Reply to this topicStart new topic
> STM32, USART на прерываниях и очередях, проблемы с передачей, Портится очередь
asdus
сообщение Jan 20 2012, 14:14
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 21
Регистрация: 28-04-08
Из: Раменсбург
Пользователь №: 37 126



Есть проектик, STM32F10*, FreeRTOS 7.1.0
USART реализован на прерываниях и очередях, по примеру из FreeRTOS
С приемом все хорошо, а вот при передаче через некоторое время работы "портятся" данные. Свиду - сдвигаются указатели на голову и хвост в очереди.
В данный момент пройтись отладчиком возможности нет.
Выписал код в минипрогу, ошибка повторяется. Через некоторое, рандомное время, вместо "Hello World!\n" становится, например "rlWorld!\no Wo", потом еще что-нибудь и т.д.
CODE
#include "stm32f10x.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

static xQueueHandle USART1_TxQueue;

uint8_t USART1_PutChar( uint8_t cOutChar )
{
uint8_t xReturn;

if( xQueueSend( USART1_TxQueue, &cOutChar, 10 ) == pdPASS )
{
xReturn = pdPASS;
USART_ITConfig( USART1, USART_IT_TXE, ENABLE );
}
else
{
xReturn = pdFAIL;
}

return xReturn;
}

void USART1_PutString( const uint8_t * pcString )
{
uint8_t *pxNext;

pxNext = ( uint8_t * ) pcString;
while( *pxNext )
{
USART1_PutChar( *pxNext );
pxNext++;
}
}

void HelloWorldTask(void *pvParameters)
{
for(;;)
{
USART1_PutString("Hello World!\n");
vTaskDelay( 1000 );
}
}

void USART1_IRQHandler( void )
{
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
uint8_t cChar;

if( USART_GetITStatus( USART1, USART_IT_TXE ) == SET )
{
if( xQueueReceiveFromISR( USART1_TxQueue, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE )
{
USART_SendData( USART1, cChar );
}
else
{
USART_ITConfig( USART1, USART_IT_TXE, DISABLE );
}
}

portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}

int main(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;

/* Enable USART1 GPIO clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);

/* Enable UART1 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);

/* Enable the USART1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_LOWEST_INTERRUPT_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

/* Configure USART1 Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

/* Configure USART1 Rx as input floating */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

/* Configure USART1 parameters 115200 8n1 noHW Tx+Rx*/
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);

/* Create TxQueue for USART1 */
USART1_TxQueue = xQueueCreate( 256, ( unsigned portBASE_TYPE ) sizeof( uint8_t ) );

USART1_PutString("Program started!\n");
USART1_PutString("================\n");

xTaskCreate(HelloWorldTask, "HelWor", configMINIMAL_STACK_SIZE, NULL, 2, NULL);

vTaskStartScheduler();

for(;;)
{
}
}


Сообщение отредактировал asdus - Jan 20 2012, 14:16


--------------------
Секс - классная штука. Как ни крути...
Go to the top of the page
 
+Quote Post
kan35
сообщение Jan 21 2012, 15:58
Сообщение #2


Знающий
****

Группа: Участник
Сообщений: 537
Регистрация: 22-02-06
Пользователь №: 14 594



Во первых, вы начинаете использовать queue до старта шедулера, это грубая ошибка.
И на сколько мне помнится надо сбрасывать соответствующий pending bit при обработке ISR
Go to the top of the page
 
+Quote Post
asdus
сообщение Jan 22 2012, 19:53
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 21
Регистрация: 28-04-08
Из: Раменсбург
Пользователь №: 37 126



Цитата(kan35 @ Jan 21 2012, 19:58) *
Во первых, вы начинаете использовать queue до старта шедулера, это грубая ошибка.
Спасибо за подсказку. В оригинальной программе такого небыло, прибил в тестовой.

Цитата(kan35 @ Jan 21 2012, 19:58) *
И на сколько мне помнится надо сбрасывать соответствующий pending bit при обработке ISR
GetITStatus уже давно сбрасывает соответствующий ITPendingBit. На всякий случай добавил в тестовую прогу.

Запустил тесты, ждем-с...
Долго ждать не пришлось, ошибка сохранилась. К слову, с передачей, реализованной на тех-же прерываниях и очередях проблем нет, как и с передачей без использования очередей...

Сообщение отредактировал asdus - Jan 22 2012, 19:56


--------------------
Секс - классная штука. Как ни крути...
Go to the top of the page
 
+Quote Post
kan35
сообщение Jan 23 2012, 06:56
Сообщение #4


Знающий
****

Группа: Участник
Сообщений: 537
Регистрация: 22-02-06
Пользователь №: 14 594



Смущает вот что:
бит TXE выставляется когда
Цитата
TXE: Transmit data register empty
This bit is set by hardware when the content of the TDR register has been transferred into
the shift register.

Таким образом при первой записи в очередь прерывание возникнет ДВАЖДЫ, но при втором входе очередь будет пустой. Может быть не это вызывает ваш глюк, однако обратите внимание на это.

Возможно проблемы с настройкой прерываний. Неплохо было бы посмотреть как freertos сконфигурирована.
Go to the top of the page
 
+Quote Post
asdus
сообщение Jan 24 2012, 08:04
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 21
Регистрация: 28-04-08
Из: Раменсбург
Пользователь №: 37 126



Цитата(kan35 @ Jan 23 2012, 10:56) *
Смущает вот что:
бит TXE выставляется когда
Код
TXE: Transmit data register empty
This bit is set by hardware when the content of the TDR register has been transferred into the shift register.
Таким образом при первой записи в очередь прерывание возникнет ДВАЖДЫ, но при втором входе очередь будет пустой. Может быть не это вызывает ваш глюк, однако обратите внимание на это.
Это нормально, обрабатывается ;)

Цитата(kan35 @ Jan 23 2012, 10:56) *
Возможно проблемы с настройкой прерываний. Неплохо было бы посмотреть как freertos сконфигурирована.
Проблема была решена.
Действительно, она была в настройке прерываний. Конкретно: порт FreeRTOS под STM32 требует следующей настройки:
Код
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
Почему он не делает это сам - непонятно. После выполнения этой команды все стало работать как должно.


--------------------
Секс - классная штука. Как ни крути...
Go to the top of the page
 
+Quote Post
Bass
сообщение Jan 25 2012, 09:48
Сообщение #6


Участник
*

Группа: Свой
Сообщений: 66
Регистрация: 5-08-10
Из: Томск
Пользователь №: 58 761



С позволения ТС, задам вопрос здесь, чтобы темы не плодить.
Начал осваивать FreeRTOS, и споткнулся на таком месте:
создаю задачу "отложенного прерывания", которая должна отрабатывать после получения байта во USART'у. Использую для этого семафор
Код
xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR( USART_RxSemaphore, &xHigherPriorityTaskWoken );
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );


Код самой задачи:
Код
void USART_RX_TaskHandler( void *params ) {
    for(;; ) {
        xSemaphoreTake( USART_RxSemaphore, portMAX_DELAY );                // ждем семафора

        USART_puts("byte recieved\r\n");
    }
}

и код создания задачи:
Код
#define USART_RX_TASKHDL_PRIORITY    (configMAX_PRIORITIES-1)

// семафор для задачи получения данных по USART
vSemaphoreCreateBinary( USART_RxSemaphore );
if ( USART_RxSemaphore != NULL ) {
    xTaskCreate(
        USART_RX_TaskHandler,
        (signed char *) "RX handler task",
        USART_RX_TASKHDL_STACK,
        NULL,
        USART_RX_TASKHDL_PRIORITY,
        NULL
    );
}

Проблема в том, что при запуске шедулера первый раз выполняется задача USART_RX_TaskHandler, т.е. не останавливается на xSemaphoreTake (хотя по логике вроде как должна), а потом уже выполняется после "пинка" из прерывания.
Подскажите это нормально или я где-то накосячил?

Сообщение отредактировал Bass - Jan 25 2012, 09:51
Go to the top of the page
 
+Quote Post
Gunner
сообщение Jan 25 2012, 14:38
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 99
Регистрация: 23-06-04
Из: Kiev
Пользователь №: 146



QUOTE (Bass @ Jan 25 2012, 13:48) *
Проблема в том, что при запуске шедулера первый раз выполняется задача USART_RX_TaskHandler, т.е. не останавливается на xSemaphoreTake (хотя по логике вроде как должна), а потом уже выполняется после "пинка" из прерывания.
Подскажите это нормально или я где-то накосячил?

Я тоже только еще изучаю FreeRTOS. Насколько я понял, семафор, как только создан, сразу становится доступен. Поэтому задача USART_RX_TaskHandler сразу захватывает его. Так что это нормально.
Go to the top of the page
 
+Quote Post
MALLOY2
сообщение Jan 25 2012, 16:08
Сообщение #8


Знающий
****

Группа: Validating
Сообщений: 838
Регистрация: 31-01-05
Пользователь №: 2 317



Есть такая беда у FreeRTOS нельзя при создании семафора задать его состояние. Я выкрутился созданием такого макроса:

Код
#define osSemNew(Sem,State,Name)\
do\
{\
  Sem = xQueueCreate( ( unsigned portBASE_TYPE ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH );\
  if (Sem!=NULL)\
  {\
    vQueueAddToRegistry(Sem,(signed char*)Name);\
    if((State))\
    {\
      xSemaphoreGive( Sem );\
    }\
  }\
}while(0)\
Go to the top of the page
 
+Quote Post
Bass
сообщение Jan 25 2012, 18:11
Сообщение #9


Участник
*

Группа: Свой
Сообщений: 66
Регистрация: 5-08-10
Из: Томск
Пользователь №: 58 761



Ага, нашел сам макрос vSemaphoreCreateBinary, в котором видно, что после создания он сразу отдается:
Код
xSemaphoreGive( ( xSemaphore ) );

Тогда я думаю проще при инициализации сразу после создания взять семафор, тогда задача не выполнится до повторной выдачи уже в прерывании.
Go to the top of the page
 
+Quote Post
diwil
сообщение Jan 27 2012, 07:37
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 366
Регистрация: 5-09-06
Из: Санкт-Петербург
Пользователь №: 20 107



ээээ... как показывает практика - использование очередей в уарте не есть самый лучший способ передачи данных по нескольким причинам
- необходимо распределеить память под очередь
- передача одного байта вызывает большой overhead
- еще какие-то-там-я-и-не-помню.

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

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

Код для stm32l152 ниже.

Может кому пригодится еще. у меня работает в оч критической задаче.

Код
#include "stm32l1xx.h"
#include "stm32l1xx_rcc.h"


#include "stm32l1xx_tim.h"
#include "stm32l1xx_gpio.h"
#include "stm32l1xx_spi.h"
#include "stm32l1xx_dma.h"
#include "stm32l1xx_usart.h"

#include "misc.h"

#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
#include "queue.h"

#define  USART2_RX_BUF_SIZE    128
static char usart2_rx_buffer[USART2_RX_BUF_SIZE];


xSemaphoreHandle xSemaphoreUSART2;

void
usart2_init(void)
{
    USART_InitTypeDef        USART_InitStructure;
    GPIO_InitTypeDef        GPIO_InitStructure;
    NVIC_InitTypeDef        NVIC_InitStructure;
    DMA_InitTypeDef          DMA_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

    USART_InitStructure.USART_BaudRate = 57600;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

    USART_Init(USART2, &USART_InitStructure);

    USART_DMACmd(USART2, USART_DMAReq_Tx | USART_DMAReq_Rx, ENABLE);


  /* Enable USART1 IDLE line interrupts because all others are handeled via DMA */
    USART_ITConfig(USART2, USART_IT_IDLE , ENABLE);

      GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2 );
      GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2 );

  /* Configure USART1 Tx, RX (PA.02 PA.03) as alternate function push-pull */
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
      GPIO_Init(GPIOA, &GPIO_InitStructure);    


      /* Enable the USART1 Interrupt */
      NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 12;
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 12;
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      NVIC_Init(&NVIC_InitStructure);
    
    DMA_DeInit(DMA1_Channel6);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART2->DR;
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)usart2_rx_buffer;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize = USART2_RX_BUF_SIZE;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init(DMA1_Channel6, &DMA_InitStructure);


    USART_DMACmd(USART2, USART_DMAReq_Rx, ENABLE);

      NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel6_IRQn;
      NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 12;
      NVIC_InitStructure.NVIC_IRQChannelSubPriority = 11;
      NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
      NVIC_Init(&NVIC_InitStructure);

    /* Enable interrupts on channel 6 */
    DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE);
    DMA_ITConfig(DMA1_Channel6, DMA_IT_HT, ENABLE);

    vSemaphoreCreateBinary( xSemaphoreUSART2 );
    xSemaphoreTake( xSemaphoreUSART2, ( portTickType ) portMAX_DELAY );


    USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);

    

    USART2->SR = 0;
    DMA_Cmd(DMA1_Channel6, ENABLE);
      USART_Cmd(USART2, ENABLE);
}



int
usart2_send(void *buffer, int size)
{
    DMA_InitTypeDef          DMA_InitStructure;

       if(size > 65535)
        return -2;

//    if (DMA1_Channel7->CNDTR)
//        return -1;

    while(DMA1_Channel7->CNDTR);

    // now configure transmit line:
    // do not enable interrupts
    DMA_DeInit(DMA1_Channel7);
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART2->DR;
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)buffer;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_BufferSize = size;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

    DMA_Init(DMA1_Channel7, &DMA_InitStructure);
    DMA_Cmd(DMA1_Channel7, ENABLE);    

    return 0;
}

  
void USART2_IRQHandler(void)
{
  portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;    
  int statusreg = USART2->SR;
  char uart_messages;

  uart_messages = 0;


  if(statusreg & (1<<4) )   // IDLE. ONLY this interrupt is enabled!!!
  {
     uart_messages = 3;
     USART2->DR;      // dummy read to clear idle flag

  }
  
  if(uart_messages)
  {      
      xSemaphoreGiveFromISR( xSemaphoreUSART2, &xHigherPriorityTaskWoken );  
  }

  portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
}

void
DMA1_Channel6_IRQHandler(void)
{
    portBASE_TYPE xHigherPriorityTaskWoken;
    
    DMA1->IFCR = 7 << 20;    // clear DMA interrupt flags and continue

    xSemaphoreGiveFromISR( xSemaphoreUSART2, &xHigherPriorityTaskWoken );
    portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
}

static int  rx_read;

int
uart2_get_char(portTickType block_time)
{
    int res;

    while(1)
    {
        if (USART2_RX_BUF_SIZE - DMA1_Channel6->CNDTR != rx_read)
        {
            res = usart2_rx_buffer[rx_read];
            rx_read++;
            if(rx_read == USART2_RX_BUF_SIZE)
                rx_read = 0;
            return res & 0xff;
        }

        if (pdFALSE == xSemaphoreTake( xSemaphoreUSART2, ( portTickType ) block_time ))
            return -1;
    }
            
    return 0;
}
Go to the top of the page
 
+Quote Post
asdus
сообщение Jan 30 2012, 15:08
Сообщение #11


Участник
*

Группа: Участник
Сообщений: 21
Регистрация: 28-04-08
Из: Раменсбург
Пользователь №: 37 126



Обязательно перепишу на DMA, как только, так сразу :)
Для истории пишу свой код целиком, на неэффективных прерываниях и очередях :)
Как-нибудь при случае замеряю загрузку ЦП. Работает на STM32F100RB (STM32VLDISCOVERY)
И не забываем запустить шулдер до использования) хотя у меня работало и до включения, но не протестировано на стабильность.
CODE
#include <stm32f10x.h>
#include <FreeRTOS.h>
#include <queue.h>

static xQueueHandle MODBUS_RxQueue;
static xQueueHandle MODBUS_TxQueue;

void MODBUS_Init( void )
{
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;

/* Create Rx/Tx Queues */
MODBUS_RxQueue = xQueueCreate( 256, sizeof( uint32_t ) );
MODBUS_TxQueue = xQueueCreate( 256, sizeof( uint32_t ) );
/* Enable GPIOA clock (for USART1 TX=PA9, RX=PA10) */
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
/* Enable AFIO clock (for USART1 TX) */
RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO, ENABLE );
/* Enable UART1 clock */
RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1, ENABLE );
/* Select NVIC Preemption Priority Group 4 (for FreeRTOS) */
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
/* Enable the USART1 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_LOWEST_INTERRUPT_PRIORITY;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init( &NVIC_InitStructure );
/* Configure USART1 GPIO PINs (TX=PA9, RX=PA10) */
/* Configure USART1 Tx as alternate function push-pull */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init( GPIOA, &GPIO_InitStructure );
/* Configure USART1 Rx as input floating */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init( GPIOA, &GPIO_InitStructure );
/* Configure USART1 parameters 115200 8n1 noHW Tx+Rx*/
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init( USART1, &USART_InitStructure );
USART_ITConfig( USART1, USART_IT_RXNE, ENABLE );
USART_Cmd( USART1, ENABLE );
}

uint8_t MODBUS_GetChar( uint8_t *pcRxedChar )
{
if( xQueueReceive( MODBUS_RxQueue, pcRxedChar, 0 ) )
{
return pdTRUE;
}
else
{
return pdFALSE;
}
}

void MODBUS_PutString( const uint8_t * pcString )
{
uint8_t *pxNext;

pxNext = ( uint8_t * ) pcString;
while( *pxNext )
{
MODBUS_PutChar( *pxNext );
pxNext++;
}
}

uint8_t MODBUS_PutChar( uint8_t cOutChar )
{
uint8_t xReturn;

if( xQueueSend( MODBUS_TxQueue, &cOutChar, 10 ) == pdPASS )
{
xReturn = pdPASS;
USART_ITConfig( USART1, USART_IT_TXE, ENABLE );
}
else
{
xReturn = pdFAIL;
}

return xReturn;
}

void USART1_IRQHandler( void )
{
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
uint8_t cChar;

if( USART_GetITStatus( USART1, USART_IT_TXE ) == SET )
{
if( xQueueReceiveFromISR( MODBUS_TxQueue, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE )
{
USART_SendData( USART1, cChar );
}
else
{
USART_ITConfig( USART1, USART_IT_TXE, DISABLE );
}
}

if( USART_GetITStatus( USART1, USART_IT_RXNE ) == SET )
{
cChar = USART_ReceiveData( USART1 );
xQueueSendFromISR( MODBUS_RxQueue, &cChar, &xHigherPriorityTaskWoken );
}

portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}


--------------------
Секс - классная штука. Как ни крути...
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 20th July 2025 - 05:56
Рейтинг@Mail.ru


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