蓝桥杯嵌入式第六届省赛:电压测量监控设备

```c
```c
/*赛题:第六届:电压测量监控设备
**作者:*wj  
**时间:2021-2-15
**注意:设备通过串口发送给PC,思路和LCD动态显示一样(记得添加"stdio.h")
        sprintf((char*)time,"%.2f+%.1f+%0.2d%0.2d%0.2d\r\n",ADC_Value, K/10, TH,TM,TS);
*/
**第一部分**
#include "stm32f10x.h"
#include "lcd.h"
#include "stdio.h"
#include "led.h"
#include "key.h"
#include "adc.h"
#include "i2c.h"
#include "rtc.h"
#include "usart.h"

u8 text1[20];                  //字符串数组1
u8 RXBUF[20];                  //串口接收数组
u8 RXOVER=0;                   //串口接收标志0:没有接收     1:接收        
u8 RXCOUNT=0;                  //串口数组计数变量 
u8 i;                          //循环变量
u32 TimingDelay = 0;           //定时延时变量     
u8 TimeDisplay=0;              //RTC中断标志变量
float ADC_Value;               //采集模拟电压量 
float K=1;                     //参数扩大10倍,方便后面计算保存
u8 Key1_flag = 0;              //“B1”按键设定为“功能”按键
u8 Key2_flag = 0;              //“B2”按键设定为“设置”按键
u8 Key3_flag = 0;              //“B3”切换选择时、分、秒
u8 TH = 00, TM = 00, TS = 00;  //定时上报时间变量
u8 LED1_on =0;                 //LED1闪烁标志位 1:亮 0:灭
u8 LED1_off =0;                //LED1闪烁标志位 1:灭 0:亮

//函数的声明
void Delay_Ms(u32 nTime);
void LCD_Init(void);
void LCD_Display(void);
void RCC_Configuration(void);
void Scan_Key(void);
void _24c02_Write(u16 addr,u16 data);
u16 _24c02_Read(u16 addr);
//Main Body
int main(void)
{
	i2c_init();
    LCD_Init();
	RCC_Configuration();
	LED_Configuration();
	KEY_Configuration();
	ADC_Configuration();
	RTC_Configuration();
	USART2_Configuration();
	while(1)
	{
	  Scan_Key();
		LCD_Display();
	}
}
/***********************LCD_Init函数**************************************/	
void LCD_Init(void)
{
	STM3210B_LCD_Init();
	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);
	SysTick_Config(SystemCoreClock/1000);	
  K= _24c02_Read(0x01);	               //上电获取上次断电存储数值
}
/***********************LCD_Display函数**************************************/	
void LCD_Display(void)
{		

  if(RXOVER)                    //串口接收
	{
		RXOVER = 0;
		if(RXBUF[0] == 'k')         //判断接收的内容
		{
		  K = (RXBUF[3] - 48 );
		}
		Send_String((u8*)"ok\r\n"); //返回给PC机
		_24c02_Write(0x01,K);       //写入到存储器中	
		Delay_Ms(10);
		for(i=0;i<20;i++)           //RXBUF[]数组清零
		{
			RXBUF[i]=0;		
		}	
		USART_ITConfig(USART2,USART_IT_RXNE, ENABLE);
	}
	if(Key2_flag == 0)  //指示灯闪烁报警功能状态和系统时间,
	{
		ADC_Value = Get_ADC(8) * 3.3 / 0xfff;       //电压计算法:ADC采集精度12位,所以是0xfff,电源电压为3.3v
		sprintf((char*)text1,"   V1:%.2f      ",ADC_Value);
    LCD_DisplayStringLine(Line3,text1); 
		sprintf((char*)text1,"   k :%.1f         ",K / 10);
    LCD_DisplayStringLine(Line4,text1); 	
    if(Key1_flag == 0)
		{
		  LCD_DisplayStringLine(Line5 ,"   LED: ON      ");
		}
    else if(Key1_flag == 1)
		{
		  LCD_DisplayStringLine(Line5 ,"   LED: OFF     ");
		}
    Time_Display(RTC_GetCounter());	              //时间的获取并且显示
	}

	if(Key2_flag == 1)  //设置界面
	{
    LCD_DisplayStringLine(Line3 ,"      Setting      ");
    switch(Key3_flag )//按键 B3 切换选择时、分、秒
		{
			case 1: sprintf((char*)text1,"       %0.2d:      ",TH);
              LCD_DisplayStringLine(Line5,text1); 
		          break;
			case 2: sprintf((char*)text1,"         %0.2d:    ",TM);
              LCD_DisplayStringLine(Line5,text1); 
		          break; 
			case 3: sprintf((char*)text1,"           %0.2d   ",TS);
              LCD_DisplayStringLine(Line5,text1); 
		          break;
			default:sprintf((char*)text1,"      %0.2d:%0.2d:%0.2d   ",TH,TM,TS);
              LCD_DisplayStringLine(Line5,text1); 
		}
	}	
//报警显示控制
	if(Key1_flag == 0)
	{
		if((ADC_Value > 3.3 * K / 10))  //当 ADC_Value>VDD*k 时,指示灯 LD1 以 0.2 秒为间隔闪烁
		{
			if(LED1_on == 1)
			{
				LED1_on =0;
				LED_Control(LED1,0);		
			}
			else if(LED1_off == 1)
			{
				LED1_off =0;
				LED_Control(LED1,1);		
			}		
		}
		else
		{
		  LED_Control(LED1,1);        //否则关闭
		}
	}	
	else if(Key1_flag == 1)        //闪烁功能可以通过按键关闭
	{
		LED_Control(LED1,1);
	}
}

