[GD32L233C-START 评测] 【GD32L233C-START评测】15、RT-Thread消息队列、多线程使用

freeelectron   2022-1-29 19:59 楼主

相关文章:

【GD32L233C-START评测】1、优点与缺点都很明显的GD32L233C-START(开箱)

【GD32L233C-START评测】2、非阻塞方式点灯,blink,blink,blink……

【GD32L233C-START评测】3、pwm实现呼吸灯

【GD32L233C-START评测】4、串口不定长数据接收

【GD32L233C-START评测】5、Flash读写——使用内部Flash存储数据

【GD32L233C-START评测】6、硬件I2C驱动0.96吋OLED

【GD32L233C-START评测】7、硬件SPI1驱动RC522

【GD32L233C-START评测】8、获取MCU96位唯一ID、SRAM、FLASH大小

【GD32L233C-START评测】9、IAP程序升级——基于YMODEM协议

【GD32L233C-START评测】10、使用内部参考电压校准adc,adc采样更准确

【GD32L233C-START评测】11、GD32 ISP软件还不支持GD32L233

【GD32L233C-START评测】12、按键——外部中断

【GD32L233C-START评测】13、I2C驱动环境光和接近传感器RPR-0521RS

【GD32L233C-START评测】14、RT-Thread移植到GD32L233(内核,finsh移植)

 

1、基本思路
三个线程,一个消息队列(大小是1,长度是12);
线程1:LED 500ms闪烁一次,指示mcu运行;
线程2:adc采样,vdd电压、Ch1通道电压、mcu温度;
线程3:oled显示;

在线程2中,采样到数据后,通过消息队列发送到线程3,线程3收到消息后,更新oled显示。

 

2、RT-Thread配置

默认是没有使能消息队列的,需要使能消息队列;

image.png  或

image.png  

3、代码实现

(1)Led初始化及led线程

static rt_thread_t led_thread = RT_NULL;

void LedInit(void)
{
	/* enable the LED GPIO clock */
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_GPIOC);
    /* configure LED GPIO pin */
    gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_7 | GPIO_PIN_8);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7 | GPIO_PIN_8);
    /* reset LED GPIO pin */
    gpio_bit_reset(GPIOA, GPIO_PIN_7 | GPIO_PIN_8);
}

static void led_thread_entry(void *parameter)
{
    while (1)
    {
		gpio_bit_toggle(GPIOA, GPIO_PIN_7|GPIO_PIN_8);
        rt_thread_mdelay(500);
		rt_kprintf("led blink\r\n");
    }
}


void LedThreadStart(void)
{
	led_thread = rt_thread_create( "led",     /*线程名字*/                    
								   led_thread_entry,/*线程入口函数*/
								   RT_NULL,/*线程入口函数参数*/
								   256,    /*线程栈大小*/
								   4 ,    /*线程优先级*/
								   20);   /*线程时间片*/
	rt_thread_startup (led_thread);
}

(2)adc初始化以及adc线程

static rt_thread_t adc_thread = RT_NULL;
static uint8_t adc_data[12];

void AdcInit(void)
{
	AdcGpioInit();
	AdcConfig();
}

