一、赛题分析
模拟液位检测告警系统,涉及到KEY、ADC、EEPROM、LED、USART、LCD等模块。本届赛题相对简单,各个模块均可在往期文章中找到配置方法和编写说明。如:
蓝桥杯嵌入式——第六届省赛“电压测量监控设备”旧版标准库_对愁眠后霜满天的博客-CSDN博客
本届赛题主要难点在于对液位上升和下降趋势的判断,并通过串口发送至电脑。以及串口查询,和存储液面阀值。
二、程序设计
本届赛题所用到的模块均在往届赛题有所涉及,具体可查看往期文章或在文章最后下载本届赛题的项目工程。
1、对液面等级变化趋势的判断
对于此处,博主的思想是:在while(1)之前要读取一次ADC采样值,判断level等级,并标记此时的液面等级。再在while(1)中level改变之前标记和改变之后的值进行对比,可得出液面变化趋势。
2、串口发送查询部分
对于此处,题目中要求对接收一个字符数据的判断。所以可以先接收数据再判断是否满足条件,若不满足查询条件直接清除,若满足则发送查询数据,再清除接收数据。如果不清除接收数据,则多次串口发送后可能会出错。
void USART2_IRQHandler(void)
{
if(USART_GetITStatus(USART2,USART_IT_RXNE) != RESET)
{
USART_ClearITPendingBit(USART2,USART_IT_RXNE);
USART_RXBUF[RXCUNT++] = USART_ReceiveData(USART2);
if(USART_RXBUF[0] != '\0')
{
USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);
RXOVER = 1;
}
}
}
/* 此为部分,整体可在主函数中体现
if(RXOVER == 1)
{
RXOVER = 0;
RXCUNT = 0;
if(USART_RXBUF[0] == 'C')
{
memset(string,0,sizeof(string));
sprintf((char*)string,"C:H%d+L%d\\r\\n\r\n",Height,leve);
USART_SendString(USART2,string);
led3_flag = 1;
}
if(USART_RXBUF[0] == 'S')
{
memset(string,0,sizeof(string));
sprintf((char*)string,"S:TL%d+TM%d+TH%d\\r\\n\r\n",TH.th_1,TH.th_2,TH.th_3);
USART_SendString(USART2,string);
led3_flag = 1;
}
memset(USART_RXBUF,0,sizeof(USART_RXBUF));
}
*/
3、main.c
写I2C之后一定要延时5ms左右10ms比较保险,不然可能出错。
#include "stm32f10x.h"
#include "lcd.h"
#include "led.h"
#include "key.h"
#include "delay.h"
#include "adc.h"
#include "timer.h"
#include "usart.h"
#include "i2c.h"
#include "stdio.h"
#include "string.h"
struct Level{u8 th_1,th_2,th_3;}TH={30,50,70};
enum show_stat{Level,Setting};
u8 Height = 0,leve = 0,leve_flag = 0,select_flag = 0;
u8 ADC_Flag,led_flag = 0,key_flag = 0,show_flag = Level;
u8 led2_flag = 0,ld2 = 0,led3_flag = 0,ld3 = 0;
u8 string[20];
float adc_temp;
void key_in(void);
void show_lcd(void);
void highlight_char(u8 Line, u8 *ptr);
void height_leve(void);
void Leve_init(void);
void judgement_usart(void);
void led_state(void);
//Main Body
int main(void)
{
STM3210B_LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
SysTick_Config(SystemCoreClock/1000);
TIM4_Init();
USART2_Init(9600);
LED_Init();
KEY_Init();
ADC_INIT();
i2c_init();
TH.th_1 = i2c_read(0x32);
if(TH.th_1 > 95&&TH.th_1%5 != 0)
TH.th_1 = 30;
TH.th_2 = i2c_read(0x33);
if(TH.th_2 > 95&&TH.th_2%5 != 0)
TH.th_2 = 50;
TH.th_3 = i2c_read(0x34);
if(TH.th_3 > 95&&TH.th_3%5 != 0)
TH.th_3 = 70;
Leve_init();
while(1)
{
key_in();
show_lcd();
led_state();
}
}
void Leve_init(void)
{
adc_temp = Read_ADC();
Height = adc_temp * 100 / 3.3;
height_leve();
leve_flag = leve;
}
void key_in(void)
{
key_flag = key_scan();
if(key_flag == 1)
{
show_flag =! show_flag;
LCD_Clear(Black);
}
if(key_flag == 2&&show_flag == Setting)
{
select_flag = (select_flag + 1) % 3;
}
if(key_flag == 3&&show_flag == Setting)
{
if(select_flag == 0&&TH.th_1<95)TH.th_1 = TH.th_1 + 5;
if(select_flag == 1&&TH.th_2<95)TH.th_2 = TH.th_2 + 5;
if(select_flag == 2&&TH.th_3<95)TH.th_3 = TH.th_3 + 5;
i2c_write(0x32,TH.th_1);Delay_Ms(10);
i2c_write(0x33,TH.th_2);Delay_Ms(10);
i2c_write(0x34,TH.th_3);Delay_Ms(10);
}
if(key_flag == 4&&show_flag == Setting)
{
if(select_flag == 0&&TH.th_1>5)TH.th_1 = TH.th_1 - 5;
if(select_flag == 1&&TH.th_2>5)TH.th_2 = TH.th_2 - 5;
if(select_flag == 2&&TH.th_3>5)TH.th_3 = TH.th_3 - 5;
i2c_write(0x32,TH.th_1);Delay_Ms(10);
i2c_write(0x33,TH.th_2);Delay_Ms(10);
i2c_write(0x34,TH.th_3);Delay_Ms(10);
}
}
void show_lcd(void)
{
if(ADC_Flag)
{
ADC_Flag = 0;
adc_temp = Read_ADC();
}
if(show_flag == Level)
{
LCD_DisplayStringLine(Line1,(u8*)" Liquid Level ");
Height = adc_temp * 100 / 3.3;
memset(string,0,sizeof(string));
sprintf((char*)string," Height:%dcm ",Height);
LCD_DisplayStringLine(Line3,string);
memset(string,0,sizeof(string));
sprintf((char*)string," ADC:%.2fV ",adc_temp);
LCD_DisplayStringLine(Line5,string);
judgement_usart();
memset(string,0,sizeof(string));
sprintf((char*)string," Level:%d ",leve);
LCD_DisplayStringLine(Line7,string);
}else if(show_flag == Setting)
{
LCD_DisplayStringLine(Line1,(u8*)" Parameter Setup ");
memset(string,0,sizeof(string));
sprintf((char*)string," Threshold1:%dcm ",TH.th_1);
if(select_flag == 0)highlight_char(Line3,string);
else LCD_DisplayStringLine(Line3,string);
memset(string,0,sizeof(string));
sprintf((char*)string," Threshold2:%dcm ",TH.th_2);
if(select_flag == 1)highlight_char(Line5,string);
else LCD_DisplayStringLine(Line5,string);
memset(string,0,sizeof(string));
sprintf((char*)string," Threshold3:%dcm ",TH.th_3);
if(select_flag == 2)highlight_char(Line7,string);
else LCD_DisplayStringLine(Line7,string);
}
}
void highlight_char(u8 Line, u8 *ptr)
{
u32 i = 0;
u16 refcolumn = 319;
while ((*ptr != 0) && (i < 20))
{
LCD_SetTextColor(Yellow);
LCD_DisplayChar(Line, refcolumn, *ptr);
LCD_SetTextColor(White);
refcolumn -= 16;
ptr++;
i++;
}
}
void judgement_usart(void)
{
leve_flag = leve;
height_leve();
if(leve_flag>leve)
{
memset(string,0,sizeof(string));
sprintf((char*)string,"A:H%d+L%d+D\\r\\n\r\n",Height,leve);
USART_SendString(USART2,string);
led2_flag = 1;
}
if(leve_flag<leve)
{
memset(string,0,sizeof(string));
sprintf((char*)string,"A:H%d+L%d+U\\r\\n\r\n",Height,leve);
USART_SendString(USART2,string);
led2_flag = 1;
}
leve_flag = leve;
if(RXOVER == 1)
{
RXOVER = 0;
RXCUNT = 0;
if(USART_RXBUF[0] == 'C')
{
memset(string,0,sizeof(string));
sprintf((char*)string,"C:H%d+L%d\\r\\n\r\n",Height,leve);
USART_SendString(USART2,string);
led3_flag = 1;
}
if(USART_RXBUF[0] == 'S')
{
memset(string,0,sizeof(string));
sprintf((char*)string,"S:TL%d+TM%d+TH%d\\r\\n\r\n",TH.th_1,TH.th_2,TH.th_3);
USART_SendString(USART2,string);
led3_flag = 1;
}
memset(USART_RXBUF,0,sizeof(USART_RXBUF));
}
}
void height_leve(void)
{
if(Height<=TH.th_1)leve = 0;
else if(Height>TH.th_1&&Height<=TH.th_2)leve = 1;
else if(Height>TH.th_2&&Height<=TH.th_3)leve = 2;
else leve = 3;
}
void led_state(void)
{
LED_Control(LED1,led_flag);
LED_Control(LED2,ld2);
LED_Control(LED3,ld3);
}
void TIM4_IRQHandler(void)
{
static u16 led_cnt = 0,led2_cnt = 0,led3_cnt = 0;
if (TIM_GetITStatus(TIM4,TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
if(++led_cnt>=1000)
{
led_cnt = 0;
led_flag =! led_flag;
}
if(led2_flag == 1)
{
if(++led2_cnt%200 == 0)
ld2 =! ld2;
if(led2_cnt>=2000){led2_cnt = 0;led2_flag = 0;ld2=0;}
}
if(led3_flag == 1)
{
if(++led3_cnt%200 == 0)
ld3 =! ld3;
if(led3_cnt>=2000){led3_cnt = 0;led3_flag = 0;ld3=0;}
}
}
}
三、工程附上
链接:https://pan.baidu.com/s/1mD5Mwb8kkYdkKlSh0Y9uhg
提取码:foao
有不对的地方,请多指教...