/************************按键扫描函数**************************************/
void Scan_Key(void)
{
	static u8 k4_sum = 0;
	if(K1 == 0)
	{
	  Delay_Ms(10);
		if(K1 == 0)
		{
			if(Key1_flag == 0)
			{
				Key1_flag =1;			
			}
			else
			{
			  Key1_flag =0;
			}				
		}
	}
	while(K1 == 0);
	if(K2 == 0)
	{
	  Delay_Ms(10);
		if(K2 == 0)
		{
			if(Key2_flag == 0)
			{
				Key2_flag = 1;			
			}
			else
			{
			   Key2_flag = 0;
			}		
		}
	}
	while(K2 == 0)
	{
		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(K3 == 0)
	{
	  Delay_Ms(10);
		if(K3 == 0)
		{
			if(Key3_flag == 0)
			{
				Key3_flag = 1;			
			}
			else if(Key3_flag == 1)
			{
				Key3_flag = 2;			
			}
			else if(Key3_flag == 2)
			{
				Key3_flag = 3;			
			}			
      else	
      {
			  Key3_flag = 0;
			}						
		}
	}
	while(K3 == 0);
	if(K4 == 0)
	{
		k4_sum++;
		if(k4_sum == 1)        //单次短按
		{
			if(Key3_flag == 1)
			{
				if(TH <23)
			    TH +=1;
				else
				TH = 0;
			}
			else if(Key3_flag == 2)
			{
				if(TM <59)
			  TM +=1;
				else
				TM = 0;
			}
			else if(Key3_flag == 3)
			{
				if(TS <59)
			    TS +=1;
				else
				TS = 0;							  
			}			
		}
		else if(k4_sum == 20)   //连续长按
		{
			if(Key3_flag == 1)
			{
			    if(TH <23)
			    TH +=1;
				else
				TH = 0;
			}
			else if(Key3_flag == 2)
			{
				if(TM <59)
			    TM +=1;
				else
				TM = 0;
			}
			else if(Key3_flag == 3)
			{
				if(TS <59)
			    TS +=1;
				else
				TS = 0;	
			}						
		  k4_sum = 15;
		}		
	}
	else
  { 
	  k4_sum = 0;
	}
}
/************************外设时钟函数**************************************/	
void RCC_Configuration(void)
{
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB , ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD , ENABLE);
	
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 , ENABLE);
  /* Enable PWR and BKP clocks */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
  /* Enable USART2 clocks */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
}
/***********************_24c02_Write函数**************************************/	
/*
入口参数:存储地址(0x00 - 0xff)  存储的内容
*/
void _24c02_Write(u16 addr,u16 data)
{
	I2CStart();
	I2CSendByte(0xa0);
	I2CSendAck();
	I2CSendByte(addr);	
	I2CSendAck();
	I2CSendByte(data);	
 	I2CSendAck();
  I2CStop();
}
/***********************_24c02_Read函数**************************************/	
/*
入口参数:存储地址(0x00 - 0xff)
*/
u16 _24c02_Read(u16 addr)
{
	u16 temp;
	I2CStart();
	I2CSendByte(0xa0);
	I2CSendAck();
	I2CSendByte(addr);	
	I2CSendAck();

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


//延时函数
void Delay_Ms(u32 nTime)
{
	TimingDelay = nTime;
	while(TimingDelay != 0);	
}

第二部分

#ifndef __USART_H
#define __USART_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
void USART2_Configuration(void);
void Send_String(u8* str);
#endif 

#include "usart.h"

void USART2_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;	
  USART_InitTypeDef USART_InitStructure;	
  NVIC_InitTypeDef NVIC_InitStructure;
	
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Configure USART2 CTS and USART2 Rx as input floating */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  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;

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

  USART_Init(USART2, &USART_InitStructure);
  /* Enable the USART2 */
  USART_Cmd(USART2, ENABLE);	
  USART_ITConfig(USART2,USART_IT_RXNE, ENABLE);	
	
}
/**
功能:发送字符串
入口参数:发送内容
**/	
void Send_String(u8* str)
{
	u8 index=0;
	do
	{
		USART_SendData(USART2,str[index]);
		while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
		index++;	
	}
	while(str[index]!= 0);
}

