蓝桥杯嵌入式国赛 ---- 第十一届试题解析


前言

**本程序设计是基于嵌入式开发板CT117E,stm32f103RBT6。

如果对哪个模块的代码不理解可以点开我的博客查看各个模块的编写思路。


一、试题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

二、需要用到的模块

1.LED

代码如下:led.c:

#include "led.h"

void led_init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOC, ENABLE);

  /* Configure PD0 and PD2 in output pushpull mode */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOD, &GPIO_InitStructure);

   GPIO_InitStructure.GPIO_Pin = 0xff00;
   GPIO_Init(GPIOC, &GPIO_InitStructure);
   GPIOC->ODR |=0xff<<8;
   GPIOD->ODR |=1<<2;
   GPIOD->ODR &=~(1<<2);
}

void led_ctrl(u8 ledx,u8 status)   //控制led的亮灭,ledx取值范围:8-15
{
	if(status)
	{
		GPIOC->ODR &=~(1<<ledx);    
   		GPIOD->ODR |=1<<2;
   		GPIOD->ODR &=~(1<<2);	
	}
	else
	{
	  	GPIOC->ODR |=1<<ledx;
   		GPIOD->ODR |=1<<2;
   		GPIOD->ODR &=~(1<<2);
	}
}

led.h:

#ifndef LED_H
#define LED_H

#include "stm32f10x.h"

void led_init(void);
void led_ctrl(u8 ledx,u8 status);
#endif

2.按键

代码如下:key.c:

#include "key.h"

void key_init(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);

  /* Configure PD0 and PD2 in output pushpull mode */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

}

key.h:

#include "key.h"

#ifndef KEY_H
#define KEY_H

#include "stm32f10x.h"

#define key1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)   //读取按键的状态
#define key2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)
#define key3 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)
#define key4 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_8)

void key_init(void);
#endif

3.ADC

代码如下:adc.c:

#include "adc.h"

void adc_init(void)
{
  ADC_InitTypeDef ADC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);

  /* Configure PC.01, PC.02 and PC.04 (ADC Channel11, Channel12 and Channel14)
    as analog input ----------------------------------------------------------*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_4;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* ADC1 configuration ------------------------------------------------------*/
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 1;
  ADC_Init(ADC1, &ADC_InitStructure);
  /* ADC1 regular channels configuration */ 
  //ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_239Cycles5);  
  
  ADC_Cmd(ADC1, ENABLE);

  /* Enable ADC1 reset calibration register */   
  ADC_ResetCalibration(ADC1);
  /* Check the end of ADC1 reset calibration register */
  while(ADC_GetResetCalibrationStatus(ADC1));

  /* Start ADC1 calibration */
  ADC_StartCalibration(ADC1);
  /* Check the end of ADC1 calibration */
  while(ADC_GetCalibrationStatus(ADC1));  
}

u16 get_adc(u8 Channel)
{
	u8 i,j;
	u16 t[50];
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);
	ADC_RegularChannelConfig(ADC1, Channel, 1, ADC_SampleTime_239Cycles5);
	for(i=0;i<50;i++)
	{
		t[i]=ADC_GetConversionValue (ADC1);
	}
	ADC_SoftwareStartConvCmd(ADC1, DISABLE);
	for(i=0;i<50-1;i++)
	{
		for(j=0;j<50-1-i;j++)
		{
			if(t[j]>t[j+1])
			{
				t[j]=t[j] ^ t[j+1];
				t[j+1]=t[j] ^ t[j+1];
				t[j]=t[j] ^ t[j+1];
			}
		}
	}
	return (t[24]+t[25])/2;
}

}


adc.h:

#ifndef ADC_H
#define ADC_H

#include "stm32f10x.h"

void adc_init(void);
u16 get_adc(void);

#endif

4.定时器3输出pwm

代码如下:pwm.c:

#include "pwm.h"

void time3_pwm_init(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_OCInitTypeDef  TIM_OCInitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

  /* Enable the TIM3 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 ;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 65535;
  TIM_TimeBaseStructure.TIM_Prescaler = 71;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

  /* Output Compare Toggle Mode configuration: Channel1 */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = 65535;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  TIM_OC2Init(TIM3, &TIM_OCInitStructure);

  /* TIM enable counter */
  TIM_Cmd(TIM3, ENABLE);

  /* TIM IT enable */
  TIM_ITConfig(TIM3, TIM_IT_CC2 , ENABLE);
}
u32 PWM_VAL,PWM_DUTY;
void set_pwm(u32 pwm_val,u32 pwm_duty)
{
	PWM_VAL=1000000/pwm_val;
	PWM_DUTY= pwm_duty * PWM_VAL /100;
	
	TIM_SetCounter(TIM3,0);
	TIM_SetCompare2(TIM3,0);
		
}

