蓝桥杯第四届嵌入式程序

本次考试主要是双路PWM的输出控制;

①、库函数

蓝桥杯第四届嵌入式程序_第1张图片

 

②、初始化函数

init.c

#include "stm32f10x.h"
#include "lcd.h"
#include 
#include "init.h"
#include "i2c.h"

 void GPIO_Int(void)
{

	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD , ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB , ENABLE);

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);

  //LED
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10| GPIO_Pin_11 | GPIO_Pin_12| GPIO_Pin_13 | GPIO_Pin_14|GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOC, &GPIO_InitStructure);

	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);

	

	//KEY

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

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

	GPIO_SetBits(GPIOC,GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10| GPIO_Pin_11 | GPIO_Pin_12| GPIO_Pin_13 | GPIO_Pin_14|GPIO_Pin_15);
	GPIO_SetBits(GPIOD,GPIO_Pin_2);
	GPIO_ResetBits(GPIOD,GPIO_Pin_2);

	//RTC
	/* Allow access to BKP Domain */
  PWR_BackupAccessCmd(ENABLE);

  /* Reset Backup Domain */
  BKP_DeInit();

  /* Enable LSE */
   RCC_LSICmd(ENABLE);
  /* Wait till LSE is ready */
  while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
  {}

  /* Select LSE as RTC Clock Source */
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);

  /* Enable RTC Clock */
  RCC_RTCCLKCmd(ENABLE);

  /* Wait for RTC registers synchronization */
  RTC_WaitForSynchro();

  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();

  /* Enable the RTC Second */
  RTC_ITConfig(RTC_IT_SEC, ENABLE);

  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();

  /* Set RTC prescaler: set RTC period to 1sec */
  RTC_SetPrescaler(39999); /* RTC period = RTCCLK/RTC_PR = (40 KHz)/(3999+1) */

  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();

  RTC_SetCounter(HH*3600+MM*60+SS);

  NVIC_Configuration();	 //rtc和usart中断

}

void LCD_Init(void)
{
    STM3210B_LCD_Init();
	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);
	
	SysTick_Config(SystemCoreClock/1000);


	LCD_DisplayStringLine(Line0,"                    ");	
	LCD_DisplayStringLine(Line1," PWM-PA1: 80%       ");	
	LCD_DisplayStringLine(Line2," PWM-PA2: 10%       ");
    LCD_DisplayStringLine(Line3," Time: 23:59:50     ");
	LCD_DisplayStringLine(Line4," Channel: None      ");	
	LCD_DisplayStringLine(Line5," Command:           ");
	LCD_DisplayStringLine(Line6,"              None  ");
	LCD_DisplayStringLine(Line7,"                    ");	
	LCD_DisplayStringLine(Line8,"                    ");
	LCD_DisplayStringLine(Line9,"                    ");	
	


}

void USART2_Configuration(void)	//因为之后需要,特地将usart初始化单独出来  (PWM)
{
  USART_InitTypeDef USART_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); 
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  
  /* Configure USARTz Rx as input floating */
  GPIO_InitStructure.GPIO_Pin = USARTz_RxPin;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure); 

  USART_InitStructure.USART_BaudRate = 9600;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

  /* Configure USART2 */
  USART_Init(USART2, &USART_InitStructure);
  /* Enable USARTz Receive  interrupts */
  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
  /* Enable the USARTz */
  USART_Cmd(USART2, ENABLE);

 
}

void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Configure the NVIC Preemption Priority Bits */  
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

  /* Enable the USARTz Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);

  NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}



void TIM2_Configuration(u16 CCR2_Val,u16 CCR3_Val)
{
   TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
   TIM_OCInitTypeDef  TIM_OCInitStructure;
   GPIO_InitTypeDef GPIO_InitStructure;

   /* TIM2 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    /* GPIOA  clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);


  TIM_TimeBaseStructure.TIM_Period = 999;
  TIM_TimeBaseStructure.TIM_Prescaler = 71;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  /* PWM1 Mode configuration: Channel2 */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

  TIM_OC2Init(TIM2, &TIM_OCInitStructure);

  TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);

  

  /* PWM1 Mode configuration: Channel3 */
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_Pulse = CCR3_Val;

  TIM_OC3Init(TIM2, &TIM_OCInitStructure);

  TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);

  TIM_ARRPreloadConfig(TIM2, ENABLE);

  /* TIM2 enable counter */
  TIM_Cmd(TIM2, ENABLE);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOA, &GPIO_InitStructure);



}

