蓝桥杯嵌入式_STM32学习_第七届省赛题

个人做题记录,仅供参考

#include "stm32f10x.h"
#include "stdio.h"
#include "string.h"
#include "lcd.h"
#include "key.h"
#include "at24c02.h"
#include "adc.h"
#include "usart.h"
#include "led.h"

u32 TimingDelay = 0;
uint8_t Lcd_flag = 0;
uint8_t lcd_light = 0;
uint8_t IIC_flag = 0xdd;
uint8_t IIC_Flag = 0;
uint8_t hight = 0;
uint8_t Level = 0;
int Adc_Val = 0;
uint8_t Time_1s = 0;
uint8_t Time_200ms = 0;
uint8_t Uart_Buf = 0;
uint8_t RxOver = 0;
uint8_t Send_flag_U = 0;
uint8_t Send_flag_D = 0;
uint8_t Led_flag_2 = 0;
uint8_t Led_flag_3 = 0;
uint8_t Threshold_Buf[3] = {0};
uint8_t IIC_Buf[3] = {30,50,70};
uint8_t Buf[20] = {0};

void Delay_Ms(u32 nTime);
void Key_Proc(uint8_t* p);
void Lcd_Proc(void);
void Level_Deal(uint8_t* p,uint8_t hight,uint8_t* Level);
void Uart2_Proc(uint8_t Uart_Buf);
void Led_Proc(void);

int main(){
	SysTick_Config(SystemCoreClock/1000);

	Delay_Ms(200);
	
	STM3210B_LCD_Init();
	KEY_Init();
	i2c_init();
	ADC1_Init();
	USART2_Init(9600);
	LED_Init();
	
	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);
	
	i2c_read(&IIC_Flag,0x10,1);
	if(IIC_Flag == 0xdd){
		i2c_read(Threshold_Buf, 0x00,3);
	}
	else{
		i2c_write(&IIC_flag, 0x10,1);
		Delay_Ms(200);
		i2c_write(IIC_Buf, 0x00,3);
		Delay_Ms(200);
		i2c_read(Threshold_Buf, 0x00,3);
	}

	while(1){
		if(Time_1s){
			Time_1s = 0;
			Adc_Val = (((float)ADC1_Conv() * 3.3 / 4096)+0.001)*100;//因为我的板子最大只到2.999,hight到不了100.....
		  hight = (float)Adc_Val / 330 * 100;
		}
		
		Key_Proc(Threshold_Buf);
		Lcd_Proc();
		Level_Deal(Threshold_Buf,hight,&Level);
		Uart2_Proc(Uart_Buf);
		Led_Proc();
	}
	
}

/*******************************************************************************
* 函数名:Key_Proc
* 输入值:无符号8位整型指针变量 p
* 返回值:无
* 作者	:Moqim Flourite.
* 时间	:2022年4月4日
* 功能描述:按键设置
* 备注	:B1 按键:“设置”按键,按下后进入阈值设定界面(如图2 所示),
                再次按下B1 按键时退出设置界面,保存用户设定的结果到E2PROM,
                并返回液位检测界面;
          B2 按键: 切换选择3 个待修改的阈值,被选中的阈值应突出显示。;
          B3 按键:“加”按键,按下后,被选择的阈值增加5cm,增加到95cm 为止;
          B4 按键:“减”按键,按下后,被选择的阈值减少5cm,减少到5cm 为止;
*******************************************************************************/
void Key_Proc(uint8_t* p){
	static uint8_t ucKey_Val = 0;
	static uint8_t ucKey_Down = 0;
	static uint8_t ucKey_Old = 0;
	static uint8_t i = 0;
	
	ucKey_Val = KEY_Scan();
	ucKey_Down = ucKey_Val & (ucKey_Val ^ ucKey_Old);
	ucKey_Old = ucKey_Val;
	
	switch(ucKey_Down){
		case 1:{
			Delay_Ms(100);//消抖
			Lcd_flag = !Lcd_flag;
		  i2c_write(p, 0x00,3);
		  i = 0;
		}break;
		
		case 2:{
			if(Lcd_flag == 1){
				if(++i == 3)i = 0;	
			}
		}break;
		
		case 3:{
			if(Lcd_flag == 1){
				p[i] += 5;
			  if(p[i] > 95)p[i] = 95;
			}
			
		}break;
		
		case 4:{
			if(Lcd_flag == 1){
				p[i] -= 5;
			  if(p[i] < 5)p[i] = 5;
			}
		}break; 
	}
	lcd_light = i;

}


