蓝桥杯嵌入式十一届省题

蓝桥杯嵌入式十一届省题

一、分析

这一届的蓝桥杯嵌入式的省题相对来说还是比较简单的,其中主要的难点也就是对于adc和两路固定频率可调占空比pwm的配置,把这两个解决了,main函数编写起来相对往届简单。在这里插入图片描述
这里题目主要涉及pwm、adc、key、led。
对于pwm的配置我这里主要用到定时器的输出比较翻转模式TIM_OCMode_Toggle来进行处理,并且用到中断服务函数处理。
对于adc的配置,也都是比较基本的了,就不多说了。

二、赛题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
下面看代码部分。

三、代码

1.main函数

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

u32 TimingDelay = 0;



extern float ch1;
extern float ch2;

float ch1_f;
float ch2_f;

unsigned char key_val;
unsigned char chu_chun[40];
unsigned int adc_val;

unsigned char B1=0;   //界面切换
unsigned char mode=0;  //模式切换

unsigned char pa6_a=10;
unsigned char pa7_a=10;

void lcd_caozuo(void)
{
  if(B1==0)
	{
		LCD_DisplayStringLine(Line3,"      Date        ");
		
		adc_val=adc_scanf();
		sprintf((char *)chu_chun,"    V:%4.2f V        ",(float)adc_val*3.3/4095);
		
		LCD_DisplayStringLine(Line5,chu_chun);
		if(mode==0)
		{
		  LCD_DisplayStringLine(Line7,"    Mode:AUTO    ");
		  ch1_f=((float)adc_val*3.3/4095)/3.3;
			ch1=ch1_f;
			ch2=ch1_f;
		}
		if(mode==1)
		  LCD_DisplayStringLine(Line7,"    Mode:MANU    ");
			
			
	else if(B1==1)
	{
	  LCD_DisplayStringLine(Line3,"      Pare        ");
		
		sprintf((char *)chu_chun,"    PA6:%2u%%         ",pa6_a);
		LCD_DisplayStringLine(Line5,chu_chun);
		
		sprintf((char *)chu_chun,"    PA7:%2u%%         ",pa7_a);
		LCD_DisplayStringLine(Line7,chu_chun);
	}

}

void key_caozuo(void)
{
  key_val=key_scanf();  //读取按键值
	if(key_val==1)
	{
	  switch(B1)
		{
		  case 0:B1=1;break;
			case 1:B1=0;break;
		}
	}
	if(key_val==2)
	{
	  if(B1==1)
		{
		  if(mode==1)
			{
			  if(pa6_a!=100)
				{
				  ch1=ch1+0.1;
					pa6_a=pa6_a+10;
				}
				if(pa6_a==100)
				{
				  ch1=0.1;
					pa6_a=10;
				}
			}
		}
	}
		if(key_val==3)
	{
	  if(B1==1)
		{
		  if(mode==1)
			{
			  if(pa7_a!=100)
				{
				  ch2=ch2+0.1;
					pa7_a=pa7_a+10;
				}
				if(pa7_a==100)
				{
				  ch1=0.1;
					pa7_a=10;
				}
			}
		}
	}
	if(key_val==4)
	{
	  switch(mode)
		{
		  case 0:mode=1;break;
			case 1:mode=0;break;
		}
	}
}

//Main Body
int main(void)
{
	SysTick_Config(72000);

	STM3210B_LCD_Init();
	LCD_Clear(Black);
	LCD_SetBackColor(Black);
	LCD_SetTextColor(White);
	
	pwm_init();
	key_init();
	led_init();
	adc_init();
	
	while(1)
	{
	  lcd_caozuo();
		key_caozuo();
	}
}


void SysTick_Handler(void)
{
	led_init();
	if(mode==0)
		led_scanf(0,led1);
	else if(mode==1)
		led_scanf(1,led1);
	
	if(B1==0)
	  led_scanf(0,led2);
	else if(B1==1)
		led_scanf(1,led2);
	
}


2.pwm

#include "pwm.h"

u16 CR2_val=10000; //100hz    72Mhz/72/10000
u16 CR1_val=5000;  //200hz    72Mhz/72/5000

float ch1=0.1;     //占空比
float ch2=0.1;

u16 cata;
_Bool pa6=0;      //标志位
_Bool pa7=0;
void pwm_init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	NVIC_InitTypeDef NVIC_InitStruct;
	TIM_OCInitTypeDef TIM_OCInitStruct;
	
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	TIM_TimeBaseInitStruct.TIM_ClockDivision=0;
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period=65535;                   //65536-1
	TIM_TimeBaseInitStruct.TIM_Prescaler=71;                   //72mhz,¼ÆÊýƵÂÊΪ1mhz
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
	
	NVIC_InitStruct.NVIC_IRQChannel=TIM3_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
	NVIC_Init(&NVIC_InitStruct);
	
	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_Toggle;                //输出比较翻转
	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
	TIM_OCInitStruct.TIM_Pulse=CR1_val;
	TIM_OC1Init(TIM3,&TIM_OCInitStruct);
	
	TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Disable);  
	
	TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_Toggle;
	TIM_OCInitStruct.TIM_OutputState=TIM_OutputState_Enable;
	TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_High;
	TIM_OCInitStruct.TIM_Pulse=CR2_val;
	TIM_OC2Init(TIM3,&TIM_OCInitStruct);
	
	TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Disable);	  
	TIM_Cmd(TIM3,ENABLE);
	
	TIM_ITConfig(TIM3,TIM_IT_CC1|TIM_IT_CC2,ENABLE);
}

