基于 树莓派4 + STM32H7 构建支持云端应用的嵌入式系统平台 【二】

上一篇 ->

基于 树莓派4 + STM32H7 构建支持云端应用的嵌入式系统平台 【一】

原创不易,转载请注明出处,互相尊重劳动成果,谢谢!

三. MCU 软件设计构建

1. MCU核心温度采样

先实现基于片内ADC采样核心温度的功能,数据采样使用定时采样方式,采样数据基于DMA传输,减少CPU占用。

(1)设计框架

H743内部有三个独立的ADC转换器,除了能够采样连接到外部的模拟引脚外,还有三个内部的模拟采样通道,分别为核心温度、参考电压、VBat电压。
在这里插入图片描述

所使用的开发板上,有一个可调电阻连接到了PC3引脚,查DataSheet可知,该引脚可作为 ADC3Channel 1 使用:

外部模拟采样输入电路
因此在建立片内采样驱动时,使用 ADC3 作为采样ADC,分别采样:
* 外部引脚PC3上的电压数值
* 内部参考电压
* 内部温度传感器
* VBAT电压
四路模拟信号数值。采样结果通过DMA传输保存到变量中。
采样使用定时100毫秒采样一次,既10Hz采样率。每次连续采样上述四个通道后,触发处理信号,通知检测任务,处理采样数据,并通过串口传输出去。

(2) 片内ADC初始化与驱动

片内 ADC3 的初始化,基于LL固件库接口,参考LL库中关于ADC的使用例程移植改造而来。初始化过程中,需要注意的是对于上述四个采样通道的设置。

目前仅在启动后的初始化中做一次通道的配置,之后运行不再动态改变,因此配置过程比较简单,基本是先配置通道,再启动ADC,之后运行过程中不再配置,因此不需要做配置时的复杂判断逻辑。而在运行过程中动态切换通道配置时,是需要先停止ADC,完全停止后再配置通道,之后再开启采样的。

通道配置中,采样模式设置为软件触发而不是连续自动触发,以满足10Hz的采样率控制;
调用 LL_ADC_REG_SetSequencerLength 接口,设置总采样通道数量为 4
要使能三个内部采样通道,需要调用接口 LL_ADC_SetCommonPathInternalCh,允许对指定通道进行采样;
最后,定义四个采样通道的顺序。
通道配置代码如下:

	if ((LL_ADC_IsEnabled(TEMP_ADC) == 0)               ||
	  (LL_ADC_REG_IsConversionOngoing(TEMP_ADC) == 0)   )
	{
		LL_ADC_REG_SetTriggerSource(TEMP_ADC, LL_ADC_REG_TRIG_SOFTWARE);
		LL_ADC_REG_SetOverrun(TEMP_ADC, LL_ADC_REG_OVR_DATA_OVERWRITTEN);
		
		LL_ADC_REG_SetSequencerLength(TEMP_ADC, LL_ADC_REG_SEQ_SCAN_ENABLE_4RANKS);

		LL_ADC_SetCommonPathInternalCh(ADC3_COMMON, LL_ADC_PATH_INTERNAL_VREFINT | LL_ADC_PATH_INTERNAL_TEMPSENSOR | LL_ADC_PATH_INTERNAL_VBAT);

		LL_ADC_REG_SetSequencerRanks(TEMP_ADC, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_VREFINT);
		LL_ADC_REG_SetSequencerRanks(TEMP_ADC, LL_ADC_REG_RANK_2, LL_ADC_CHANNEL_TEMPSENSOR);
		LL_ADC_REG_SetSequencerRanks(TEMP_ADC, LL_ADC_REG_RANK_3, LL_ADC_CHANNEL_VBAT);
		LL_ADC_REG_SetSequencerRanks(TEMP_ADC, LL_ADC_REG_RANK_4, LL_ADC_CHANNEL_1);
	}

这里,定义驱动所使用的 TEMP_ADCADC3

#define TEMP_ADC								ADC3

接下来定义各个通道的采样时间:

		LL_ADC_SetChannelSamplingTime(TEMP_ADC, LL_ADC_CHANNEL_VREFINT, LL_ADC_SAMPLINGTIME_810CYCLES_5);
		LL_ADC_SetChannelSamplingTime(TEMP_ADC, LL_ADC_CHANNEL_TEMPSENSOR, LL_ADC_SAMPLINGTIME_810CYCLES_5);
		LL_ADC_SetChannelSamplingTime(TEMP_ADC, LL_ADC_CHANNEL_VBAT, LL_ADC_SAMPLINGTIME_810CYCLES_5);
		LL_ADC_SetChannelSamplingTime(TEMP_ADC, LL_ADC_CHANNEL_1, LL_ADC_SAMPLINGTIME_810CYCLES_5);

因为需求为100毫秒完成一轮采样,所有各个通道的采样时间都设置为最大,以提管转换稳定性。

最后,在启动ADC前,需要先自校准一下,之后再启动。自校准需要一定的时间,具体的启动过程如下:

	  LL_ADC_DisableDeepPowerDown(TEMP_ADC);
	  LL_ADC_EnableInternalRegulator(TEMP_ADC);
	  tx_thread_sleep(2);
	  LL_ADC_StartCalibration(TEMP_ADC, LL_ADC_CALIB_OFFSET_LINEARITY, LL_ADC_SINGLE_ENDED);
	  while (LL_ADC_IsCalibrationOnGoing(TEMP_ADC) != 0)
	  {
		  tx_thread_sleep(2);
	  }
	  
	  tx_thread_sleep(2);

	  LL_ADC_Enable(TEMP_ADC);
	  
	  while (LL_ADC_IsActiveFlag_ADRDY(TEMP_ADC) == 0)
	  {
		tx_thread_sleep(2);
	  }