/*******************************************************************************
* 函数名:Lcd_Proc
* 输入值:无
* 返回值:无
* 作者	:Moqim Flourite.
* 时间	:2022年4月4日
* 功能描述:Lcd显示设置
* 备注	:液位检测显示界面:显示当前的液位高度、传感器(R37)输出状态和液位等级;
          阈值设置界面:显示三个液位阀值,设置时高亮显示;
*******************************************************************************/

void Lcd_Proc(void){
	if(Lcd_flag == 0){//显示页面
		LCD_DisplayStringLine(Line1,"    Liquid Level    ");
		
		sprintf((char*)Buf,"    Height: %dcm     ",hight);
		LCD_DisplayStringLine(Line3,Buf);
		memset(Buf,0,20*sizeof(uint8_t));
		
		sprintf((char*)Buf,"     ADC: %.2fV     ",(float)Adc_Val/100);
		LCD_DisplayStringLine(Line5,Buf);
		memset(Buf,0,20*sizeof(uint8_t));
		
		sprintf((char*)Buf,"      Level: %d      ",Level);
		LCD_DisplayStringLine(Line7,Buf);
		memset(Buf,0,20*sizeof(uint8_t));
	}
	else{
		LCD_DisplayStringLine(Line1,"  Parameter Setup   ");
		
		if(lcd_light == 0)LCD_SetBackColor(Green);
		sprintf((char*)Buf,"  Threshold 1: %02ucm  ",Threshold_Buf[0]);
		LCD_DisplayStringLine(Line3,Buf);
		memset(Buf,0,20*sizeof(uint8_t));
		LCD_SetBackColor(Blue);
		
		if(lcd_light == 1)LCD_SetBackColor(Green);
		sprintf((char*)Buf,"  Threshold 2: %02ucm  ",Threshold_Buf[1]);
		LCD_DisplayStringLine(Line5,Buf);
		memset(Buf,0,20*sizeof(uint8_t));
		LCD_SetBackColor(Blue);
		
		if(lcd_light == 2)LCD_SetBackColor(Green);
		sprintf((char*)Buf,"  Threshold 3: %02ucm  ",Threshold_Buf[2]);
		LCD_DisplayStringLine(Line7,Buf);
		memset(Buf,0,20*sizeof(uint8_t));
		LCD_SetBackColor(Blue);
	}
}

/*******************************************************************************
* 函数名:Level_Deal
* 输入值:无符号8位整型指针变量 p,无符号8位整型变量 hight,无符号8位整型指针变量 Level(这些其实可以用全局变量的,只是我想尝试完全封装)
* 返回值:无
* 作者	:Moqim Flourite.
* 时间	:2022年4月4日
* 功能描述:液位阈值设定
* 备注	:设备可设定三个液位阈值,对应四个液位等级,阈值由用户通过按键输入,设备保存阈
          值,并根据此阈值判断液位等级;
          当液位等级发生变化时,判断是上升趋势还是下降趋势;
*******************************************************************************/
void Level_Deal(uint8_t* p,uint8_t hight,uint8_t* Level){
	static uint8_t Level_Val = 0;
	static uint8_t Level_Old = 0;
	Level_Old = *Level;
	
	if(hight < p[0] || hight == p[0])*Level = 0;
	else if(hight > p[0] && hight < p[1] || hight == p[1])*Level = 1;
	else if(hight > p[1] && hight < p[2] || hight == p[2])*Level = 2;
	else if(hight > p[2])*Level = 3;
	Level_Val = *Level;
	
	if(Level_Val != Level_Old){
		if(Level_Val > Level_Old){
		Send_flag_U = 1;
		
		}else if(Level_Val < Level_Old){
			Send_flag_D = 1;
		}
		Led_flag_2 = 1;
	}
	
}

