第十一届蓝桥杯嵌入式设计与开发 (省赛)

这里插入图片描述

分析

此次赛题围绕两个方向,结构如下:
在这里插入图片描述
代码:

1.主函数模块

main.c

#include   <stm32f10x.h>
#include   "lcd.h"
#include   "adc.h"
#include   "lcd_window.h"
#include   "pwm.h"
#include   "key.h"
#include   "led.h"
float  ADC_Value;
/******PWM********/
float  CH1_duty=0.1,CH2_duty=0.1;
u8     channel_1_flag,channel_2_flag;
/*************************/
u8     setting_mode=0;       //0 AUTO  1 MANU
u8     Data_Para=0;			 //0 Data  1 Para
int main(void)
{
    
    
 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
 SysTick_Config(SystemCoreClock/1000);
 STM3210B_LCD_Init();
 LCD_Clear(Black);
 LCD_SetBackColor(Black);
 LCD_SetTextColor(White);
 adc_Init();
 pwm_Init();
 KEY_Init();
 LED_Init();
while(1)
{
    
    
 lcd_window();
 KEY_Control();
 LED_Control();
}
}

在这里插入代码片

2.ADC模块
adc.c

#include  <stm32f10x.h>
#include  "adc.h"

void adc_Init(void)
{
    
    
  ADC_InitTypeDef ADC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
   /* Enable ADC1 and GPIOC clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOB, ENABLE);
  /* Configure PC.04 (ADC Channel14) as analog input -------------------------*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  /* ADC1 configuration ------------------------------------------------------*/
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
  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 channel14 configuration */ 
  ADC_RegularChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_13Cycles5);
 
  /* Enable ADC1 */
  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));
     
  /* Start ADC1 Software Conversion */ 
  //ADC_SoftwareStartConvCmd(ADC1, ENABLE);
}

float ADC_GetValue(void)
{
    
    
  float  ADC_V;
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);
  while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);
  ADC_V=ADC_GetConversionValue(ADC1)*3.30/0xfff;
  return ADC_V;
}

在这里插入代码片

ADC.h

#ifndef   __ADC_H
#define   __ADC_H
void adc_Init(void);
float ADC_GetValue(void);
#endif

在这里插入代码片

3.按键模块
key.c

#include  "stm32f10x.h"
#include  "stm32f10x_it.h"
#include  "key.h"
#include  "lcd.h"
extern  u8     setting_mode;       //0锟斤拷示AUTO  1锟斤拷示MANU
extern  u8     Data_Para;			 //0锟斤拷示Data页锟斤拷  1锟斤拷示Para页锟斤拷
extern  float  CH1_duty,CH2_duty;
float  ch1_duty_1=0.1,ch2_duty_1=0.1;
u8  key1_sum,key2_sum,key3_sum,key4_sum;
void   KEY_Init(void)
{
    
    
   GPIO_InitTypeDef GPIO_InitStructure;
   /* Enable GPIOA and GPIOB clock */
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
}

void   KEY_Control(void)
{
    
    
if(KEY1==0)
{
    
    
 delay_ms(10);
 if(KEY1==0)
 {
    
     key1_sum++;
   LCD_ClearLine(Line0);
   LCD_ClearLine(Line1);
   LCD_ClearLine(Line2);
   LCD_ClearLine(Line3);
   LCD_ClearLine(Line4);
   LCD_ClearLine(Line5);
   LCD_ClearLine(Line6);
   LCD_ClearLine(Line7);
   LCD_ClearLine(Line8);
   LCD_ClearLine(Line9);
 }
 if(key1_sum==1) 
 {
    
    
 if(setting_mode==1)
 {
    
    
   Data_Para^=1;
 }
 else
 {
    
    
   Data_Para=0;
 }
 }
}
else
{
    
    
key1_sum=0;
}
if(KEY2==0)
{
    
    
 delay_ms(10);
 if(KEY2==0)
 {
    
     
  key2_sum++;
  if(key2_sum==1)
  {
    
    
   if(setting_mode==1)
   {
    
    
    ch1_duty_1+=0.1;
    if((ch1_duty_1-1.0)>=0)
    {
    
    
      ch1_duty_1=0.1;
    } 
   }
  }
 }
}
else
{
    
    
key2_sum=0;
}
if(KEY3==0)
{
    
    
 delay_ms(10);
 if(KEY3==0)
 {
    
     key3_sum++;
   if(key3_sum==1)
   {
    
    
   if(setting_mode==1)
   {
    
    
    ch2_duty_1+=0.1;
    if((ch2_duty_1-1.0)>=0)
    {
    
    
      ch2_duty_1=0.1;
    } 
   }
  }
 }
}
else
{
    
    
key3_sum=0;
}
if(KEY4==0)
{
    
    
  delay_ms(10);
  if(KEY4==0)
  {
    
    
   key4_sum++;
   if(key4_sum==1)
   {
    
    
    setting_mode^=1;
   }
  }
 }
 else
 {
    
    
 key4_sum=0;
 }
}


这里的按键模块我觉得是一个很好的按键消抖方法(是参照那些前辈们这样写的)。
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_2)
void   KEY_Init(void);
void   KEY_Control(void);

#endif

在这里插入代码片

4.LED模块

#include  "stm32f10x.h"
#include  "led.h"
extern  u8     setting_mode;       
extern  u8     Data_Para;

