文章目录

  • 前言
  • 一、题目
  • 二、模块初始化以及功能分析
    • 1.模块的初始化
    • 2.模块功能分析
  • 三、函数实现
    • 1.void Display(void);
    • 2.void EEPROM_Read(void);void EEPROM_Write(void);
    • 3.uint8_t KEY_Scan(uint8_t mode);
    • 4.void KEY_Handle(uint8_t key);
    • 5.uint16_t Get_ADC(void);
    • 6.void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
    • 7.int main(void);
      • 初始化;
      • while(1);
    • 8.void SysTick_Handler(void);
  • 总结

前言

为了减少篇幅,各模块的初始化均在模块配置中,可以随时去翻看博客,还有function里面的函数,将不再罗列出来,只是截图展示。

一、题目

“模拟液位检测告警系统”通过采集模拟电压信号计算液位高度,并根据用户设定的液位阈值执行报警动作,在液位等级发生变化时,通过串行通讯接口将液位信息发送到 PC 机。系统框图如图 1 所示:

设计任务及要求

1. 液位检测

通过电位器 R37 模拟液位传感器输出电压信号,设备以 1 秒为间隔采集 R37 输出电压,并与用户设定的液位阈值进行比较。假定液位高度与 R37 输出电压之间具有正比例关系:H = VR37*K,当 VR37=3.3V 时,对应液位高度为 100cm。通过液晶显示当前的液位高度、传感器(R37)输出状态和液位等级,液位检测显示界面如图 1 所示:

AD 采集得到的结果应经过软件滤波算法处理,显示结果保留小数点后两位有效数字
2. 液位阈值设定

设备可设定三个液位阈值,对应四个液位等级,阈值由用户通过按键输入,设备保存阈值,并根据此阈值判断液位等级,假 定用户输入的三个液位阈值为 10cm、20cm 和 30cm,液位高度与液位等级的对应关系如下:
2.1 液位高度≤10cm 时,液位等级为 0;
2.2 10cm<液位高度≤20cm 时,液位等级为 1;
2.3 20cm<液位高度≤30cm 时,液位等级为 2;
2.4 液位高度>30cm 时,液位等级为 3。
设备初始液位阈值分别为 30cm、50cm 和 70cm,用户修改阈值后,设备应将此参数保
存在 E2PROM 中,当设备重新上电时,可从 E2PROM 中获取。
3. 液位阈值设定

B1 按键:“设置”按键,按下后进入阈值设定界面(如图 2 所示),再次按下 B1 按键时退出设置界面,保存用户设定的结果到 E2PROM,并返回图 1 所示的液位检测界面。

B2 按键:切换选择 3 个待修改的阈值,被选中的阈值应突出显示。
B3 按键:“加”按键,按下后,被选择的阈值增加 5cm,增加到 95cm 为止。
B4 按键:“减”按键,按下后,被选择的阈值减少 5cm,减少到 5cm 为止。
4. 串口查询与输出功能

使用 STM32 USART2 完成以下串口功能,波特率设置为 9600。
4.1 查询
通过 PC 机向设备发送字符‘C’,设备返回当前液位高度和液位等级;
通过 PC 机向设备发送字符‘S’,设备返回当前设定的三个阈值。
液位高度和等级返回数据格式举例:
“C:H55+L2\r\n”
解析:应答高度、等级查询,液位高度为 55cm,液位等级为 2。
阈值返回数据格式举例:
“S:TL30+TM50+TH70\r\n”
解析:应答阈值查询,设备内保存的三个阈值分别为 30cm、50cm 和 70cm。
4.2 输出
当液位等级发生变化时,设备自动向 PC 机发送当前液位等级、液位高度和液位变化趋势(上升或下降)。
输出数据格式举例:
“A:H55+L2+D\r\n”
解析:液位变化自动发送,液位高度 55cm,液位等级为 2,变化趋势下降。
“A:H55+L2+U\r\n”
解析:液位变化自动发送,液位高度 55cm,液位等级为 2,变化趋势上升。
5. 状态指示

LED 指示灯功能定义如下:
LD1:运行状态指示灯,以 1 秒为间隔亮灭闪烁;
LD2:液位等级变化指示灯,当液位等级发生变化时,LD2 以 0.2 秒为间隔闪烁 5 次;
LD3:通讯状态指示灯,当设备接收到查询指令时,LD3 以 0.2 秒为间隔闪烁 5 次

