文章
博客 网店

 FreeRTOS信号量的应用


信号量分二进制型和互斥型两种,主要区别就是互斥型信号量只能由申请信号的任务才可以释放信号量,而二进制型的没有这个限制,需要互斥型信号量需要多付出1K~2K的程序空间,在FreeRTOSConfig.h文件中将下面这个配置设置成1可使用互斥信号量了。
#define configUSE_MUTEXES           0 //是否使用互斥信号量

但感觉这个不知道什么场合会用到,还是来看看用二进制信号量互斥访问串口资源的办法吧:

//UART3 队列              
static xQueueHandle xRxQueue3;
static xQueueHandle xTxQueue3;
//信号量
xSemaphoreHandle xSemaphoreUart3;

//UART3初始化
void Uart3Init(unsigned portLONG ulWantedBaud, unsigned portBASE_TYPE uxBufferLength )
{
  USART_InitTypeDef USART_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;

  xRxQueue3 = xQueueCreate( uxBufferLength, ( unsigned portBASE_TYPE ) sizeof(uint8_t) );
  xTxQueue3 = xQueueCreate( uxBufferLength + 1, ( unsigned portBASE_TYPE ) sizeof(uint8_t) );
  vSemaphoreCreateBinary( xSemaphoreUart3 ); //创建二值信号量 
  //Enable clock 
  RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART3, ENABLE );  

  //Configure USART3 Rx (PB11) as input floating 
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init( GPIOB, &GPIO_InitStructure );
  
  //Configure USART3 Tx (PB10) as alternate function push-pull
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

  GPIO_Init( GPIOB, &GPIO_InitStructure );

  //中断设置
  NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;

  USART_InitStructure.USART_BaudRate = ulWantedBaud;
  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( USART3, &USART_InitStructure );
  
  USART_ITConfig( USART3, USART_IT_RXNE, ENABLE );  //接收中断使能
  
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = configLIBRARY_KERNEL_INTERRUPT_PRIORITY;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init( &NVIC_InitStructure );
  
  USART_Cmd( USART3, ENABLE );
}

//UART3
signed portBASE_TYPE Uart3ReadByte(uint8_t *pcRxedChar,portTickType xBlockTime )
{
  if(xQueueReceive( xRxQueue3, pcRxedChar, xBlockTime ))
    return pdTRUE;
  else  
    return pdFALSE;
}

//UART3发送功能
void Uart3Send(uint8_t *buf,int len)
{
  int i;

  if(xSemaphoreTake( xSemaphoreUart3, 100) == pdFALSE)   //获取信号量
  {
    xSemaphoreGive( xSemaphoreUart3 ); //强制释放信号量  
    return ; //获取信号量失败
  }

  for(i=0;i<len;i++)
     xQueueSend( xTxQueue3, buf+i, portMAX_DELAY );  

  USART_ITConfig( USART3, USART_IT_TXE, ENABLE );  //中断使能
}


//UART3中断函数
void vUART3InterruptHandler( void )
{
  portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
  portCHAR cChar;

  if( USART_GetITStatus( USART3, USART_IT_TXE ) == SET )
  {
    if( xQueueReceiveFromISR( xTxQueue3, &cChar, &xHigherPriorityTaskWoken ) == pdTRUE )
      USART_SendData( USART3, cChar );
    else
    {
      USART_ITConfig( USART3, USART_IT_TXE, DISABLE );
      //xSemaphoreGive( xSemaphoreUart3 ); //释放信号量
      xSemaphoreGiveFromISR( xSemaphoreUart3, &xHigherPriorityTaskWoken );      
    }
  }
  
  if( USART_GetITStatus( USART3, USART_IT_RXNE ) == SET )
  {
    cChar = USART_ReceiveData( USART3 );
    xQueueSendFromISR( xRxQueue3, &cChar, &xHigherPriorityTaskWoken );
  }  
  
  portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
}



这是一个用信号量控制同一时间只能由一个任务使用UART3发送数据的例子。
注意的是,信号量一创建后初始状态就是可以申请占用的。


芯艺工作室    蒙ICP备06005492号
Copyright© 2004-2023 ChipArt Studio All Rights Reserved