第十三届 蓝桥杯 嵌入式设计与开发项目 省赛

目录

一、题目分析

二、代码分析

源代码链接


一、题目分析

        题目总体来看,其实并不难。用到了模块也不复杂,主要用到了led、按键、定时器、串口模块。对于本题的作者源码在文章的末尾,下面是我对题目的一些理解,不对之处还望指正。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAa2luZ213bA==,size_16,color_FFFFFF,t_70,g_se,x_16

 watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAa2luZ213bA==,size_16,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAa2luZ213bA==,size_18,color_FFFFFF,t_70,g_se,x_16

 watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAa2luZ213bA==,size_16,color_FFFFFF,t_70,g_se,x_16

         在本道题中,PA1脚输出1kHZ的方波或者2kHZ占空比为10%的pwm波是本道题比较难的点,我使用的方法是PA1所在引脚定时器2的输出比较模式,这样就可以实现引脚输出不同的频率不同占空比的pwm波了。

        还有就是@的显示 其实这个用字符打印会比较简单。使用sprintf();%c打印出来,@对应的ASCLL码值是64。

        具体实现看下面代码或者在文章末尾下载源码。

二、代码分析

界面切换

void LCD_Display(uint8_t LCDShow_Flag,int8_t BS1,int8_t BS2,int8_t BS3,uint16_t Feruq,uint8_t Duty)
{
	uint8_t string[21];
	
	//数据界面
	if(LCDShow_Flag==0)
	{
		LCD_DisplayStringLine(Line1,(unsigned char *)"       PSD");	
		
		//BS1
		sprintf((char*)string,"%s%c            ","    B1:", BS1);
		LCD_DisplayStringLine(Line3,string);
		
		//BS2
		sprintf((char*)string,"%s%c            ","    B2:", BS2);
		LCD_DisplayStringLine(Line4,string);
		
		//BS3
		sprintf((char*)string,"%s%c            ","    B3:", BS3);
		LCD_DisplayStringLine(Line5,string);
		
	}
	//参数界面
	else
	{
		LCD_DisplayStringLine(Line1,(unsigned char *)"       STA");	
		
		//清屏
		LCD_ClearLine(Line5);
		
			
		sprintf((char*)string,"%s%dHZ          ","    F:",Feruq);
		LCD_DisplayStringLine(Line3,string);
			
		sprintf((char*)string,"%s%d%%          ","    D:",Duty);
		LCD_DisplayStringLine(Line4,string);
	}
}

pwm输出代码如下。

#include "pwm.h"

//pwm频率
uint16_t CCR2_Val1 = 1000; //80000000/80/1000
uint16_t CCR2_Val2 = 500;  //80000000/80/2000

uint8_t PA1_Flag=0;

extern uint16_t Feruq;
extern uint8_t Duty;
extern uint8_t LCDShow_Flag;
extern int8_t BS1,BS2,BS3;

//定时器输出比较回调函数
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
	uint16_t capture=0;
	uint16_t temp=0;
	static uint16_t num=0;
	
	if(htim->Instance == TIM2)
	{
		if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
		{
			//获取定时器的计数值
			capture = __HAL_TIM_GetCounter(htim);
			
			//1K
			if(LCDShow_Flag == 0)
			{
				Feruq=1000;
				Duty=50;
				
				if(PA1_Flag==0)
				{
					PA1_Flag=1;
					
					temp = capture+CCR2_Val1/2;
					temp %= 65535;
					__HAL_TIM_SET_COMPARE(htim,TIM_CHANNEL_2,temp);
				}
				else
				{
					PA1_Flag=0;
					
					temp = capture+CCR2_Val1/2;
					temp %= 65535;
					__HAL_TIM_SET_COMPARE(htim,TIM_CHANNEL_2,temp);
				}
			}
			//2K
			else 
			{
				Feruq=2000;
				Duty=10;
				
				if(PA1_Flag==0)
				{
					PA1_Flag=1;
					num++;
					
					temp = capture+CCR2_Val2*0.1;
					temp %= 65535;
					__HAL_TIM_SET_COMPARE(htim,TIM_CHANNEL_2,temp);
				}
				else
				{
					PA1_Flag=0;
					
					temp = capture+CCR2_Val2*0.9;
					temp %= 65535;
					__HAL_TIM_SET_COMPARE(htim,TIM_CHANNEL_2,temp);
				}
			}
			if(num>=10000)
			{
				num=0;
				LCDShow_Flag=0;
				
				BS1=64;
				BS2=64;
				BS3=64;
			}
		}
	}
}

串口合法性判断

//串口数据合法性判断
void USART_Analysis(uint8_t* ptr,uint16_t n)
{
	if(n == 6)
	{
		if(ptr[3]=='-')
		{
			if((ptr[0]==PSD_Num[0]) && (ptr[1]==PSD_Num[1]) && (ptr[2]==PSD_Num[2]))
			{
				if(((ptr[4]>='0')&&(ptr[4]<='9')) && ((ptr[5]>='0')&&(ptr[5]<='9')) && ((ptr[6]>='0')&&(ptr[6]<='9')))
				{
					PSD_Num[0]=ptr[4];
					PSD_Num[1]=ptr[5];
					PSD_Num[2]=ptr[6];
					
					HAL_UART_Transmit(&huart1,PSD_Num,3,0xffff);
				}
			}
		}
	}
}

 主函数

 while (1)
  {
		//key
		KeyValue=KeyScan();
		switch(KeyValue)
		{
			case 1:
				BS1 = Key_PSDNumChang(BS1,LCDShow_Flag);
				break;
			case 2:
				BS2 = Key_PSDNumChang(BS2,LCDShow_Flag);
				break;
			case 3:
				BS3 = Key_PSDNumChang(BS3,LCDShow_Flag);
				break;
			case 4:
				LCDShow_Flag=PSD_PanDuan(&BS1,&BS2,&BS3,PSD_Num);
				break;
		}
		
		//串口
		if(USART1_Rx_STA&0x8000)
		{
			USART_Analysis(USART1_Rx_BUF,(USART1_Rx_STA&0x7fff)-1);
			USART1_Rx_STA=0;
		}
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		
		//LCD显示
		LCD_Display(LCDShow_Flag,BS1,BS2,BS3,Feruq,Duty);
		
		//led显示
		LedDisplay(LedShow_Flag,LedTog_Flag);
  }
  /* USER CODE END 3 */
}

         定时器输出比较模式,在比较寄存器值和定时器的计数值相等的时候出发中断,这个时候我们可以在中断回调函数中修改比较寄存器的值,就可以实现PA1引脚输出1KHZ的方波或者2KHZ占空比为10%的PWM波。

        在代码中有PA1_Flag,这个变量是来标记输出PWM波的高低电平,PA1_Flag=0为高电平,否则为低电平。

        在Cube中配置要把该引脚通道配置成翻转模式。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAa2luZ213bA==,size_20,color_FFFFFF,t_70,g_se,x_16

 大致就说到这里,代码工程在下面,大家可以自取。只供学习使用,不对之处还望指正。欢迎大家留言。

源代码链接

链接:https://pan.baidu.com/s/1DCjDq41gdhQzoMUOZ7qqCg 
提取码:mwl7 
 

  • 13
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

只有一个m

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值