unsigned char IIC_Read(unsigned char add)
{
 unsigned char temp;
 I2CStart();
 I2CSendByte(0xa0);
 I2CSendAck();

 I2CSendByte(add);
 I2CSendAck();

 I2CStart();
 I2CSendByte(0xa1);
 I2CSendAck();
 temp=I2CReceiveByte();
 I2CSendAck();
 I2CStop();
 return (temp);
}

void  IIC_Write(unsigned char add,unsigned char dat)
{
 
 I2CStart();
 I2CSendByte(0xa0);
 I2CSendAck();

 I2CSendByte(add);
 I2CSendAck();


 I2CSendByte(dat);
 I2CSendAck();
 I2CStop();
 
}


 init.h

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


#define RB1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
#define RB2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)
#define RB3 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)
#define RB4 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_2)

#define USARTz_RxPin             GPIO_Pin_3
#define HH  23
#define MM  59
#define SS  50


void GPIO_Int(void);
void LCD_Init(void);
void TIM2_Configuration(u16 CCR2_Val,u16 CCR3_Val);

void NVIC_Configuration(void);
void USART2_Configuration(void);
void IIC_Write(unsigned char add,unsigned char dat);
unsigned char IIC_Read(unsigned char add);


#endif


③、主函数

#include "stm32f10x.h"
#include "lcd.h"
#include 
#include "init.h"
#include "i2c.h"




u32 TimingDelay = 0;
u8 RX_Buff[20];
u8 Receive=0;
u8 string[20];
u8 PA1=0,PA2=0;
u16 CCR2_Val;
u16 CCR3_Val; 
u8 BHH=0,BMM=0,BSS=0;

__IO uint32_t TimeDisplay=0;

void Delay_Ms(u32 nTime);
void LCD_Init(void);
void GPIO_Int(void);
void KEY_Scan(void);
void Time_Display(uint32_t TimeVar);



int main(void)
{
 SysTick_Config(SystemCoreClock/1000);
  
 LCD_Init();
 GPIO_Int();
 i2c_init();


 //TIM2_Configuration(500,800);
 USART2_Configuration();

 if(IIC_Read(0x20)!=20)
 {
 Delay_Ms(5);
 IIC_Write(0x00,70);

 Delay_Ms(5);
 IIC_Write(0x01,5);

 Delay_Ms(5);
 IIC_Write(0x20,20);

 
 }
 Delay_Ms(5);
 CCR2_Val=IIC_Read(0x00);

 Delay_Ms(5);
 CCR3_Val=IIC_Read(0x01);

 sprintf((char*)string," PWM-PA1: %.2d%%",CCR2_Val);
 LCD_DisplayStringLine(Line1,string);
 sprintf((char*)string," PWM-PA2: %.2d%%",CCR3_Val);	
 LCD_DisplayStringLine(Line2,string);


  while (1)
  {
	  KEY_Scan();
	
	  if(Receive==1)
	  {
	  Receive=0;
	  LCD_DisplayStringLine(Line6,RX_Buff);
	  BHH=(RX_Buff[3]-48)*10+RX_Buff[4]-48;
	  BMM=(RX_Buff[6]-48)*10+RX_Buff[7]-48;
	  BSS=(RX_Buff[9]-48)*10+RX_Buff[10]-48;  //注意ascii码,故需转化
//	  sprintf((char*)string,"BHH:%d BMM:%d BSS:%d",BHH,BMM,BSS);
//	  LCD_DisplayStringLine(Line9,string);

	  }

	  if (TimeDisplay == 1)
    {
      /* Display current time */
      Time_Display(RTC_GetCounter());
      TimeDisplay = 0;
    }

  
  }
}