二、模块初始化以及功能分析

1.模块的初始化

需要用的模块:LCD、IIC、四个按键、LED、ADC(PB15)、USART2

2.模块功能分析

LCD:显示-----》Display();
IIC:读取和存储信息到EEPROM-----》EEPROM_Write();EEPROM_Read();
按键:对参数进行调整-----》KEY_Handle();KEY_Scan();
LED:提示作用-----》LED();
ADC:读取电压值-----》Get_ADC();
USART2:与PC机交互-----》HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);

三、函数实现

1.void Display(void);

当mode = 0时显示页面1;
当mode = 1时显示页面2:
location表示更改参数的位置,使选中的参数那一行显示为绿色。
location = 1:第一个参数,location = 2:第二个参数,location = 3:第三个参数

void Display(void)
{if(mode == 0){LCD_DisplayStringLine(Line1, "   Liquid Level");sprintf((char *)str,"  Height: %.2d cm",Height);LCD_DisplayStringLine(Line3,str);sprintf((char *)str,"  ADC: %.2f V",Adc);LCD_DisplayStringLine(Line5,str);sprintf((char *)str,"  Level:  %.1d",Level);LCD_DisplayStringLine(Line7,str);}else if(mode == 1){LCD_DisplayStringLine(Line1, "   Parameter Setup");if(location == 1) LCD_SetTextColor(Green);sprintf((char *)str," Threshold 1: %.2d cm",shold[0]);LCD_DisplayStringLine(Line4,str);LCD_SetTextColor(Black);if(location == 2)    LCD_SetTextColor(Green);sprintf((char *)str," Threshold 2: %.2d cm",shold[1]);LCD_DisplayStringLine(Line6,str);LCD_SetTextColor(Black);if(location == 3)    LCD_SetTextColor(Green);sprintf((char *)str," Threshold 3: %.2d cm",shold[2]);LCD_DisplayStringLine(Line8,str);LCD_SetTextColor(Black);}
}

2.void EEPROM_Read(void);void EEPROM_Write(void);

存储三个参数到0x00、0x01、0x02。注意延时HAL_Delay(5);也可
IIC的读写函数在模块配置iic那一小节

void EEPROM_Read(void)
{shold[0] = IIC_Read(0x00);HAL_Delay(10);shold[1] = IIC_Read(0x01);HAL_Delay(10);shold[2] = IIC_Read(0x02);HAL_Delay(10);
}
void EEPROM_Write(void)
{IIC_Write(0x00,shold[0]);HAL_Delay(10);IIC_Write(0x01,shold[1]);HAL_Delay(10);IIC_Write(0x02,shold[2]);HAL_Delay(10);
}

3.uint8_t KEY_Scan(uint8_t mode);

uint8_t KEY_Scan(uint8_t mode)
{static uint8_t flag=1;if(mode)    flag = 1;if(flag &&(KEY_B1 == 0 || KEY_B2 == 0 || KEY_B3 == 0 || KEY_B4== 0 )){HAL_Delay(10);flag = 0;if (KEY_B1 == 0)  return B1_Press;else if (KEY_B2 == 0) return B2_Press;else if (KEY_B3 == 0) return B3_Press;else if (KEY_B4 == 0) return B4_Press;}else if(KEY_B1 == KEY_B2 == KEY_B3 == KEY_B4 == 1) flag = 1;return 0;
}

4.void KEY_Handle(uint8_t key);

在B1按下时显示页面切换(mode变化)
在B2按下时切换参数选择的地址(location变化)
在B3按下时对应参数加5,不大于95
在B4按下时对应参数减5,不小于5

void KEY_Handle(uint8_t key)
{if(key == B1_Press){LCD_Clear(White);//清屏if(mode == 0){mode = 1;}else if(mode == 1){mode = 0;EEPROM_Write();}}else if(key == B2_Press){location++;location = location % 4;}else if(key == B3_Press){if(shold[location-1] < 95){shold[location-1] = shold[location-1] + 5;}}else if(key == B4_Press){if(shold[location-1] > 5){shold[location-1] = shold[location-1] - 5;}}
}

5.uint16_t Get_ADC(void);

读取ADC,Get_ADC()*3.3/4096才是电压值

uint16_t Get_ADC(void)
{uint16_t temp = 0 ;HAL_ADC_Start(&hadc2);temp = HAL_ADC_GetValue(&hadc2);HAL_ADC_Stop(&hadc2);return temp;
}

6.void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);