#ifndef __RTC_H
#define __RTC_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "stdio.h"
#include "lcd.h"
#include "usart.h"
#define HH 23
#define MM 59
#define SS 55

void RTC_Configuration(void);
void Time_Display(uint32_t TimeVar);
#endif 

#include "rtc.h"
u8 time[20];
extern u8 TH, TM, TS;
extern float ADC_Value;
extern float K;    
void RTC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  PWR_BackupAccessCmd(ENABLE);
  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(40000-1); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */

  /* Wait until last write operation on RTC registers has finished */
  RTC_WaitForLastTask();	
	
  RTC_SetCounter(HH*3600 + MM*60 + SS);
  RTC_WaitForLastTask();
	
  NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
	
}

void Time_Display(uint32_t TimeVar)
{
  uint32_t THH = 0, TMM = 0, TSS = 0;
  /* Compute  hours */
  THH = TimeVar / 3600;
  /* Compute minutes */
  TMM = (TimeVar % 3600) / 60;
  /* Compute seconds */
  TSS = (TimeVar % 3600) % 60;
	sprintf((char*)time,"   Time:%0.2d:%0.2d:%0.2d",THH, TMM, TSS);
	LCD_DisplayStringLine(Line6 ,time);	
//设备自动上报电压时间判断
  if(TH == THH)
	{
	  if(TM == TMM)
		{
		   if(TS == TSS)
			 {
					sprintf((char*)time,"%.2f+%.1f+%0.2d%0.2d%0.2d\r\n",ADC_Value, K/10, TH,TM,TS);
					Send_String(time);				 		 
			 }
		}
	}		
}

#ifndef __ADC_H
#define __ADC_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
void ADC_Configuration(void);
u16 Get_ADC(u16 channel);
#endif 

#include "adc.h"

void ADC_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  ADC_InitTypeDef ADC_InitStructure;
  /* Configure PC.04 (ADC Channel14) as analog input -------------------------*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  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);
	
  ADC_Cmd(ADC1, ENABLE);	
	
  ADC_ResetCalibration(ADC1);
  while(ADC_GetResetCalibrationStatus(ADC1));
  ADC_StartCalibration(ADC1);
  while(ADC_GetCalibrationStatus(ADC1));
}
/**
功能:获取模拟输入变量
入口参数:ADC的通道(因为板上配置ADC_Channel_8)
局部变量:u16 temp保存读取的模拟量
返回值:temp保存读取的模拟量
**/	
u16 Get_ADC(u16 channel)
{
  u16 temp;
  ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_239Cycles5);	
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);
  temp = ADC_GetConversionValue(ADC1);	
  while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == 0);
  ADC_SoftwareStartConvCmd(ADC1, DISABLE);
  return 	temp;
}

#ifndef __KEY_H
#define __KEY_H

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
#define K1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)
#define K2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)
#define K3 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1)
#define K4 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_2)
void KEY_Configuration(void);
#endif 

#include "key.h"
void KEY_Configuration(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	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_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_Init(GPIOB, &GPIO_InitStructure);		
}

#ifndef __LED_H
#define __LED_H

/* Includes ------------------------------------------------------------------*/
#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
#define LEDALL GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15

void LED_Configuration(void);
void LED_Control(u16 ledx,u16 led_sta);
#endif 

#include "led.h"
/**
功能:初始化LED管脚
注意:为了防止LCD LED显示的冲突对LCD写函数进行了寄存器的操作
**/	
void LED_Configuration(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	
	GPIO_InitStructure.GPIO_Pin = LEDALL;
	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);		

	GPIO_SetBits(GPIOD,GPIO_Pin_2);
	GPIO_SetBits(GPIOC,LEDALL);
    GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}
/**
功能:控制LED亮灭
入口参数ledx:LED1-LED8
入口参数led_sta:低电平点亮(根据原理图配置)
**/	
void LED_Control(u16 ledx,u16 led_sta)
{
	if(led_sta == 0)
	{
		GPIO_SetBits(GPIOD,GPIO_Pin_2);
		GPIO_ResetBits(GPIOC,ledx);
		GPIO_ResetBits(GPIOD,GPIO_Pin_2);
	}
	else
	{
		GPIO_SetBits(GPIOD,GPIO_Pin_2);
		GPIO_SetBits(GPIOC,ledx);
		GPIO_ResetBits(GPIOD,GPIO_Pin_2);				
	}

}

*wj
发布了9 篇原创文章 · 获赞 6 · 访问量 281

猜你喜欢

转载自blog.csdn.net/weixin_44236302/article/details/104555368
今日推荐