900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 嵌入式设计与开发项目-液位检测告警系统

嵌入式设计与开发项目-液位检测告警系统

时间:2021-01-11 10:31:51

相关推荐

嵌入式设计与开发项目-液位检测告警系统

嵌入式设计与开发项目-液位检测告警系统

一、实现的功能二、根据功能实现代码1、主文件main.c2、void KEY_Proc(void)按键处理程序设计3、LCD处理程序设计5、ADC处理程序设计6、UART处理程序设计7、LED处理程序设计8、USART2处理程序设计 三、实现功能过程的注意与学习点1、注意点2、学习的知识点

一、实现的功能

①液位检测,通过ADC外设检测电位器的电压模拟液位传感器,并通过公式计算出液位高度;②阈值设置,通过按键外设设置液位的阈值;③阈值保存,通过IIC外设把数据保存到AT12C02存储器中;④串口的查询和输出,通过串口外设发送特定的字符‘C’、‘S’分别查询液位高度和等级以及阈值。液位等级改变时串口发送实时液位数据;⑤状态指示,通过LED外设的LD1以1S间隔闪烁表示运行状态指示灯,LD2以0.2S间隔闪烁5次表示液位等级发送变化,LD3以0.2S间隔闪烁5次表示串口接收到信息;

二、根据功能实现代码

1、主文件main.c