接受中断服务函数
接收到数据,send = 1;用以控制LD3亮
若是接收到C,发送信息;
若是接收到S,发送信息;

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{send = 1;if(data[0] == 'C'){sprintf((char *)str,"C:H%.2d+L%.1d\r\n",Height,Level);HAL_UART_Transmit(&huart1, (unsigned char *)str, strlen((char *)str), 50);}else if(data[0] == 'S'){sprintf((char *)str,"S:TL%.2d+TM%.2d+TH%.2d\r\n",shold[0],shold[1],shold[2]);HAL_UART_Transmit(&huart1, (unsigned char *)str, strlen((char *)str), 50);}
}

7.int main(void);

初始化;

 HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);I2CInit();IIC_Write(0x00,30);HAL_Delay(10);IIC_Write(0x01,50);HAL_Delay(10);IIC_Write(0x02,70);HAL_Delay(10);EEPROM_Read();LCD_Init();LCD_Clear(White);LCD_SetTextColor(Black);HAL_Delay(100);

while(1);


     Display();HAL_UART_Receive_IT(&huart1,data,1);key = KEY_Scan(0);if(key)    KEY_Handle(key);if(count == 1 && mode == 0){Level_Last = Level;Adc = Get_ADC()*3.3/4096;Height = 100/3.3*Adc;if(Height < shold[0])    Level = 0;else if(Height < shold[1])    Level = 1;else if(Height < shold[2])    Level = 2;else Level = 3;if(Level_Last > Level){change = 1;sprintf(arr,"A:H%.2d+L%.1d+D\r\n",Height,Level);HAL_UART_Transmit(&huart1, (unsigned char *)arr, strlen(arr), 50);}else if(Level_Last < Level){change = 1;sprintf(arr,"A:H%.2d+L%.1d+U\r\n",Height,Level);HAL_UART_Transmit(&huart1, (unsigned char *)arr, strlen(arr), 50);}count = 0;if(i++%2)HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_SET);elseHAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);}if(change == 1 && time == 1){if(j++%2)HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,GPIO_PIN_SET);elseHAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,GPIO_PIN_RESET);//       HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_9);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);}else if(send == 1 && time == 1){if(k++%2)HAL_GPIO_WritePin(GPIOC,GPIO_PIN_10,GPIO_PIN_SET);elseHAL_GPIO_WritePin(GPIOC,GPIO_PIN_10,GPIO_PIN_RESET);//HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_10);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_9|GPIO_PIN_8|GPIO_PIN_11|GPIO_PIN_12,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);}

8.void SysTick_Handler(void);

上面的time和count在哪变了,在哪计时呢?
就在滴答定时器里面咯。
大家打开stm32g4xx_it.c

 if(j++ == 200){j = 0;time = 1;}if(i++ >= 1000){count = 1;i = 0;change = 0;send = 0;}

j是0.2s的计时,i是1s的计时


总结

以上就是本次赛题的程序设计部分(变量定义部分,本人没有罗列出来嗷),在代码简洁方面本人做的不是很好,如有更好的设计方法可以在评论区留言。互相学习。