void KEY_Scan(void)
{

if(RB1==0)
{
Delay_Ms(10);
if(RB1==0)
{
	if(PA1==0)
	{
	PA1=1;
	TIM2_Configuration(CCR2_Val*10,0);
	LCD_DisplayStringLine(Line4," Channel: PA1       ");

	GPIO_SetBits(GPIOC,GPIO_Pin_9 | GPIO_Pin_10| GPIO_Pin_11 | GPIO_Pin_12| GPIO_Pin_13 | GPIO_Pin_14|GPIO_Pin_15);
	GPIO_ResetBits(GPIOC,GPIO_Pin_8);
	GPIO_SetBits(GPIOD,GPIO_Pin_2);
	GPIO_ResetBits(GPIOD,GPIO_Pin_2);
	}

	else if(PA1==1)
	{
	PA1=0;
	TIM2_Configuration(0,0);
	LCD_DisplayStringLine(Line4," Channel: None      ");

	GPIO_SetBits(GPIOC,GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10| GPIO_Pin_11 | GPIO_Pin_12| GPIO_Pin_13 | GPIO_Pin_14|GPIO_Pin_15);
	GPIO_SetBits(GPIOD,GPIO_Pin_2);
	GPIO_ResetBits(GPIOD,GPIO_Pin_2);
	}

}
while(!RB1);

}

else if(RB2==0)
{
Delay_Ms(10);
if(RB2==0)
{
	CCR2_Val+=10;
	if(CCR2_Val>=100)
	{
	CCR2_Val=10;
	}
	Delay_Ms(5);
	IIC_Write(0x00,CCR2_Val);
	sprintf((char*)string," PWM-PA1: %.2d%",CCR2_Val);
    LCD_DisplayStringLine(Line1,string);
	if(PA1==1)
	{
	 TIM2_Configuration(CCR2_Val*10,0);	
	}

}
while(!RB2);

}

else if(R3==0)
{
Delay_Ms(10);
if(RB3==0)
{				 
 if(PA2==0)
 {
 PA2=1;
 LCD_DisplayStringLine(Line4," Channel: PA2         ");
 USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
  /* Disable the USARTz */
 USART_Cmd(USART2, DISABLE);				 //因为usart与pwm共用引脚PA2
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, DISABLE);
 TIM2_Configuration(0,CCR3_Val*10);

 	GPIO_SetBits(GPIOC,GPIO_Pin_8 | GPIO_Pin_10| GPIO_Pin_11 | GPIO_Pin_12| GPIO_Pin_13 | GPIO_Pin_14|GPIO_Pin_15);
	GPIO_ResetBits(GPIOC,GPIO_Pin_9);
	GPIO_SetBits(GPIOD,GPIO_Pin_2);
	GPIO_ResetBits(GPIOD,GPIO_Pin_2);
 }

 else if(PA2==1)
 {
   PA2=0;
   TIM2_Configuration(0,0);
   LCD_DisplayStringLine(Line4," Channel: None       ");
   USART2_Configuration();

    GPIO_SetBits(GPIOC,GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10| GPIO_Pin_11 | GPIO_Pin_12| GPIO_Pin_13 | GPIO_Pin_14|GPIO_Pin_15);
	GPIO_SetBits(GPIOD,GPIO_Pin_2);
	GPIO_ResetBits(GPIOD,GPIO_Pin_2);

 }

}
while(!RB3);

}

else if(RB4==0)
{
Delay_Ms(10);
if(RB4==0)
{
	CCR3_Val+=10;
	if(CCR3_Val>=100)
	{
	CCR3_Val=10;
	}
	Delay_Ms(5);
	IIC_Write(0x01,CCR3_Val);
	sprintf((char*)string," PWM-PA2: %.2d%",CCR3_Val);
    LCD_DisplayStringLine(Line2,string);
	if(PA2==1)
	{
	 TIM2_Configuration(CCR3_Val*10,0);	
	}

  

}
while(!RB4);

}


}