void  LED_Init(void)
{
    
    
  GPIO_InitTypeDef GPIO_InitStructure;
  /* Enable GPIOA and GPIOB clock */
  RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC, ENABLE);
  GPIO_InitStructure.GPIO_Pin = LED1|LED2|LED3|LED4|LED5|LED6|LED7|LED8;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin =GPIO_Pin_2;
  GPIO_Init(GPIOD, &GPIO_InitStructure);
}

void LED_Status(uint16_t LED,u8 state)
{
    
    
//  GPIO_Write(GPIOC,0Xff00);	 //全灭
//  GPIO_SetBits(GPIOD,GPIO_Pin_2);//
//  GPIO_ResetBits(GPIOD,GPIO_Pin_2);
  if(state)    //on
  {
    
    
   GPIO_ResetBits(GPIOC,LED);
   GPIO_SetBits(GPIOD,GPIO_Pin_2);//
   GPIO_ResetBits(GPIOD,GPIO_Pin_2);
  }
  else
  {
    
    
   GPIO_SetBits(GPIOC,LED);
   GPIO_SetBits(GPIOD,GPIO_Pin_2);//
   GPIO_ResetBits(GPIOD,GPIO_Pin_2);
  }
}
void  LED_Control(void)
{
    
      
  GPIO_Write(GPIOC,0Xff00);	 //全灭
  GPIO_SetBits(GPIOD,GPIO_Pin_2);//	此处需要特别注意,应该在这里添加这三行代码
  GPIO_ResetBits(GPIOD,GPIO_Pin_2);
 if(setting_mode==1)
 {
    
    
  LED_Status(LED1,0);
 }
 if(setting_mode==0)
 {
    
    
 LED_Status(LED1,1);
 }
 if(Data_Para==0)
 {
    
    
 LED_Status(LED2,1);
 }	
 else
 {
    
    
 LED_Status(LED2,0);
 }

}

LED.H

#ifndef   __LED_H
#define    __LED_H
#include   "stm32f10x.h"
#define    LED1    GPIO_Pin_8
#define    LED2    GPIO_Pin_9
#define    LED3    GPIO_Pin_10
#define    LED4    GPIO_Pin_11
#define    LED5    GPIO_Pin_12
#define    LED6    GPIO_Pin_13
#define    LED7    GPIO_Pin_14
#define    LED8    GPIO_Pin_15
void  LED_Init(void);
void LED_Status(uint16_t LED,u8 state);
void  LED_Control(void);

#endif



5.pwm模块
pwm.c

#include <stm32f10x.h>
#include "pwm.h"
/******功能介绍****/
/*
该PWM函数是在同一定时器下的不同通道可以产生不同的频率,同时产生不同的占空比;
可以配合按键进行占空比修改和频率进行修改。
*/
/******PWM参数设定********/
extern  float    CH1_duty,CH2_duty;
extern  u8     channel_1_flag,channel_2_flag;
/*************************/
__IO uint16_t CCR1_Val =10000; //72000000/72/100	---100HZ
__IO uint16_t CCR2_Val =5000; //72000000/72/200	---200HZ

void  pwm_Init(void)
{
    
    
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_OCInitTypeDef  TIM_OCInitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
  NVIC_InitTypeDef  NVIC_InitStructure;
  /* TIM3 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
 /* GPIOA and GPIOA clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO, ENABLE);	//注意要是能复用时钟
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | 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 = 72-1;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

   /* Enable the TIM3 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  /* PWM1 Mode configuration: Channel1 */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; //记住
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  TIM_OC1Init(TIM3, &TIM_OCInitStructure);

  TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable);
  /* PWM1 Mode configuration: Channel2 */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  TIM_OC2Init(TIM3, &TIM_OCInitStructure);

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

  /* Enable the CC2 Interrupt Request */
  TIM_ITConfig(TIM3, TIM_IT_CC2|TIM_IT_CC1, ENABLE);
  TIM_SetCounter(TIM3,0x0);
  TIM_SetCompare2(TIM3,0x0);
  TIM_SetCompare3(TIM3,0x0);
}

void TIM3_IRQHandler(void)
{
    
     
  u16 capture;		        //注意这里时u16,之前用得是u8不行。
  if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
  {
    
    
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);
    capture = TIM_GetCapture1(TIM3);
	if(channel_1_flag)
    {
    
    
	TIM_SetCompare1(TIM3, capture + (u16)CCR1_Val*CH1_duty);
	}
	else
	{
    
    
	TIM_SetCompare1(TIM3, capture + (u16)CCR1_Val*(1-CH1_duty));
	}
   channel_1_flag^=1;
  }
  if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET)
  {
    
    
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
    capture = TIM_GetCapture2(TIM3);
	if(channel_2_flag)
    {
    
    
	TIM_SetCompare2(TIM3, (u16)(capture + CCR2_Val*CH2_duty));
	}
	else
	{
    
    
	TIM_SetCompare2(TIM3, (u16)(capture + CCR2_Val*(1-CH2_duty)));
	}
   channel_2_flag^=1;
  }
}
在这里插入代码片

该方法既可以调节占空比,也可以调节频率,题目要求只需调节占空比即可。同时有个地方注意一下: CH1_duty,CH2_duty这里我定义的是用float型来表示占空比,这样CH1_duty,CH2_duty直接就是小数,而当我把CH1_duty,CH2_duty,定义为u16时,用CH1_duty/100,CH2_duty/100来表示占空比时,PWM就无法正常输出。
pwm.h

#ifndef   __PWM_H
#define   __PWM_H
 void  pwm_Init(void);
#endif


结果

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

猜你喜欢

转载自blog.csdn.net/fsvff/article/details/114368935