RT-Thread信号量+消息队列实验

最近打算学习RT-Thread,但是由于手上没有现成的开发套件,也懒得去买(有条件的最好还是买一块),于是在公司随手找了一块好用的板子,只要仿真器好用+有一个可用的串口,就可以玩起来了,有兴趣的可以试试,高手勿喷。

首先使用STM32Cubemx ,配合原理图,配置好引脚功能

配置好要用的功能,本次实验可以只配置串口,如果有其他外设可以自己扩展,生成一个附带RT-Thread操作系统的基础工程,接下来开始扩展代码。

本次实验要实现的功能是,在串口中断中,以单个字节的方式接收串口数据,释放信号量,消息队列发送线程获取信号量,以单字节的方式,解析串口数据,当确认收到一包完整的数据后,将数据发送到消息队列,接收消息队列取出数据,打印信息。先看主函数:

int main(void)
{
	HAL_Init();
	SystemClock_Config();
	MX_GPIO_Init();
	MX_USART2_UART_Init();
	/*开启串口中断*/
	HAL_UART_Receive_IT(&huart2, (uint8_t *)&rDataBuffer, 1);  
	
	/* 初始化信号量*/
    rt_sem_init(&sem_lock, "sig_lock", 0 ,  RT_IPC_FLAG_PRIO);
	 
    /*创建一个消息队列*/
	test_mq = rt_mq_create("test_mq",/*消息队列名字*/
	                         50,       /*消息最大长度*/
	                         20,       /*消息队列最大容量*/
	                         RT_IPC_FLAG_FIFO);/*队列模式*/
    if (test_mq != RT_NULL)
    rt_kprintf("消息队列创建成功!\n\n");
									 
	receive_thread =                          /* 线程控制块指针 */
        rt_thread_create( "receive",              /* 线程名字 */
                        receive_thread_entry,   /* 线程入口函数 */
                        RT_NULL,             /* 线程入口函数参数 */
                        512,                 /* 线程栈大小 */
                        3,                   /* 线程的优先级 */
                        20);                 /* 线程时间片 */

    /* 启动线程,开启调度 */
    if (receive_thread != RT_NULL)
        rt_thread_startup(receive_thread);
    else
        return -1;

    send_thread =                          /* 线程控制块指针 */
        rt_thread_create( "send",              /* 线程名字 */
                        send_thread_entry,   /* 线程入口函数 */
                        RT_NULL,             /* 线程入口函数参数 */
                        512,                 /* 线程栈大小 */
                        2,                   /* 线程的优先级 */
                        20);                 /* 线程时间片 */

    /* 启动线程,开启调度 */
    if (send_thread != RT_NULL)
        rt_thread_startup(send_thread);
    else
        return -1;
}

 启动串口中断,初始化信号量,并创建消息队列,创建两个线程,一个接收,一个发送。在串口接收中断回调函数里:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	    UNUSED(huart);
        rData[rDataCount]=rDataBuffer;
		rDataCount++;
		//数据缓冲区满
		if(rDataCount >= RecvBuffSize)  
		{  
			 rDataCount = 0;
		}	
        /*重新设置中断*/
		HAL_UART_Receive_IT(&huart2, (uint8_t *)&rDataBuffer, 1);
		/*释放锁信号*/
		rt_sem_release(&sem_lock);
}

发送线程用来解析数据,将每次收到的字节发送到解析程序,让线程程序实现快进快出,增加实时性,当确认收到完整的数据后,将数据发送到消息队列:

static void send_thread_entry(void* parameter)
{
    rt_err_t uwRet = RT_EOK;

    while (1)
	{ 
	    /* 获取信号量 */
        rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
			
        /* 解析数据--并判断是否为完整包数据*/
	    CmdReceive(rData[rSendDataCount]);
		rSendDataCount++;
		if(rSendDataCount >= RecvBuffSize)
		{
			rSendDataCount = 0;
		}
		if(Msg_Deal.msg_finish == 1)
		{
			/* 收到完整包,将数据写入(发送)到队列中  */
			uwRet = rt_mq_send(test_mq,/* 写入(发送)队列的ID(句柄) */
						/* 写入(发送)的数据 */								 
                        &Msg_Deal.msg_Data[Msg_Deal.msg_packsend],
						/* 数据的长度 */								 
                        sizeof(Msg_Deal.msg_Data[Msg_Deal.msg_packsend])); 
			Msg_Deal.msg_finish = 0;
			if (RT_EOK != uwRet) 
			{
				rt_kprintf("数据不能发送到消息队列!错误代码: %lx\n",uwRet);
			}
		}
        rt_thread_delay(50);
    }
}

接收线程里,取出消息队列中的数据,并打印信息,这里还可以进一步扩展为命令解析后的执行操作,待后续完善:

static void receive_thread_entry(void* parameter)
{
    rt_err_t uwRet = RT_EOK;
    Uart_MessageInfo r_queue;
    /* 线程都是一个无限循环,不能返回 */
    while (1) 
	{
        /* 队列读取(接收),等待时间为一直等待 */
        uwRet = rt_mq_recv( test_mq,             /* 读取(接收)队列的ID(句柄) */
                            &r_queue,            /* 读取(接收)的数据保存位置 */
                            sizeof(r_queue),     /* 读取(接收)的数据的长度 */
                            RT_WAITING_FOREVER); /* 等待时间:一直等 */
        if (RT_EOK == uwRet) 
		{
			 rt_kprintf("接收的数据:Len=%d Devid=%d SrcAddr=%d DstAddr=%d Cmd=%d 
                               DateLen=%d\n" ,r_queue.Len,r_queue.DevId,r_queue.SrcAddr
                              ,r_queue.DstAddr,r_queue.Cmd,r_queue.DateLen);
        } 
		else 
		{
            rt_kprintf("数据接收出错,错误代码: 0x%lx\n",uwRet);
        }
        rt_thread_delay(100);
    }
}

记录一下实现效果:

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值