/*******************************************************************************
* 函数名:Uart2_Proc
* 输入值:无
* 返回值:无
* 作者	:Moqim Flourite.
* 时间	:2022年4月4日
* 功能描述:串口发送函数
* 备注	:通过PC 机向设备发送字符‘C’,设备返回当前液位高度和液位等级; 
          通过PC 机向设备发送字符‘S’,设备返回当前设定的三个阈值;
          当液位等级发生变化时,设备自动向PC 机发送当前液位等级、液位高度和液位变
          化趋势(上升或下降);
*******************************************************************************/
void Uart2_Proc(uint8_t Uart_Buf){
	if(RxOver == 1){
		if(Uart_Buf == 'C'){
		sprintf((char*)Buf,"C:H%02d+L%d\r\n",hight,Level);
		Led_flag_3 = 1;
	}
		else if(Uart_Buf == 'S'){
			sprintf((char*)Buf,"S:TL%02d+TM%02d+TH%02d\r\n",Threshold_Buf[0],Threshold_Buf[1],Threshold_Buf[2]);
			Led_flag_3 = 1;
		}
	}
	if(Send_flag_U == 1){
		sprintf((char*)Buf,"A:H%02d+L%d+U\r\n",hight,Level);
	}
	else if(Send_flag_D == 1){
		sprintf((char*)Buf,"A:H%02d+L%d+D\r\n",hight,Level);
	}
	USART_SendString(USART2,Buf);
	memset(Buf,0,20*sizeof(uint8_t));
	Send_flag_U = Send_flag_D = RxOver = 0;
}


/*******************************************************************************
* 函数名:USART2_IRQHandler
* 输入值:无
* 返回值:无
* 作者	:Moqim Flourite.
* 时间	:2022年4月4日
* 功能描述:串口中断服务函数
* 备注	:接收数据;
*******************************************************************************/
void USART2_IRQHandler(void){
	if(USART_GetITStatus(USART2,USART_IT_RXNE)){
		RxOver = 1;
		Uart_Buf = USART_ReceiveData(USART2);
		USART_ClearITPendingBit(USART2,USART_IT_RXNE);
	}
}

/*******************************************************************************
* 函数名:Led_Proc
* 输入值:无
* 返回值:无
* 作者	:Moqim Flourite.
* 时间	:2022年4月4日
* 功能描述:Led控制函数
* 备注	:LD1:运行状态指示灯,以1秒为间隔亮灭闪烁; 
          LD2:液位等级变化指示灯,当液位等级发生变化时,LD2 以0.2秒为间隔闪烁5 次; 
          LD3:通讯状态指示灯,当设备接收到查询指令时,LD3 以0.2秒为间隔闪烁5 次。
*******************************************************************************/
void Led_Proc(void){
	static uint8_t ucLed = 0;
	static uint8_t Num = 10;
	if(Time_1s == 1){
		ucLed ^= 0x01;
	}
	if(Led_flag_2 == 1){
		if(Time_200ms == 1){
			if(Num --){
				ucLed ^= 0x02;
			}
			else{
				Led_flag_2 = 0;
				Num = 10;
			}
			Time_200ms = 0;
		}
	}
	if(Led_flag_3 == 1){
		if(Time_200ms == 1){
			if(Num --){
				ucLed ^= 0x04;
			}
			else{
				Led_flag_3 = 0;
				Num = 10;
			}
			Time_200ms = 0;
		}
	}
		LED_Disp(ucLed);
}
void Delay_Ms(u32 nTime)
{
	TimingDelay = nTime;
	while(TimingDelay != 0);	
}

问题:
1、sprintf里写字符变量用%u;
2、LED灯逻辑没有很好,要多记几个算法;
3、E2PROM的掉电存储,注意里面存储的是8位数据,最好用16进制数做判断。(我之前疯狂用int型判断orz,最后还是参考小默的博客才写出来的。。。当然,也有我太懒了,不想去改官方IIC程序的因素。反正,越简单越好)
4、注意按键消抖,官方的程序里可能时间不太够。(不过就B1会抖动,还挺怪的)
参考博客:
@小默 haa—— 蓝桥杯之单片机设计与开发(31)——2016_第七届_蓝桥杯_国赛 ——“电压、频率采集设备”

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Moqim Flourite.

你的鼓励将是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值