static void adc_thread_entry(void *parameter)
{
	uint16_t ref=0;
	float ch1=0;
	float vdd=0;
	float temp=0;
	uint16_t part1=0,part2=0;
	    
	int result;
	uint8_t *p=(uint8_t *)parameter;

	while(1)
	{
		ref=AdcSample(ADC_CHANNEL_17);
		vdd=1.2/(float)ref*4095;
		part1=(uint32_t)vdd;
		part2=vdd*1000-part1*1000;
		rt_kprintf("\r\nVdd=%d.%d V\r\n",part1,part2);
		
        rt_memcpy(&p[0],(uint8_t *)&part1,2);
		rt_memcpy(&p[2],(uint8_t *)&part2,2);

		ch1=AdcSample(ADC_CHANNEL_1)*vdd / 4095;
		part1=(uint32_t)ch1;
		part2=ch1*1000-part1*1000;
		rt_kprintf("Channel 1=%d.%d V\r\n",part1,part2);
		        
		rt_memcpy(&p[4],(uint8_t *)&part1,2);
		rt_memcpy(&p[6],(uint8_t *)&part2,2);
		
		temp = ((float)((int16_t)AdcSample(ADC_CHANNEL_16) - (*(int16_t *)(0x1FFFF7F8)))* vdd / 4095 * 1000 / vdd) + 30;
		part1=(uint32_t)temp;
		part2=temp*100-part1*100;
		rt_kprintf("Temp=%d.%d \r\n\r\n",part1,part2);
		
		rt_memcpy(&p[8],(uint8_t *)&part1,2);
		rt_memcpy(&p[10],(uint8_t *)&part2,2);
		
		extern rt_mq_t adc_to_oled_mq;
		
		result = rt_mq_send(adc_to_oled_mq, p,12); //发送消息

		if (result != RT_EOK)
        {
			rt_kprintf("%s,send mq err\r\n",adc_thread->name);
        }
		else
		{
			rt_kprintf("%s,send mq success\r\n",adc_thread->name);
		}
		
		rt_memset(p,'\0',12);
			
		rt_thread_mdelay(5000);
	}
}

void AdcThreadStart(void)
{
	adc_thread = rt_thread_create("adc",
								  adc_thread_entry,
								  &adc_data,
				                  512,
	                              5,
					              20);
		
	rt_thread_startup (adc_thread);
}

(3)oled初始化、oled线程、消息队列创建

static rt_thread_t oled_thread=RT_NULL;

rt_mq_t adc_to_oled_mq=RT_NULL;
static uint8_t oled_data[12];
static char temp[16];

static  void oled_thread_entry(void *parameter)
{
	uint8_t *p =(uint8_t *)parameter;
	
	while(1)
	{
		if(rt_mq_recv(adc_to_oled_mq,p,12,RT_WAITING_FOREVER)==RT_EOK)//读取消息
		{
			rt_kprintf("%s,recv message queue \r\n",oled_thread->name);
			
			rt_memset(temp,' ',sizeof(temp));
			rt_sprintf(temp,"Vdd=%d.%d V",*(uint16_t*)(&p[0]),*(uint16_t*)(&p[2]));
			OledShowString(10,0,temp,16);
			rt_kprintf("%s\r\n",temp);
						
			rt_memset(temp,' ',sizeof(temp));
			rt_sprintf(temp,"Ch1=%d.%d V",*(uint16_t*)(&p[4]),*(uint16_t*)(&p[6]));
			OledShowString(10,2,temp,16);
			rt_kprintf("%s\r\n",temp);
						
			rt_memset(temp,' ',sizeof(temp));
			rt_sprintf(temp,"Temp=%d.%d",*(uint16_t*)(&p[8]),*(uint16_t*)(&p[10]));
			OledShowString(10,4,temp,16);
			rt_kprintf("%s\r\n",temp);
		}
	}
}


void OledThreadStart(void)
{
	adc_to_oled_mq=rt_mq_create("adc_oled", 12,1, RT_IPC_FLAG_PRIO); //创建消息队列
	
	oled_thread= rt_thread_create("oled",oled_thread_entry,oled_data,512,7,20);
	
	rt_thread_startup(oled_thread);
}

4、现象

rtthread多线程消息队列.gif  

 

 

 

 

 

 

 

 

本帖最后由 freeelectron 于 2022-2-7 13:10 编辑
stm32/LoRa物联网:304350312

回复评论 (4)

学习了,很用心

点赞  2022-2-22 14:20
引用: zhangdaoyu 发表于 2022-2-22 14:20 学习了,很用心

相互学习,共同进步。

stm32/LoRa物联网:304350312
点赞  2022-2-22 19:02

用消息来给线程来做显示,很好,我原来做的定时刷新。

点赞  2022-2-23 09:06
引用: lugl4313820 发表于 2022-2-23 09:06 用消息来给线程来做显示,很好,我原来做的定时刷新。

项目中我也用消息做的显示,不过是部分显示,类似弹窗

点赞 (1) 2022-2-23 09:30
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复