u32 capture;
static u8 ch2_mode=0;
void TIM3_IRQHandler(void)
{


  /* TIM3_CH2 toggling with frequency = 366.2 Hz */
  if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)
  {
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
    capture = TIM_GetCapture2(TIM3);
	if(ch2_mode)
	{
		TIM_SetCompare2(TIM3, capture + PWM_VAL);
	}
	else
	{
		TIM_SetCompare2(TIM3, capture + PWM_VAL - PWM_VAL);
	}
	ch2_mode ^=1;
    
  }

 
}

pwm.h:

#ifndef PWM_H
#define PWM_H
#include "stm32f10x.h"

void time3_pwm_init(void);
void set_pwm(u32 pwm_val,u32 pwm_duty);


#endif


5.定时器2捕获2路pwm频率

代码如下:capture.c:


#include "capture.h"
void time2_capture_init(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
  TIM_ICInitTypeDef  TIM_ICInitStructure;

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

  /* GPIOA clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  /* Enable the TIM3 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  /* TIM3 channel 2 pin (PA.07) configuration */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_1 | GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

  GPIO_Init(GPIOA, &GPIO_InitStructure);
  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 65535;
  TIM_TimeBaseStructure.TIM_Prescaler = 71;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  TIM_ICInitStructure.TIM_ICFilter = 0x0;

  TIM_ICInit(TIM2, &TIM_ICInitStructure);

  TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;
  TIM_ICInit(TIM2, &TIM_ICInitStructure);
  
  /* TIM enable counter */
  TIM_Cmd(TIM2, ENABLE);

  /* Enable the CC2 Interrupt Request */
  TIM_ITConfig(TIM2, TIM_IT_CC2 | TIM_IT_CC3, ENABLE);
}
u8 mode=1;
u8 ch2_mode=0,ch3_mode=0;
u32 CH2_VAL,CH2_DUTY,CH3_VAL,CH3_DUTY;
void TIM2_IRQHandler(void)
{ 
  if(TIM_GetITStatus(TIM2, TIM_IT_CC2) == SET) 
  {
    /* Clear TIM3 Capture compare interrupt pending bit */
    TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
    if(mode==1)
	{
		switch(ch2_mode)
		{
			case 0: CH2_VAL=0;
					CH2_DUTY=0;
					TIM_SetCounter(TIM2,0);
					TIM_OC2PolarityConfig(TIM2,TIM_OCPolarity_Low);
					ch2_mode=1;
					break;

			case 1: CH2_DUTY=TIM_GetCounter(TIM2);
					TIM_OC2PolarityConfig(TIM2,TIM_OCPolarity_High);
					ch2_mode=2;
					break;

			case 2: CH2_VAL=TIM_GetCounter(TIM2);
					TIM_OC2PolarityConfig(TIM2,TIM_OCPolarity_High);
					ch2_mode=3;
					break;

			default: break;
		}
	}
	else
	{
		ch2_mode=0;
		TIM_OC2PolarityConfig(TIM2,TIM_OCPolarity_High);
	}
  }

  if(TIM_GetITStatus(TIM2, TIM_IT_CC3) == SET) 
  {
    /* Clear TIM3 Capture compare interrupt pending bit */
    TIM_ClearITPendingBit(TIM2, TIM_IT_CC3);
    if(mode==0)
	{
		switch(ch3_mode)
		{
			case 0: CH3_VAL=0;
					CH3_DUTY=0;
					TIM_SetCounter(TIM2,0);
					TIM_OC3PolarityConfig(TIM2,TIM_OCPolarity_Low);
					ch3_mode=1;
					break;

			case 1: CH3_DUTY=TIM_GetCounter(TIM2);
					TIM_OC3PolarityConfig(TIM2,TIM_OCPolarity_High);
					ch3_mode=2;
					break;

			case 2: CH3_VAL=TIM_GetCounter(TIM2);
					TIM_OC3PolarityConfig(TIM2,TIM_OCPolarity_High);
					ch3_mode=3;
					break;

			default: break;
		}
	}
	else
	{
		ch3_mode=0;
		TIM_OC3PolarityConfig(TIM2,TIM_OCPolarity_High);
	}
  }
}

capture.h:

#ifndef CAPTURE_H
#define CAPTURE_H
#include "stm32f10x.h"

void time2_capture_init(void);

extern u8 mode;
extern u8 ch2_mode,ch3_mode;
extern u32 CH2_VAL,CH2_DUTY,CH3_VAL,CH3_DUTY;
#endif


三、主函数逻辑设计

stm32f10x_it.c:

#include "stm32f10x_it.h"

extern u32 TimingDelay;
extern u8 key_flag;
extern u8 mode;
void SysTick_Handler(void)
{
	static u8 key_num=0;
	static u16 time_num=0;
	key_num++;
	time_num++;
	if(key_num==50)
	{
		key_num=0;
		key_flag=1;
	}
	if(time_num==500)
	{
		time_num=0;
		mode ^=1;
	}
	TimingDelay--;
}

main.c:

#include "stm32f10x.h"
#include "stdio.h"
#include "adc.h"
#include "lcd.h"
#include "led.h"
#include "key.h"
#include "capture.h"
#include "pwm.h"