void TIM3_IRQHandler(void)
{
  if(TIM_GetITStatus(TIM3,TIM_IT_CC1)!=RESET)
	{
	  TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);        
		cata=TIM_GetCapture1(TIM3);               //获取当前计数器的值
		if(pa6==0)
		{
		  TIM_SetCompare1(TIM3,cata+(u16)(CR1_val*ch1));
			pa6=1;
		}
		if(pa6==1)
		{
		  TIM_SetCompare1(TIM3,cata+(u16)(CR1_val*(1-ch1)));
			pa6=0;
		}
	}
	  if(TIM_GetITStatus(TIM3,TIM_IT_CC2)!=RESET)
	{
	  TIM_ClearITPendingBit(TIM3,TIM_IT_CC2);
		cata=TIM_GetCapture2(TIM3);
		if(pa7==0)
		{
		  TIM_SetCompare2(TIM3,cata+(u16)(CR2_val*ch2));
			pa7=1;
		}
		if(pa7==1)
		{
		  TIM_SetCompare2(TIM3,cata+(u16)(CR2_val*(1-ch2)));
			pa7=0;
		}
	}
}


3.adc

#include "adc.h"

void adc_init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	ADC_InitTypeDef ADC_InitStruct;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_ADC1,ENABLE);
	
  GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AIN;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStruct);
	
	ADC_InitStruct.ADC_ContinuousConvMode=DISABLE;
	ADC_InitStruct.ADC_DataAlign=ADC_DataAlign_Right;
	ADC_InitStruct.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;
	ADC_InitStruct.ADC_Mode=ADC_Mode_Independent;
	ADC_InitStruct.ADC_NbrOfChannel=1;
	ADC_InitStruct.ADC_ScanConvMode=DISABLE;
	ADC_Init(ADC1,&ADC_InitStruct);
	
	ADC_RegularChannelConfig(ADC1,ADC_Channel_8,1,ADC_SampleTime_1Cycles5);
	ADC_Cmd(ADC1,ENABLE);
	ADC_StartCalibration(ADC1);
	while(ADC_GetCalibrationStatus(ADC1));
}

unsigned int adc_scanf(void)
{
  ADC_SoftwareStartConvCmd(ADC1,ENABLE);
	while(!ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC));
	return ADC_GetConversionValue(ADC1);
}


4.led

#include "led.h"

void led_init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD,ENABLE);
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin=led1|led2|led3|led4|led5|led6|led7|led8;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOC,&GPIO_InitStruct);
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_2;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOD,&GPIO_InitStruct);
	
	GPIO_SetBits(GPIOD,GPIO_Pin_2);
	GPIO_SetBits(GPIOC,ledALL);
	GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}

void led_scanf(unsigned char mode ,unsigned int led)
{
  if(mode==1)
	{
	  GPIO_SetBits(GPIOD,GPIO_Pin_2);
	  GPIO_SetBits(GPIOC,led);
	  GPIO_ResetBits(GPIOD,GPIO_Pin_2);
	}
	else if(mode==0)
	{
	  GPIO_SetBits(GPIOD,GPIO_Pin_2);
	  GPIO_ResetBits(GPIOC,led);
	  GPIO_ResetBits(GPIOD,GPIO_Pin_2);	  
	}
}


5.key

#include "key.h"
#include "lcd.h"

void key_init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_8;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_1;
	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStruct);
}

unsigned char key_scanf(void)
{
  unsigned char key_but=0;
	if(key1==0||key2==0||key3==0||key4==0)
	{
		Delay_LCD(200);
	  if(key1==0) key_but=1;
		if(key2==0) key_but=2;
		if(key3==0) key_but=3;
		if(key4==0) key_but=4;
	}
	return key_but;
}


注意:对于自动模式我们发现电压值与占空比是成除3.3的关系的,因此我们在自动模式中用adc的值除3.3,当adc=3.3时占空比为100%,当adc=0时占空比=0;
在这里插入图片描述
在这里插入图片描述

总结
这是我第一次写的文章可能不是写的很好,大家多担待一下。
另外说明一下在lcd.c上LCD_WriteReg(),LCD_WriteRAM_Prepare(),LCD_WriteRAM()三个函数中首行加上u16 pcout=GPIOC->ODR,最后一行加上GPIOC->ODR=pcout。用于锁存HC573.

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

叶同学要努力呀

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

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

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

打赏作者

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

抵扣说明:

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

余额充值