1. 前言

最近在准备16届的蓝桥杯嵌入式赛道的国赛,打算出一个系列的博客,记录STM32G431RBT6这块比赛用板上所有模块可能涉及到的所有考点,如果有错误或者遗漏欢迎各位大佬斧正。

本系列博客会分为以下两大类:

1.1. 单独模块的讲解

在这部分,我会分享自己总结的各个模块的相关配置、代码书写模板,涉及到的大致框架如下:

 这个框架后续可能会不断更新,欢迎各位给出建议。

这一大类相关的文章链接如下(持续补充中):

【蓝桥杯嵌入式】【模块】一、系统初始化-CSDN博客

【蓝桥杯嵌入式】【模块】二、LED相关配置及代码模板-CSDN博客

【蓝桥杯嵌入式】【模块】三、LCD相关配置及代码模板-CSDN博客

【蓝桥杯嵌入式】【模块】四、按键相关配置及代码模板-CSDN博客

【蓝桥杯嵌入式】【模块】五、ADC相关配置及代码模板-CSDN博客

【蓝桥杯嵌入式】【模块】六、PWM相关配置及代码模板-CSDN博客

【蓝桥杯嵌入式】【模块】七、IIC相关配置及代码模板-CSDN博客

【蓝桥杯嵌入式】【模块】八、UART相关配置及代码模板-CSDN博客

1.2. 蓝桥杯各届的真题、模拟题复盘及个人答案

在这一部分,我会分享个人练过的所有题的复盘思路及代码,每篇文章结构如下:

这一大类相关的文章链接如下(持续补充中):

【蓝桥杯嵌入式】【复盘】第13届国赛真题_蓝桥杯嵌入式13届国赛题-CSDN博客

【蓝桥杯嵌入式】【复盘】第14届国赛真题-CSDN博客

【蓝桥杯嵌入式】【复盘】第15届省赛真题-CSDN博客

【蓝桥杯嵌入式】【复盘】第15届国赛真题-CSDN博客


以下是本篇博客正文内容:

2. 4t评测结果

4t平台网址:学单片机,上4T - 4T评测网

尝试了接近20次,始终有一个评测点过不了,实在没辙了。。


3. 个人解答代码

仓库地址:lanqiao/14_true_shengsai at main · Dukiyaaa/lanqiao

如果不嫌麻烦的话,可以点个star~


4. 重点和易错点

这一套题,根据我个人的做题经历,我认为应该关注的有以下几点:

1. pwm输出的高频调整。

2. 最大速度保持不足2s的不纳入统计。

4.1. pwm输出的高频调整

我的核心代码如下:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM4)
	{
		// ...按键扫描逻辑
		
		if(switch_lock == 1)
		{
			switch_lock_cnt++;
			
			if((switch_lock_cnt % 10) == 0)
			{
				led_8bits = led_8bits ^ (1 << 1);
			}
			
			if((switch_lock_cnt % 25) == 0)
			{
				if(is_high == 1 && fre_out > 4000)
				{
					fre_out -= 200;
					if(fre_out < 4000) fre_out = 4000;
				}
				else if(is_high == 0 && fre_out < 8000)
				{
					fre_out += 200;
					if(fre_out > 8000) fre_out = 8000;
				}

				pwm_set_fre_duty(fre_out, duty);
			}

			
			if(switch_lock_cnt >= 500)
			{
				switch_lock_cnt = 0;
				switch_lock = 0;
				
				led_8bits &= ~(1 << 1);
				
				if(is_high == 1)
				{
					fre_out = 4000.0f;
					is_high = 0;
				}
				else if(is_high == 0)
				{
					fre_out = 8000.0f;
					is_high = 1;
				}
				
				pwm_set_fre_duty(fre_out, duty);
			}
		}
		else
		{
			switch_lock_cnt = 0;
		}
		
		// ...最高速度保持2s
	}
}

void pwm_set_fre_duty(uint32_t fre, uint32_t duty)
{
    uint32_t clk = 80000000;
    uint32_t div = 1;
    uint32_t period = clk / div / fre - 1;
    uint32_t pulse  = period * duty / 100;
    if (pulse > period) pulse = period - 1; // 防止CCR超出ARR

    // 设置周期与占空比
    TIM2->ARR  = period;
    TIM2->CCR2 = pulse;

    // 强制立即更新(如果启用了预装载)
    TIM2->EGR |= TIM_EGR_UG;

    // 启动定时器
    TIM2->CR1 |= TIM_CR1_CEN;
}

void pwm_task(void)
{
    // ...pwm捕获
	
	// ...异步处理pwm输出
	pwm_set_fre_duty(fre_out, duty);
}

这个考点与之前的内容不同的地方在于pwm的输出会经历短时间内高频率的切换(我的是250ms切换一次,共切换20次,每次让频率变化200),测试时发现这样操作pwm输出huui'dao

4.2. 最大速度保持不足2s的不纳入统计

我的核心代码如下:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM4)
	{
		// ...按键扫描逻辑
		
        // ...pwm切换逻辑
		
        
		if(mh_lock == 0)
		{
			max_vh_cnt++;
			if(max_vh_cnt >= 200)
			{
				mh_lock = 1;
				max_vh_cnt = 0;
				MH = tmp_MH;
			}
		}
		
		if(ml_lock == 0)
		{
			max_vl_cnt++;
			if(max_vl_cnt >= 200)
			{
				ml_lock = 1;
				max_vl_cnt = 0;
				ML = tmp_ML;
			}
		}
	}
}

void pwm_task(void)
{
	V = fre * 2.0f * 3.14f * (float)R / (100.0f * (float)K);
	// 要加进任务调度才行,否则下面的if作比较会出问题
	if((V > MH) && (is_high == 1))
	{
		if(V != tmp_MH)
		{
			tmp_MH = V;	
			max_vh_cnt = 0;
			mh_lock = 0;
		}
	}
	
	if((V > ML) && (is_high == 0))
	{ 
		if(V != tmp_ML)
		{
			tmp_ML = V;
			max_vl_cnt = 0;
			ml_lock = 0;			
		}
	}
	
	// pwm输出逻辑
}

处理思路如下:

当测量得到当前的V大于记录的最大速度时,需要先进行判断,如果这次的V与当前的tmp_MH/tmp_ML相同,说明是同一个值重复在保持,跳过;反之说明上一次的最大值保持不足2s,所以要清零计数器重新开始计数2s;达到2s后,再做更新。

但是我这个点测评一直过不了,自己的板子上测试效果倒是没问题。如果有佬发现可能有什么问题,非常欢迎提出。


5. 总结

本文总结了个人在练习14届省赛过程中的复盘及易错点、重难点分析,主要内容在pwm输出高频调整、最大速度的捕捉。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