蓝桥杯嵌入式省赛第七届:模拟液位检测告警系统”

/*赛题:第七届:模拟液位检测告警系统”
**作者:*wj  
**时间:2021-2-13
**注意:设备通过串口发送给PC,思路和LCD动态显示一样(记得添加"stdio.h")
*/
**第一部分:逻辑功能实现**
#include "stm32f10x.h"
#include "lcd.h"
#include "led.h"
#include "key.h"
#include "i2c.h"
#include "stdio.h"
#include "usart.h"
#include "adc.h"
u32 TimingDelay = 0;
u8 text1[20];           //字符串数组1
u8 text2[20];           //字符串数组2
u8 RXBUF[20];           //串口接收数组
u8 TXBUF[20];           //串口发送数组
u8 RXOVER = 0;          //串口接收标志0:没有接收     1:接收
u8 RXCOUNT = 0;         //串口数组计数变量      
u8 ADC_Flag =1;         //ADC以1s间隔采集变量  1:采集(初始化为1,是让上电之后就进行一次电压采集)
u8 K1_FLAG = 0;         //B1 按键: “设置”按键   0:液位检测界面    1://阈值设置界面
u8 K2_FLAG = 0;         //B2 按键:切换选择 3 个待修改的阈值,被选中的阈值应突出显示
u8 LED1_on = 0;         //控制LED1开变量
u8 LED1_off = 0;        //控制LED1关变量
u8 Threshold_1 = 30;    //液位范围1
u8 Threshold_2 = 50;    //液位范围2
u8 Threshold_3 = 70;    //液位范围3
u8 Level_old = 0;       //上一次的水平值
u8 Level_now= 0;        //新的水平值
u8 Height = 0;          //液面高度变量
float ADC_Value;        //ADC采集的值(浮点型)
u8 i = 0;               //循环变量
u8 j = 0;               //循环变量
u8 k = 0;               //循环变量

/************************函数引用**************************************/
void Delay_Ms(u32 nTime);
void RCC_Configuration(void);
void LCD_Init(void);
void KEY_Scan(void);
void _24c02_Write(u16 addr, u16 data);
u16 _24c02_Read(u16 addr);
void LCD_Display(void);
void Deal_Data(void);
void LED_Blink(void);
/************************Main Body函数**************************************/
int main(void)
{
	i2c_init();             //IIC初始化
    LCD_Init();             //LCD初始化
	RCC_Configuration();    //所有外设时钟配置
	LED_Configuration();    //LED配置
	KEY_Configuration();    //KEY配置
	USART2_Configuration(); //串口通信2配置
	ADC_Configuration();    //ADC配置
	while(1)
	{
	    KEY_Scan();           //按键扫描函数
		Deal_Data();          //数据处理比较函数
		LCD_Display();        //LCD显示函数
	    LED_Blink();          //LED闪烁配置函数
	}
}
/************************LCD_Init初始化函数**************************************/
void LCD_Init(void)
{
	STM3210B_LCD_Init();
	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);	
	SysTick_Config(SystemCoreClock/1000);	