(3)DMA配置

ADC转换完成后,使用DMA将转换结果传输到内存变量中。由于ADC配置为连续采样4个通道,因此每个通道采样转换完成后,会自动触发DMA动作,将结果传输到内存地址中,并开启下一个通道转换。当四个通道全部采样转换完成后,会触发DMA传输中断,可在此中断中添加处理转换完成的动作。

与STM32F7系列相比,STM32H7系列中,DMA部分有较大的改动,之前在F7上的DMA访问机制,在H7上无法复用。最大的来处不同为:
* ① 使用DMA MUX来为各个DMA通道选择外设,可由用户自由定义,不再严格受限于硬件指定
* ② DMA可访问地址受到限制。由于H7内核可运行在480MHz,内部的SRAM并没有全部运行在内核频率下,只有部分地址区间被设计为全速480MHz运行,其他地址空间运行在200MHz的低速。因此DMA的可访问地址,与能够与外设互通的内存,被限制在低速内存地址空间,而不是任意地址范围。这个变化是最坑的地方,如果按照之前ST的MCU使用经验,直接将变量地址设置为DMA访问内存地址,如果地址空间速度不匹配,将会出现不报任何错误的情况下,DMA收不到数据,调死也出不来!!!

未完待续… …

(4) 采样触发接口

因为是定时触发采样,所以设计一个采样触发接口,启动ADC采样转换。该接口可在定时任务中,每隔100毫秒调用一次。每次转换完成后,ADC自动停止采样。

void TriggerChipADCConversion()
{
	if ((LL_ADC_IsEnabled(TEMP_ADC) == 1)				&&
		(LL_ADC_IsDisableOngoing(TEMP_ADC) == 0)		&&
		(LL_ADC_REG_IsConversionOngoing(TEMP_ADC) == 0)   )
	{
		LL_DMA_ClearFlag_TC7(TEMP_ADC_DMA_LL);
		LL_DMA_ClearFlag_TE7(TEMP_ADC_DMA_LL);
		LL_DMA_SetDataLength(TEMP_ADC_DMA_LL, TEMP_ADC_DMA_STREAM_LL, TEMP_ADC_CHANNELS);
		LL_DMA_EnableStream(TEMP_ADC_DMA_LL, TEMP_ADC_DMA_STREAM_LL);
		LL_ADC_REG_StartConversion(TEMP_ADC);
	}
}

一轮转换完成后,会触发DMA传输中断,在中断处理中,做采样完成的通知操作:

void TEMP_ADC_DMA_IRQHandler()
{
	if(LL_DMA_IsActiveFlag_TC7(TEMP_ADC_DMA_LL))
	{
		LL_DMA_DisableStream(TEMP_ADC_DMA_LL, TEMP_ADC_DMA_STREAM_LL);
		TriggerTempCtrlEvent(0x01);
		LL_DMA_ClearFlag_TC7(TEMP_ADC_DMA_LL);
	}

	if(LL_DMA_IsActiveFlag_FE7(TEMP_ADC_DMA_LL))
	{
		LL_DMA_ClearFlag_FE7(TEMP_ADC_DMA_LL);
	}
	if(LL_DMA_IsActiveFlag_TE7(TEMP_ADC_DMA_LL))
	{
		LL_DMA_ClearFlag_TE7(TEMP_ADC_DMA_LL);
	}	
}

未完待续… …

2. MCU串口传输

未完待续… …

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于树莓派STM32的智能家居系统,需要一个清晰的系统架构和细致的软件设计。首先,我们需要将树莓派STM32以及Onenet云平台进行嵌入式开发,以实现智能家居系统的各种功能。 系统架构中,树莓派被设计为主控设备,负责与云平台进行通信和控制。而STM32作为从设备,主要处理各种传感器和执行器的数据采集和控制功能。这样的架构可以有效分担树莓派的计算负担,并提高系统的稳定性和响应速度。 在软件设计方面,我们可以采用分层的设计思路。首先是应用层,这个层次负责用户交互和控制。通过设计友好的用户界面和优雅的交互方式,使用户能够方便地使用系统各项功能。 其次是通信层,这个层次负责树莓派和云平台之间的通信。我们可以使用MQTT协议,通过WiFi或以太网连接树莓派和云平台,实现数据的传送和云端控制。 再次是逻辑层,这个层次负责处理来自传感器和执行器的数据,并自动化执行一些任务。通过编写适当的逻辑算法和规则,使系统能够智能地感知和响应环境变化,例如自动调节温度、照明和安防等。 最后是驱动层,这个层次负责与STM32进行通信和控制。我们可以编写相应的驱动程序,与STM32的GPIO口进行通信,实现对传感器和执行器的控制。 整个系统的设计需要考虑可扩展性和易于维护性。我们可以使用面向对象的编程方法,将各个功能模块进行封装,使其能够独立工作和灵活组装。同时,我们还需要进行充分的测试和调试,以确保系统的稳定性和可靠性。 总之,基于树莓派STM32的智能家居系统设计,需要一个清晰的架构和合理的软件设计。通过分层设计和模块化开发,我们可以实现一个功能强大、稳定可靠的智能家居系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值