void Time_Display(uint32_t TimeVar)
{
  uint32_t THH = 0, TMM = 0, TSS = 0;
  
  /* Reset RTC Counter when Time is 23:59:59 */
  if (RTC_GetCounter() == 0x0001517F)
  {
     RTC_SetCounter(0x0);
     /* Wait until last write operation on RTC registers has finished */
     RTC_WaitForLastTask();
  }
  
  /* Compute  hours */
  THH = TimeVar / 3600;
  /* Compute minutes */
  TMM = (TimeVar % 3600) / 60;
  /* Compute seconds */
  TSS = (TimeVar % 3600) % 60;
  if(THH==BHH)
  {
  	if(TMM==BMM)
	{	
		if(TSS==BSS)
		{
		 if(RX_Buff[14]=='1')
		 {
		 TIM2_Configuration(CCR2_Val*10,0);
	     LCD_DisplayStringLine(Line4," Channel: PA1       "); 
		  
		 		GPIO_SetBits(GPIOC,GPIO_Pin_9 | GPIO_Pin_10| GPIO_Pin_11 | GPIO_Pin_12| GPIO_Pin_13 | GPIO_Pin_14|GPIO_Pin_15);
				GPIO_ResetBits(GPIOC,GPIO_Pin_8);
				GPIO_SetBits(GPIOD,GPIO_Pin_2);
				GPIO_ResetBits(GPIOD,GPIO_Pin_2);
		 }
		 else if(RX_Buff[14]=='2')
		 {
		 	 
			 LCD_DisplayStringLine(Line4," Channel: PA2         ");
			 USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
			  /* Disable the USARTz */
			 USART_Cmd(USART2, DISABLE);				 //因为usart与pwm共用引脚PA2
			 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, DISABLE);
			 TIM2_Configuration(0,CCR3_Val*10);


				GPIO_SetBits(GPIOC,GPIO_Pin_8 | GPIO_Pin_10| GPIO_Pin_11 | GPIO_Pin_12| GPIO_Pin_13 | GPIO_Pin_14|GPIO_Pin_15);
				GPIO_ResetBits(GPIOC,GPIO_Pin_9);
				GPIO_SetBits(GPIOD,GPIO_Pin_2);
				GPIO_ResetBits(GPIOD,GPIO_Pin_2);

			 	

		 
		 }

		
		}
		else if(TSS==BSS+RX_Buff[16]-48)	
		{
		  TIM2_Configuration(0,0);
	      LCD_DisplayStringLine(Line4," Channel: None      ");
		  if(RX_Buff[14]=='2')
		  {
		  	USART2_Configuration();
		  }

		  GPIO_SetBits(GPIOC,GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10| GPIO_Pin_11 | GPIO_Pin_12| GPIO_Pin_13 | GPIO_Pin_14|GPIO_Pin_15);
		  GPIO_SetBits(GPIOD,GPIO_Pin_2);
		  GPIO_ResetBits(GPIOD,GPIO_Pin_2);
		
		}
	
	}

  
  }
  sprintf((char*)string," Time: %.2d:%.2d:%.2d", THH, TMM, TSS);

  LCD_DisplayStringLine(Line3,string);
}


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

④、中断服务函数

u8 Counter=3;


void USART2_IRQHandler(void)     
{
u8 temp;

  if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
  {
  	USART_ClearITPendingBit(USART2, USART_IT_RXNE);
    /* Read one byte from the receive data register */
    temp = USART_ReceiveData(USART2);

    if(temp == 'S')				//注意是字符所以单引号,下同
    {
	   RX_Buff[Counter]=temp;	
       Receive=1;
	   Counter=3;
    }
	else
	{
	RX_Buff[0]=' ';
	RX_Buff[1]=' ';
	RX_Buff[2]=' ';	 //为了美观,显示三个空格
	RX_Buff[Counter]=temp;
	Counter++;
	
	}
  }
  
  
}

void RTC_IRQHandler(void)
{
  if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
  {
    /* Clear the RTC Second interrupt */
    RTC_ClearITPendingBit(RTC_IT_SEC);
    /* Enable time update */
    TimeDisplay = 1;

    /* Wait until last write operation on RTC registers has finished */
    RTC_WaitForLastTask();
    
  }
}

⑤、代码分析

本次考试的难点在于,由于usart接受引脚为PA2,而PWM2的输出引脚也是PA2这就导致了,当我们需要PWM波时需要关闭USART功能,即失能usart的接受中断,开启命令和时钟;其次usart接收到的是字符串,即ascii码故在处理时尤其在转换为数字时需要减去48,同时为了美观接收到的前三个字符设置为空格,使其在lcd上显示不至于靠边;另外为了关闭开启usart的方便特地将其初始化单独出来。

具体程序和试题

你可能感兴趣的:(蓝桥杯)