【STM32G4】备战蓝桥杯嵌入式---实战---第七届嵌入式省赛—“模拟液位检测告警系统”相关推荐

  1. 蓝桥杯嵌入式——第七届省赛-模拟液位检测告警系统

    第七届省赛-模拟液位检测告警系统 目录 第七届省赛-模拟液位检测告警系统 一.赛题分析 二.代码 一.赛题分析 这一届和上一届也就是第六届一样,没有涉及到定时器得PWM输出和输入捕获.主要得赛题难度是 ...

  2. 蓝桥杯嵌入式第七届省赛——“模拟液位检测告警系统”旧板标准库

    一.赛题分析 模拟液位检测告警系统,涉及到KEY.ADC.EEPROM.LED.USART.LCD等模块.本届赛题相对简单,各个模块均可在往期文章中找到配置方法和编写说明.如: 蓝桥杯嵌入式--第六届 ...

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

    /*赛题:第七届:模拟液位检测告警系统" **作者:*wj **时间:2021-2-13 **注意:设备通过串口发送给PC,思路和LCD动态显示一样(记得添加"stdio.h&qu ...

  4. 蓝桥杯嵌入式STM32G431——第七届省赛真题模拟液位检测告警系统

    第七届省赛真题模拟液位检测告警系统 第七届省赛真题 主函数部分的代码功能实现(不包含各模块初始化代码) 第七届省赛真题 主函数部分的代码功能实现(不包含各模块初始化代码) #include " ...

  5. java蓝桥杯凑算是,第七届蓝桥杯JAVA B组真题解析-凑算式(第三题)

    第七届蓝桥杯JAVA B组真题解析-凑算式(第三题) 凑算式 A+B/C+DEF/GHI =10 (如果显示有问题,可以参见[图1.jpg]) 这个算式中AI代表19的数字,不同的字母代表不同的数字. ...

  6. 蓝桥杯2022年第十三届嵌入式详解

    此前也发了关于蓝桥杯的题目,昨天刚比完赛,放松了一下,没来得及整理,早上我就把我所有的思路整理了一下,发出来,希望能帮到大家.当然也有很多不足的地方,希望大家能提出,我们一起讨论. 首先,关于题目的功 ...

  7. [蓝桥杯][2016年第七届真题]压缩变换(主席树求区间不同数的个数)

    题目描述 小明最近在研究压缩算法. 他知道,压缩的时候如果能够使得数值很小,就能通过熵编码得到较高的压缩比. 然而,要使数值很小是一个挑战. 最近,小明需要压缩一些正整数的序列,这些序列的特点是,后面 ...

  8. [蓝桥杯][2016年第七届真题]冰雹数(暴力打表找规律)

    题目描述 任意给定一个正整数N, 如果是偶数,执行: N / 2 如果是奇数,执行: N * 3 + 1 生成的新的数字再执行同样的动作,循环往复. 通过观察发现,这个数字会一会儿上升到很高, 一会儿 ...

  9. [蓝桥杯][2016年第七届真题]密码脱落(记忆化搜索)

    题目描述 X星球的考古学家发现了一批古代留下来的密码. 这些密码是由A.B.C.D 四种植物的种子串成的序列. 仔细分析发现,这些密码串当初应该是前后对称的(也就是我们说的镜像串). 由于年代久远,其 ...

最新文章

  1. 中国首次纳米孔测序大会:不可错过的教学专场和技术诊断
  2. STL之hashtable源代码剖析
  3. 酱油和gbt酱油哪个好_酱油不是越贵越好,聪明人才知道的两个选酱油小技巧
  4. 微信状态可设置QQ音乐 网友:能不能整点实用的?
  5. “疯狂猜成语”软件用户体验
  6. ionic应用程序文件保存和清除缓存
  7. win11怎样在多屏中设置主显示器 Windows11主显示器的设置方法
  8. 【新闻发布系统】项目文档
  9. flash mx拖拽实例_Flash MX 2004 Professional的照片闪光器效果面板
  10. 在Simulink中对S 函数进行参数传递的三种方法
  11. firedrake求解NS方程
  12. 使用UCSC基因组浏览器可视化测序深度分布数据
  13. UE4自定义资源和编辑器(一):创建自定义资源
  14. 算法时间复杂度分析(一)
  15. 一款简单好用的开源简繁转换类库
  16. 计算机怎么审单流程,电子审单
  17. JasperReport生成pdf文件 Java开发pdf文件 pdf文件生成及下载
  18. elasticsearch 聚合搜索
  19. 人民币对美元汇率中间价报6.7802元 上调167个基点
  20. pycharm 全局搜索快捷键

热门文章

  1. eplan单线原理图多线原理图,EPLAN 安装板布局图比多线原理图的要大吗?为什么适用于多线原理图的图框在安装板布局图里很小很小...
  2. LinuxGUI环境下vim与外界复制粘贴
  3. vue + element 谷歌浏览器调用电脑摄像头拍照
  4. [回归分析][11]--共线性数据的分析
  5. 免签支付是什么意思,个人和企业该如何使用免签支付?
  6. Web前端实现一个图片放大镜
  7. 【嵌入式单元测试】C语言单元测试框架搭建
  8. Kafka Partition重分配流程简析
  9. Excel中实现模糊查询-LOOKUP+FIND函数
  10. 乐优商城--服务(七) : 用户中心微服务(LyUserApplication)