Stm32 freertos队列串口缓冲区的使用

2023-05-16

main.c

 

#include "Config.h"
#include "Command.h"	
#include "Control.h"
#include "bsp.h"
#include "delay.h"
#include "24C512.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
//==================================================
//任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);

//任务优先级
#define LED1_TASK_PRIO		1
//任务堆栈大小	
#define LED1_STK_SIZE 		50  
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void Led1_task(void *pvParameters);

//任务优先级
#define KEY_TASK_PRIO		1
//任务堆栈大小	
#define KEY_STK_SIZE 		50  
//任务句柄
TaskHandle_t KEYTask_Handler;
//任务函数
void Key_task(void *pvParameters);


//任务优先级
#define uart1_process_TASK_PRIO		1
//任务堆栈大小	
#define uart1_process_task_STK_SIZE 		128
//任务句柄
TaskHandle_t uart1_process_Task_Handler;
//任务函数
void uart1_process_task(void const *pvParameters);

QueueHandle_t Rx_Message_Queue; //信息队列句柄,用来传递串口接收到的数据
#define MESSAGE_Q_NUM   1000  //接收数据的消息队列的数量 (本实验这里指的是可存储连续10条串口指令)  改大可以缓解大数据量的吞吐
//==================================================
int main(void)
{  
	BSP_Init();//Board Init,板级初始化
	System_init();
	//init_config();//调取eeprom参数
		//创建任务
   	//创建开始任务
    xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
    vTaskStartScheduler();                              //开启任务调度
	while(1);
	

}


//
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
	  //Tx_Message_Queue=xQueueCreate(MESSAGE_Q_NUM,sizeof(u8));
	  Rx_Message_Queue=xQueueCreate(MESSAGE_Q_NUM,sizeof(u8));//MESSAGE_Q_NUM队列的队列长度,这里是队列的项目数,队列中每个项目(消息)的长度,单位为字节
    //
    xTaskCreate((TaskFunction_t )Led1_task,     	
                (const char*    )"led1_task",   	
                (uint16_t       )LED1_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )LED1_TASK_PRIO,	
                (TaskHandle_t*  )&LED1Task_Handler);   
    
    xTaskCreate((TaskFunction_t )Key_task,     
                (const char*    )"KEY_task",   
                (uint16_t       )KEY_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )KEY_TASK_PRIO,
                (TaskHandle_t*  )&KEYTask_Handler);   							
    //
    xTaskCreate((TaskFunction_t )uart1_process_task,     
                (const char*    )"uart1_process_task",   
                (uint16_t       )uart1_process_task_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )uart1_process_TASK_PRIO,
                (TaskHandle_t*  )&uart1_process_Task_Handler);  
													
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}
//
void Led1_task(void *pvParameters)
{
    while(1)
    {
      //GPIO_WriteBit(GPIOC, GPIO_Pin_13, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13)));
			LED1_ON();
			vTaskDelay(500);
			LED1_OFF();
			vTaskDelay(500);
    }
}   


void Key_task(void *pvParameters)
{
    while(1){
			Key_Scan();
		}
}

//
#define MY_CMD_SIZE 0x0a
enum input_stat
{
	NULL__=0,
	WATI_NORMAL,
	WATI_FUNCTION,
	
};
struct my_shell
{
	enum input_stat stat;
	char line[MY_CMD_SIZE];
	uint8_t line_position;//队头
	uint8_t line_curpos;//队尾
};

struct my_shell  _shell,*shell;
//
void uart1_process_task(void const *pvParameters)
{
	uint8_t ch;
	shell=&_shell;//结构体指针指向结构体变量
	while(1)
	{
//		 if( USARTStructure2.RX_Flag==1 ){                    /*If receive the command*/
//			  USARTStructure2.RX_Flag=0;									 //清标志位 
//			  USARTStructure2.RX_TMEP_Len=0;
//				USARTStructure2.RX_Len=0;
//			  Command_exec((char*)USARTStructure2.RX_TEMP_BUFF);
//			  //Check2((char *)USARTStructure2.RX_TEMP_BUFF);  /*Run the action*/ 
//		  }
		while(xQueueReceive( Rx_Message_Queue, &ch, 10 ) != pdPASS){//没有收到数据继续读,读到就跳出执行163行后面程序,(读取队列Rx_Message_Queue过程中把读到的数据拷贝到ch缓冲区中,读取成功以后就会将队列中的这条数据删除)
			   if (shell->line_curpos == 0)//一条正确格式的指令后就会清0 看182行
         continue;//继续执行155行
				 shell->line_position--;                   //频繁接收出错(shell->line_curpos!=0) 队头指针回0位置 正常不会执行到这里
         shell->line_curpos--;                     //队尾指针回0位置
         shell->line[shell->line_position]= 0;     //出错清除shell队列里面内容

				 
		}
		if(ch=='\r'){
			char next;
			if(xQueueReceive( Rx_Message_Queue , &next, 10 ) == pdPASS){//如果队列读取成功
				if(next=='\0'){
					ch='\r';
				}
				else {
					ch=next;//正常带\r\n的指令 解析\r的时候执行到这儿	ch=0x0A 接着执行178行
				}					
			}
			else{
				ch='\r';//如果队列读取失败
			}
			
		}
		 /* handle end of line, break  处理命令行结尾*/
		if (ch == '\r' || ch == '\n'){
			Command_exec(shell->line); //解析队列里面的内容
			memset(shell->line, 0, sizeof(shell->line));
			shell->line_curpos = shell->line_position = 0;//初始化为0位置
			continue;//跳转到146行
		}
		 /* it's a large line, discard it 命令行太长*/
		if (shell->line_position>=MY_CMD_SIZE)//判断是否是长指令
		{
				shell->line_position = 0;
				shell->line_curpos = 0;
		}
		shell->line[shell->line_position] = ch;//把指令存到缓冲区里面
		ch=0;//接收数据变量清0
		shell->line_position++; //收到数据队头指针向后移一位
		shell->line_curpos++;   //收到数据队尾指针向后移一位
	}
}