#include "stm32f10x.h"#include "lcd.h"#include "led.h"#include "key.h"#include "usart.h"#include "i2c.h"#include "adc.h"typedef unsigned char uchar;typedef unsigned int uint;uint uiAdc_Val;//R37模拟液位传感器的ADC值uchar ucHeight,ucLevel,ucLevel1;//液位高度、液位等级uchar ucState,pucStr[21],pucTh[3],pucRcv[1];//LCD显示缓冲区、液位阈值、串口缓冲区uchar ucLed,ucLd2,ucLd3,ucNum = 10;//点亮LEDuchar ucSec,ucSec1,ucKey_Long; //保存ms、s,长按标志位unsigned long ulTick_ms;//滴答定时器的计数void KEY_Proc(void);void LCD_Proc(void);void ADC_Proc(void);void UART_Proc(void);//Main Bodyint main(void){SysTick_Config(SystemCoreClock/1000);//设置系统滴答时钟1ms并使能中断KEY_Init();//按键初始化LED_Init();//LED初始化STM3210B_LCD_Init(); //LCD初始化LCD_Clear(Blue); //把屏幕刷新为蓝色LCD_SetBackColor(Blue); //设置字体背景为蓝色LCD_SetTextColor(White); //字体设置为白色USART2_Init(9600); //串口初始化i2c_init(); //IIC初始化ADC1_Init(); //ADC初始化i2c_read(pucTh,0,3); //AT24C02读取从地址0开始的3个字节的数据if(pucTh[0] > 100)pucTh[0] = 10;if(pucTh[1] > 100)pucTh[0] = 20;if(pucTh[2] > 100)pucTh[0] = 30;while(1){KEY_Proc();//按键相对应的功能LCD_Proc(); //LCD相对应的功能ADC_Proc();//ADC采集相对应的功能UART_Proc();//串口相对应的功能}}/***********************************************************************************************函数:void KEY_Proc(void)*功能:按键B1设置键,B2切换键,B3加键,B4减键*输入:无*输出:无*特殊说明:各按键互不影响**********************************************************************************************/void KEY_Proc(void){uchar ucKey_Val;ucKey_Val = KEY_Scan();//检测那个按键按下if(ucKey_Val != ucKey_Long)ucKey_Long = ucKey_Val;elseucKey_Val = 0;//防止长按switch(ucKey_Val){case 1://B1:设置键if(!ucState)ucState = 1;else{if((pucTh[0]) < pucTh[1] && pucTh[1] < pucTh[2]){LCD_DisplayStringLine(Line3,(u8*)" ");i2c_write(pucTh , 0 , 3);//pucTh阈值存到AT24C02ucState = 0;}else{LCD_SetTextColor(Red);LCD_DisplayStringLine(Line3,(u8*)" Threshold Error ");//设置阈值有误LCD_SetTextColor(White); }}break;case 2://B2:切换键if(ucState)if(++ucState == 4)ucState = 1;break;case 3://B3:阈值加if(ucState)if(pucTh[ucState-1] < 95)pucTh[ucState-1] +=5;break;case 4://B3:阈值减if(ucState)if(pucTh[ucState-1] > 5)pucTh[ucState-1] -=5;break;}}/***********************************************************************************************函数:void LCD_Proc(void)*功能:LCD屏幕显示函数*输入:无*输出:无*特殊说明:无**********************************************************************************************/void LCD_Proc(void){float temp;if(!ucState)//0显示状态界面,不等于0显示设置界面{LCD_DisplayStringLine(Line1,(u8*)" Liquid Level ");sprintf((char*)pucStr," Height:%03ucm ",ucHeight);LCD_DisplayStringLine(Line4,pucStr);temp = (float)uiAdc_Val * 3.3 /4095;sprintf((char*)pucStr," VR37: %4.3fV",temp);LCD_DisplayStringLine(Line6,pucStr);sprintf((char*)pucStr," Level: %01u ",ucLevel);LCD_DisplayStringLine(Line8,pucStr);}else{LCD_DisplayStringLine(Line1,(u8*)" Threshold Setup ");//索引在第1个阈值设置sprintf((char*)pucStr," Threshold 1: %02ucm ",pucTh[0]);if(ucState == 1)LCD_SetBackColor(Red);LCD_DisplayStringLine(Line4,pucStr);LCD_SetBackColor(Blue);//索引在第2个阈值设置sprintf((char*)pucStr," Threshold 2: %02ucm ",pucTh[1]);if(ucState == 2)LCD_SetBackColor(Red);LCD_DisplayStringLine(Line6,pucStr);LCD_SetBackColor(Blue);//索引在第3个阈值设置sprintf((char*)pucStr," Threshold 3: %02ucm ",pucTh[2]);if(ucState == 3)LCD_SetBackColor(Red);LCD_DisplayStringLine(Line8,pucStr);LCD_SetBackColor(Blue);}}/***********************************************************************************************函数:void ADC_Proc(void)*功能:ADC采集电位器R37的电压信号*输入:无*输出:无*特殊说明:无**********************************************************************************************/void ADC_Proc(void){if(!ucState && ucSec != ucSec1){ucSec1 = ucSec;uiAdc_Val = ADC1_Conv();//获取装换值ucHeight = uiAdc_Val*100/4095;//计算液位高度 ADC_Val = V * 4095 / 3.3if(ucHeight < pucTh[0])ucLevel = 0;else if(ucHeight < pucTh[1])ucLevel = 1;else if(ucHeight < pucTh[2])ucLevel = 2;elseucLevel = 3;if(ucLevel != ucLevel1){if(ucLevel > ucLevel1)//液位升高printf("A:H%02u+L%01u+U\r\n",ucHeight,ucLevel);else//液位减低printf("A:H%02u+L%01u+D\r\n",ucHeight,ucLevel);ucLevel1 = ucLevel;ucLd2 = 1;//等级改变}}}/***********************************************************************************************函数:void UART_Proc(void)*功能:串口查询与发送函数*输入:无*输出:无*特殊说明:无**********************************************************************************************/void UART_Proc(void){if(pucRcv[0] == 'C')printf("C:H%02u+L%01u\r\n",ucHeight,ucLevel);if(pucRcv[0] == 'S')printf("S:TL%02u+TM%02u+TH%02u\r\n",pucTh[0],pucTh[1],pucTh[2]);if(pucRcv[0] == 'C' || pucRcv[0] == 'S')ucLd3 = 1;//串口查询pucRcv[0] = 0;}/***********************************************************************************************函数:void SysTick_Handler(void)*功能:滴答定时器中断函数*输入:无*输出:无*特殊说明:每1模式进入一次**********************************************************************************************/void SysTick_Handler(void){ulTick_ms++;if(ulTick_ms%1000 == 0){ucSec++;ucLed ^=1;//LD1闪烁}if(ucLd2){if(ulTick_ms%200 == 0){if(ucNum--)ucLed ^= 2;//LD2闪烁5次else{ucLd2 = 0;ucNum = 10;}}}if(ucLd3){if(ulTick_ms%200 == 0){if(ucNum--)ucLed ^= 4;//LD3闪烁5次else{ucLd3 = 0;ucNum = 10;}}}LED_Disp(ucLed);}/***********************************************************************************************函数:void USART2_IRQHandler( void )*功能:接收串口2的数据*输入:无*输出:无*特殊说明:接收串口2的中断服务函数**********************************************************************************************/void USART2_IRQHandler(void){pucRcv[0] = USART_ReceiveData(USART2);}