//第一次给EEPROM写入数据
//		_24c02_Write(0x01,30);
//		Delay_Ms(10);
//		_24c02_Write(0x02,50);
//		Delay_Ms(10);
//		_24c02_Write(0x03,70);
//		Delay_Ms(10);		
//上电之后读取之前存储的数据
	Threshold_1 = _24c02_Read(0x01);
	Delay_Ms(10);
	Threshold_2 = _24c02_Read(0x02);
	Delay_Ms(10);
	Threshold_3 = _24c02_Read(0x03);
}
/************************LCD_Display显示函数**************************************/	
void LCD_Display(void)
{
	if(K1_FLAG == 0)    // 液位检测界面
	{
		LCD_DisplayStringLine(Line2 ,"    Liquid Level    ");
		sprintf((char*)text1,"  Height: %dcm ",Height);
	  LCD_DisplayStringLine(Line4,text1);		
		if(ADC_Flag == 1)
		{
			ADC_Flag =0;
			ADC_Value = Get_ADC(8) * 3.3 /0xfff;
			sprintf((char*)text2,"  ADC_VAL: %.2fV ",ADC_Value);  //保留俩位小数:.2f
			LCD_DisplayStringLine(Line6,text2);
		}			
		sprintf((char*)text1,"  Level: %d ",Level_now);
	    LCD_DisplayStringLine(Line8,text1);	
		_24c02_Write(0x01,Threshold_1);
		Delay_Ms(10);
		_24c02_Write(0x02,Threshold_2);
		Delay_Ms(10);
		_24c02_Write(0x03,Threshold_3);
		Delay_Ms(10);					
	}
	else if(K1_FLAG == 1)  //阈值设置界面
	{
		LCD_SetBackColor(Blue);      //第一行一直显示蓝色
		LCD_DisplayStringLine(Line2 ,"  Parameter Setup    ");	
		if(K2_FLAG == 1)
		{
		  LCD_SetBackColor(Red);    //选中高亮显示
		  sprintf((char*)text1,"  Threshold 1: %dcm   ",Threshold_1);		
          LCD_DisplayStringLine(Line4,text1);			
		}
		else
		{
		  LCD_SetBackColor(Blue);
		  sprintf((char*)text1,"  Threshold 1: %dcm   ",Threshold_1);		
          LCD_DisplayStringLine(Line4,text1);	
		}
		if(K2_FLAG == 2)
		{
		  LCD_SetBackColor(Red);
		  sprintf((char*)text1,"  Threshold 2: %dcm   ",Threshold_2);		
          LCD_DisplayStringLine(Line5,text1);			
		}
		else
		{
		  LCD_SetBackColor(Blue);
		  sprintf((char*)text1,"  Threshold 2: %dcm   ",Threshold_2);		
          LCD_DisplayStringLine(Line5,text1);	
		}		
		if(K2_FLAG == 3)
		{
		  LCD_SetBackColor(Red);
		  sprintf((char*)text1,"  Threshold 3: %dcm   ",Threshold_3);		
          LCD_DisplayStringLine(Line6,text1);			
		}
		else
		{
		  LCD_SetBackColor(Blue);
		  sprintf((char*)text1,"  Threshold 3: %dcm   ",Threshold_3);		
          ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200225154220972.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDIzNjMwMg==,size_16,color_FFFFFF,t_70)LCD_DisplayStringLine(Line6,text1);	
		}
//设置不要的行的颜色为背景颜色
		LCD_SetBackColor(Blue); 
		LCD_DisplayStringLine(Line0 ,"                     ");   
		LCD_DisplayStringLine(Line1 ,"                     ");
		LCD_DisplayStringLine(Line3 ,"                     ");
		LCD_DisplayStringLine(Line7 ,"                     ");
		LCD_DisplayStringLine(Line8 ,"                     ");
		LCD_DisplayStringLine(Line9 ,"                     ");
	}
//串口部分		
	if(RXOVER)
	{		
		RXOVER = 0;
		if(RXBUF[0] == 'C')
		{
            sprintf((char*)TXBUF,"C:H%d+L%d\r\n",Height,Level_now);     
			Send_String(TXBUF);			
		}
		else if(RXBUF[0] == 'S')
		{
            sprintf((char*)TXBUF,"S:TL%d+TM%d+TH%d\r\n",Threshold_1,Threshold_2,Threshold_3);     
			Send_String(TXBUF);			
		}
		for(k=0;k<5;k++)
		{
			LED_Control(LED1,1);
			LED_Control(LED3,0);							
			Delay_Ms(200);
			LED_Control(LED3,1);				
			Delay_Ms(200);
		}
		for(i=0;i<20;i++)
		{
			RXBUF[i] = 0;		
		}
	  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
	}	
}
/************************液位水平比较函数**************************************/	
void Deal_Data(void)
{
	Height = ADC_Value * 100 / 3.3;   //根据题目要求的关系
	if(Height <= Threshold_1)
	{
		Level_now = 0;	
	}
	else if((Threshold_1 < Height ) && (Height <=  Threshold_2))
	{
		Level_now = 1;	
	}
	else if((Threshold_2 < Height ) && (Height <=  Threshold_3))
	{
		Level_now = 2;	
	}
	else if(Threshold_3 < Height )
	{
		Level_now = 3;	
	}	
}