uart2.c

extern QueueHandle_t Rx_Message_Queue;
unsigned char uart2_data;

void USART2_IRQHandler(void)
{  
	BaseType_t xHigherPriorityTaskWoken=pdFALSE;
	BaseType_t err;
	if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET)				// 串口接收数据触发中断
	{
		USART_ClearITPendingBit(USART2, USART_IT_RXNE);					//清空接收中断标志			
		uart2_data=USART_ReceiveData(USART2);
	  err=xQueueSendFromISR(Rx_Message_Queue,&uart2_data,&xHigherPriorityTaskWoken);//发送消息到队尾uart2_data->Rx_Message_Queue
		if(err==errQUEUE_FULL){
			printf("xQueue is full,send message fail to pc\r\n");
		}
		portYIELD_FROM_ISR(xHigherPriorityTaskWoken);       
		
	}	

}

command.c

#include "Config.h"
#include "string.h"
#include "Control.h"
#include "Command.h"
#include "USART1_init.h"
#include "24C512.h"
#include "delay.h"
#include "SysTick.h"
#include "crc16.h"



typedef void (*op_func)();
void Help(void *parameters);

struct _cmd
{
	char *str;
	uint8_t parameters;
	void *f;
};
//===================================================
const struct _cmd Cmd[]=
{
	{"HELP",0,Help},
  {"FWVER",0,Fwver},
	{"SET_OUT",0,Set_OUT},
	{"RESET_OUT",0,Reset_OUT},
	{"GET_ALL_SENSOR_STATUS",0,Get_ALL_Sensor_Status},
	{"RESET",0,Reset},
	{"BEEP",0,Beep},
	
};

#define CMD_LEN sizeof(Cmd)/sizeof(struct _cmd)    //84/12
//===================================================
void Help(void *parameters){
	  int j,i;
	  i=CMD_LEN;
	 	for(j=0;j<i;j++)
		{
				printf("%s\r\n",Cmd[j].str);
		}
    printf("OK\r\n"); 
} 
//===================================================

int uart_strncmp(const char *str,const char *cmd_str)
{

		for(;;)
		{
			    if(*cmd_str=='\0')
					{
						if(((int)*str<48)||(((int)*str>57)&&((int)*str<65))||(((int)*str>90)&&((int)*str<96))||((int)*str>122))
						{
									if((int)*str!=95)
								break;						
						}
					}
					if(*str != *cmd_str)return 1;//
					str++;
					cmd_str++;
		}
		return 0;
}


//===================================================
char pr[32];
void Command_exec(char *cChar){
	int parameterv[8],temp;
  unsigned int parameters,i;
	op_func p;
  for(i=0;i<CMD_LEN;i++)                //CMD_LEN为指令的个数
	{
		if(uart_strncmp(cChar,Cmd[i].str)==0)
	 {			
			parameters=Cmd[i].parameters;     //保存函数参数个数
		  sscanf(cChar,"%*[^(](%[^)]"	,pr);	//cChar为uart2缓冲区中的指令 %*[^(] + ( + %[^)] 3部分组成   pr含有数字和逗号和句号 例如1,2,3,4,5,6   %*[^(]:忽略(之前的非(字符      %[^):取)之前的字符
		  p=(op_func)Cmd[i].f;              //函数指针指向结构体函数指针
      if(p!=NULL){
			switch(parameters)                //解析函数参数个数
			{
				case 0:p(pr);break;
				case 1:
					temp=sscanf(pr,"%d",&parameterv[0]);
          if(temp==1){
						p(parameterv[0]);
					}
					else i=CMD_LEN; //错误的指令,退出for循环
          break;	

       	case 2:
					temp=sscanf(pr,"%d,%d",parameterv,parameterv+1);
          if(temp==2){
						p(parameterv[0],parameterv[1]);
					}
					else i=CMD_LEN;//错误的指令,退出for循环 下达指令函数参数只能多不能少 少则出错 多则不报错
          break;					
				default: break;
      					
			}
			
		 }
			break;//跳出for循环 使得i值不增加 为不识别的指令判断创造判断条件
		}
		
	}
	if(i>=CMD_LEN){
		printf("Command Not Found!\r\n"); //无法匹配命令表时 i=CMD_LEN
	}


}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Stm32 freertos队列串口缓冲区的使用 的相关文章

随机推荐