主函数分析:❤️ ❤️ ❤️

定义全局变量,在当前源文件的函数可以交叉赋值和使用。主控芯片的每个外设尽量模块化,每个函数负责一个外设的功能。定义了三个ucLevel1、ucSec1、ucKey_Long变量,分别保存上一次的液位等级、时间、按键键值,从而实时判断液位等级延时1S防止长按的功能。

2、void KEY_Proc(void)按键处理程序设计

/***********************************************************************************************函数:void KEY_Proc(void)*功能:按键B1设置键,B2切换键,B3加键,B4减键*输入:无*输出:无*特殊说明:各按键互不影响**********************************************************************************************/void KEY_Proc(void){uchar ucKey_Val;ucKey_Val = KEY_Scan();//检测那个按键按下if(ucKey_Val != ucKey_Long)ucKey_Long = ucKey_Val;elseucKey_Val = 0;//防止长按switch(ucKey_Val){case 1://B1:设置键if(!ucState)ucState = 1;else{if((pucTh[0]) < pucTh[1] && pucTh[1] < pucTh[2]){LCD_DisplayStringLine(Line3,(u8*)" ");i2c_write(pucTh , 0 , 3);//pucTh阈值存到AT24C02ucState = 0;}else{LCD_SetTextColor(Red);LCD_DisplayStringLine(Line3,(u8*)" Threshold Error ");//设置阈值有误LCD_SetTextColor(White); }}break;case 2://B2:切换键if(ucState)if(++ucState == 4)ucState = 1;break;case 3://B3:阈值加if(ucState)if(pucTh[ucState-1] < 95)pucTh[ucState-1] +=5;break;case 4://B3:阈值减if(ucState)if(pucTh[ucState-1] > 5)pucTh[ucState-1] -=5;break;}}

按键KEY简要分析:❤️ ❤️

定义ucKey_Long标志位,防止长按一直执行该按键的功能;定义pucTh[3]数据可以进行函数i2c_write的(unsigned char*)传参,把数据按顺序存到AT24C02存储器中;如果ucState大于0,判断是设置界面,从而可以执行切换键、阈值加、阈值减的操作。巧妙地使用ucState判断当前切换选择的液位等级阈值设置,并可使用到阈值数组pucTh的设置。

3、LCD处理程序设计

/***********************************************************************************************函数:void LCD_Proc(void)*功能:LCD屏幕显示函数*输入:无*输出:无*特殊说明:无**********************************************************************************************/void LCD_Proc(void){float temp;if(!ucState)//0显示状态界面,不等于0显示设置界面{LCD_DisplayStringLine(Line1,(u8*)" Liquid Level ");sprintf((char*)pucStr," Height:%03ucm ",ucHeight);LCD_DisplayStringLine(Line4,pucStr);temp = (float)uiAdc_Val * 3.3 /4095;sprintf((char*)pucStr," VR37: %4.3fV",temp);LCD_DisplayStringLine(Line6,pucStr);sprintf((char*)pucStr," Level: %01u ",ucLevel);LCD_DisplayStringLine(Line8,pucStr);}else{LCD_DisplayStringLine(Line1,(u8*)" Threshold Setup ");//索引在第1个阈值设置sprintf((char*)pucStr," Threshold 1: %02ucm ",pucTh[0]);if(ucState == 1)LCD_SetBackColor(Red);LCD_DisplayStringLine(Line4,pucStr);LCD_SetBackColor(Blue);//索引在第2个阈值设置sprintf((char*)pucStr," Threshold 2: %02ucm ",pucTh[1]);if(ucState == 2)LCD_SetBackColor(Red);LCD_DisplayStringLine(Line6,pucStr);LCD_SetBackColor(Blue);//索引在第3个阈值设置sprintf((char*)pucStr," Threshold 3: %02ucm ",pucTh[2]);if(ucState == 3)LCD_SetBackColor(Red);LCD_DisplayStringLine(Line8,pucStr);LCD_SetBackColor(Blue);}}

LCD屏幕简要分析:❤️ ❤️

如果ucState为0,是液位状态显示界面,否则是设置界面。巧妙使用空格重叠另一个界面显示数据;

5、ADC处理程序设计

/***********************************************************************************************函数:void ADC_Proc(void)*功能:ADC采集电位器R37的电压信号*输入:无*输出:无*特殊说明:无**********************************************************************************************/void ADC_Proc(void){if(!ucState && ucSec != ucSec1){ucSec1 = ucSec;uiAdc_Val = ADC1_Conv();//获取装换值ucHeight = uiAdc_Val*100/4095;//计算液位高度 ADC_Val = V * 4095 / 3.3if(ucHeight < pucTh[0])ucLevel = 0;else if(ucHeight < pucTh[1])ucLevel = 1;else if(ucHeight < pucTh[2])ucLevel = 2;elseucLevel = 3;if(ucLevel != ucLevel1){if(ucLevel > ucLevel1)//液位升高printf("A:H%02u+L%01u+U\r\n",ucHeight,ucLevel);else//液位减低printf("A:H%02u+L%01u+D\r\n",ucHeight,ucLevel);ucLevel1 = ucLevel;ucLd2 = 1;//等级改变}}}

ADC模拟液位电压简要分析:❤️ ❤️

在液位显示界面,进行1S采集一次模拟液位电压电位器;根据获取到的AD值进行公式转换为高度,判断高度在液位的那个阈值范围内,从而得知当前的液位等级;通过ucLevel1判断液位等级是否发送改变,根据液位改变给串口发送相对应的消息,并进行Ld2的5次闪烁

6、UART处理程序设计

/***********************************************************************************************函数:void UART_Proc(void)*功能:串口查询与发送函数*输入:无*输出:无*特殊说明:无**********************************************************************************************/void UART_Proc(void){if(pucRcv[0] == 'C')printf("C:H%02u+L%01u\r\n",ucHeight,ucLevel);if(pucRcv[0] == 'S')printf("S:TL%02u+TM%02u+TH%02u\r\n",pucTh[0],pucTh[1],pucTh[2]);if(pucRcv[0] == 'C' || pucRcv[0] == 'S')ucLd3 = 1;//串口查询pucRcv[0] = 0;}

串口UART简要分析:❤️ ❤️

判断串口接收到的字符,是否和系统设置参数一致,执行相对应的功能。接收完之后,重新把pucRcv缓冲区恢复默认值。

7、LED处理程序设计

/***********************************************************************************************函数:void SysTick_Handler(void)*功能:滴答定时器中断函数*输入:无*输出:无*特殊说明:每1模式进入一次**********************************************************************************************/void SysTick_Handler(void){ulTick_ms++;if(ulTick_ms%1000 == 0){ucSec++;ucLed ^=1;//LD1闪烁}if(ucLd2){if(ulTick_ms%200 == 0){if(ucNum--)ucLed ^= 2;//LD2闪烁5次else{ucLd2 = 0;ucNum = 10;}}}if(ucLd3){if(ulTick_ms%200 == 0){if(ucNum--)ucLed ^= 4;//LD3闪烁5次else{ucLd3 = 0;ucNum = 10;}}}LED_Disp(ucLed);}

系统滴答定时器简要分析:❤️ ❤️

设置了1ms,中断进入这个函数一次,实现精准的计时。如果液位等级发送变化,则LD2闪烁5次;如果接收到串口的指令,则LD3进行闪烁5次,闪烁完后清除标志位。

8、USART2处理程序设计

/***********************************************************************************************函数:void USART2_IRQHandler( void )*功能:接收串口2的数据*输入:无*输出:无*特殊说明:接收串口2的中断服务函数**********************************************************************************************/void USART2_IRQHandler(void){pucRcv[0] = USART_ReceiveData(USART2);}

简要分析:❤️ ❤️

串口中断函数,串口接收到数据进入中断把数据保存到pucRcv数组中。

三、实现功能过程的注意与学习点

1、注意点

①如何定义全局变量,使各个外设功能耦合在一起!

2、学习的知识点

①实现模块化编程,每个外设的功能单独定义一个函数;②巧妙地定义一个数组,保存液位各个等级的阈值,还实现阈值的加减操作;③学会定义标志位,判断当前状态是否发生改变,防止长按按键、液位等级变化检测等功能;④实现串口的中断接收服务函数;

❤️ ❤️ ❤️ ❤️ ❤️ ❤️

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。