u32 TimingDelay = 0;
u8 key_flag;
u8 key_num[4];
u8 key1_flag=1;
void Delay_Ms(u32 nTime);
void key_read(void);
void lcd_show(void);
float rp5,rp6;
u8 buff[20];
u8 vd=1,fd=2;
u8 key4_flag=1;
//Main Body
int main(void)
{
	SysTick_Config(SystemCoreClock/1000);

	Delay_Ms(200);
	
	STM3210B_LCD_Init();
	LCD_Clear(Black);
	LCD_SetBackColor(Black);
	LCD_SetTextColor(White);
	led_init();
	key_init();
	adc_init();
	time2_capture_init();
	time3_pwm_init();
	
	while(1)
	{
		if(key_flag)
		{
			key_read();
			key_flag=0;
		}

		lcd_show();
		
			
	}
}

//
void Delay_Ms(u32 nTime)
{
	TimingDelay = nTime;
	while(TimingDelay != 0);	
}

void key_read(void)
{
	if(key1==0)
	{
	   key_num[0]++;
	   if(key_num[0]>15)
	   {
	   	
	   }
	}
	else
	{
		if(key_num[0]>1 && key_num[0]<10)
		{
			key1_flag ^=1;
			if(key1_flag==1)
			{
				GPIOC->ODR |=(0xff<<8);
  				GPIOD->ODR |=(1<<2);
  				GPIOD->ODR &=~(1<<2);

			}
		}
		key_num[0]=0;
	}


if(key2==0 && key1_flag==0)
	{
	   key_num[1]++;
	   if(key_num[1]>15)
	   {
	   	
	   }
	}
	else
	{
		if(key_num[1]>1 && key_num[1]<10)
		{
		   vd++;
		   if(vd==fd)
		   {
		   	 vd++;
		   }
		   if(vd>8)
		   {
		   	vd=1;
		   }
		}
		key_num[1]=0;
	}


	if(key3==0 && key1_flag==0)
	{
	   key_num[2]++;
	   if(key_num[2]>15)
	   {
	   	
	   }
	}
	else
	{
		if(key_num[2]>1 && key_num[2]<10)
		{
		   fd++;
		   if(vd==fd)
		   {
		   	 fd++;
		   }
		   if(fd>8)
		   {
		   	fd=1;
		   }
		}
		key_num[2]=0;
	}


	if(key4==0)
	{
	   key_num[3]++;
	   if(key_num[3]>15)
	   {
	   	
	   }
	}
	else
	{
		if(key_num[3]>1 && key_num[3]<10)
		{
			 key4_flag ^=1;
		}
		key_num[3]=0;
	}

}
void lcd_show(void)
{
	if(key1_flag==1)
	{
		LCD_DisplayStringLine(Line1,"    DATA             ");
		rp5=(float)get_adc(ADC_Channel_4)/0xfff*3.3;
		sprintf((char *)buff,"    V1:%0.1fV        ",rp5);
		LCD_DisplayStringLine(Line3,buff);
		
		rp6=(float)get_adc(ADC_Channel_5)/0xfff*3.3;
		sprintf((char *)buff,"    V2:%0.1fV        ",rp6);
		LCD_DisplayStringLine(Line4,buff);
		
		if(rp5>rp6)
		{
			led_ctrl(vd+7,1);
		}
		else
		{
			led_ctrl(vd+7,0);
		}

		if(ch2_mode==3)
		{
			if(key4_flag)
			{
				set_pwm(1000000/CH2_VAL,CH2_DUTY *100 / CH2_VAL);	
			}
			else
			{
				set_pwm(1000000/CH3_VAL,CH3_DUTY *100 / CH3_VAL);
			}	
			sprintf((char *)buff,"    F1:%dHz        ",1000000/CH2_VAL);
			LCD_DisplayStringLine(Line5,buff);
			ch2_mode=0;
		}

		if(ch3_mode==3)
		{
			if(key4_flag)
			{
				set_pwm(1000000/CH2_VAL,CH2_DUTY *100 / CH2_VAL);	
			}
			else
			{
				set_pwm(1000000/CH3_VAL,CH3_DUTY *100 / CH3_VAL);
			}	
			sprintf((char *)buff,"    F2:%dHz        ",1000000/CH3_VAL);
			LCD_DisplayStringLine(Line6,buff);
			ch3_mode=0;
		}

		if(1000000/CH2_VAL > 1000000/CH3_VAL)
		{
			led_ctrl(fd+7,1);
		}
		else
		{
			led_ctrl(fd+7,0);
		}
	}
	else
	{
		LCD_DisplayStringLine(Line1,"    PARA             ");

		sprintf((char *)buff,"    VD:LD%d        ",vd);
		LCD_DisplayStringLine(Line3,buff);

		sprintf((char *)buff,"    FD:LD%d        ",fd);
		LCD_DisplayStringLine(Line4,buff);

		LCD_DisplayStringLine(Line5,"                     ");
		LCD_DisplayStringLine(Line6,"                     ");


	}
}

四、 代码测试结果图

①主测试界面:
在这里插入图片描述

②设置界面

在这里插入图片描述

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值