/************************LED闪烁函数**************************************/	
void LED_Blink(void)
{
//LED1_配置
	if(K1_FLAG == 0)        //运行状态下
	{
		if(LED1_on == 1)
		{
			LED1_on =0;
		  LED_Control(LED1,0);		
		}

		if(LED1_off == 1)
		{
			LED1_off=0;
	    LED_Control(LED1,1);		
		}	
	}
	else
  {
	  LED_Control(LED1,1);
	}
//LED2_配置
	if(Level_old != Level_now)
	{
		if(Level_now > Level_old)
			{
				sprintf((char*)TXBUF,"A:H%d+L%d+U\r\n",Height,Level_now);     
				Send_String(TXBUF);							
			}
		if(Level_now < Level_old)
			{
				sprintf((char*)TXBUF,"A:H%d+L%d+D\r\n",Height,Level_now);     
				Send_String(TXBUF);				
			}
		for(j=0;j<5;j++)
		{
			LED_Control(LED1,1);
		    LED_Control(LED2,0);							
            Delay_Ms(200);
		    LED_Control(LED2,1);				
            Delay_Ms(200);		
		}  
	}
	Level_old = Level_now;       //加载上一次的液位等级 
}
/************************外设时钟函数**************************************/	
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_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
}
/************************外设时钟函数**************************************/	
void KEY_Scan(void)
{
	if(K1 == 0)
	{
	  Delay_Ms(10);
		if(K1 == 0)
		{
		  if(K1_FLAG == 0)
			{
			  K1_FLAG = 1;			
			}
			else
			{
			  K1_FLAG = 0;
			}	
		}
		while(K1 == 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(K2 == 0 && K1_FLAG == 1)
	{
	  Delay_Ms(10);
		if(K2 == 0 && K1_FLAG == 1)
		{	
			if(K2_FLAG < 3)
			K2_FLAG++;		
      else
      K2_FLAG=1;				
		}
		while(K2 == 0);
	}	

	if(K3 == 0)
	{
	  Delay_Ms(10);
		if(K3 == 0)
		{
		  if(K2_FLAG == 1)
			{
				if(Threshold_1 < Threshold_2)
				Threshold_1 +=5;
	      else 
				Threshold_1 = Threshold_2;
			}
		  else if(K2_FLAG == 2)
			{
				if(Threshold_2<Threshold_3)
				Threshold_2 +=5;
	      else 
				Threshold_2 = Threshold_3;
			}
			else if(K2_FLAG == 3)
			{
				if(Threshold_3<90)
				Threshold_3 +=5;
	      else 
				Threshold_3 = 95;
			}	
		}
		while(K3 == 0);
	}	

	if(K4 == 0)
	{
	  Delay_Ms(10);
		if(K4 == 0)
		{
		  if(K2_FLAG == 1)
			{
				if(Threshold_1>5)
				Threshold_1 -=5;
	      else 
				Threshold_1 = 5;
			}
		  else if(K2_FLAG == 2)
			{
				if(Threshold_2 >Threshold_1)
				Threshold_2 -=5;
	      else 
				Threshold_2 = Threshold_1;
			}
			else if(K2_FLAG == 3)
			{
				if(Threshold_3>Threshold_2)
				Threshold_3 -=5;
	      else 
				Threshold_3 = Threshold_2;
			}	
		}
		while(K4 == 0);
	}	
}


void _24c02_Write(u16 addr, u16 data)
{

	I2CStart();
	I2CSendByte(0xa0);
	I2CSendAck();
	I2CSendByte(addr);
	I2CSendAck();
	I2CSendByte(data);
    I2CSendAck();
	I2CStop();
}


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

第二部分:初始化配置

#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

#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_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);	
	}
}
#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)
#include "key.h"
void KEY_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /* Configure TIM1_CH1 (PA8) as alternate function push-pull */
  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);
}
#include "usart.h"
void USART2_Configuration(void)
{
  USART_InitTypeDef USART_InitStructure;
  GPIO_InitTypeDef GPIO_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);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  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);
  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
  /* Enable the USART2 */
  USART_Cmd(USART2, 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);
}
#include "adc.h"
void ADC_Configuration(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
  ADC_InitTypeDef  ADC_InitStructure;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;   //模拟输入
  GPIO_Init(GPIOB, &GPIO_InitStructure);

	RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //ADC时钟分频,不能超过14M,所以72/6=12M
  /* 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);
	
  /* 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));
	
}
/**
功能:获取模拟输入变量
入口参数:ADC的通道(因为板上配置ADC_Channel_8)
局部变量:u16 temp保存读取的模拟量
返回值:temp保存读取的模拟量
**/	
u16 Get_ADC(u8 channel)
{
	u16 temp;
  /* ADC1 regular channel14 configuration */ 
  ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_239Cycles5);	
	ADC_SoftwareStartConvCmd(ADC1,ENABLE);
	while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC) == 0);  //转换结束标志ADC_FLAG_EOC
	temp = ADC_GetConversionValue(ADC1);
	ADC_SoftwareStartConvCmd(ADC1,DISABLE);
  return temp;
}

第三部分:中断处理

extern u32 TimingDelay;
extern u8 RXBUF[20];
extern u8 RXOVER;
extern u8 RXCOUNT;
extern u8 LED1_on;
extern u8 LED1_off;
extern u8 ADC_Flag;
void SysTick_Handler(void)
{
	static u16 count1 = 0 ,count2 =0;
	TimingDelay--;
	if(++count1 == 1000)
	{
		count1 = 0;
	  LED1_on	= 1;
		ADC_Flag = 1;
	}
  if(++count2 == 2000)
	{
		count2 = 0;
	  LED1_off = 1;
	}
}


void USART2_IRQHandler(void)
{
	u8 temp;
  if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
  {
	  USART_ClearITPendingBit(USART2,USART_IT_RXNE);
		temp = USART_ReceiveData(USART2);
		if(temp == '\n' || RXCOUNT ==20)
		{
//			RXBUF[RXCOUNT - 1] = 0;         //防止最后出现乱码\r
			RXOVER = 1;			
		  RXCOUNT=0;
			USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
		}
		else
		{
			RXBUF[RXCOUNT] = temp;
		  RXCOUNT++;
		}		
	}
}

在这里插入图片描述

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

猜你喜欢

转载自blog.csdn.net/weixin_44236302/article/details/104498115