系列文章目录
第十一届省赛
第十三届省赛第一场
第十三届省赛第二场
第十四届省赛
第十五届4T模拟赛 加部分更新
目录
前言
本次记录的是第六届省赛的题目,有点久远了,因为电脑上没有另外下载的比赛题目,所以在蓝桥杯官网上找的题目。
本次新接触到的是RTC时钟(一个断电也会继续计时的时钟),其余都是常规模块。
一、题目介绍
二、模块实现
1.key+定时器
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM2)
{
keys[0].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
keys[1].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
keys[2].key_sta=HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
keys[3].key_sta=HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
for(int i=0;i<4;i++)
{
switch(keys[i].key_pro)
{
case 0:
{
if(keys[i].key_sta==0)
keys[i].key_pro=1;
}
break;
case 1:
{
if(keys[i].key_sta==0)
keys[i].key_pro=2;
else
keys[i].key_pro=0;
}
break;
case 2:
{
if(keys[i].key_sta==1)
{
keys[i].key_flg=1;
keys[i].key_pro=0;
}
}
break;
}
}
}
if(htim->Instance==TIM3)
{
if(volt>(3.3*k))
{
led1_sta^=1;
Invoid_Complict();
Control_Single_Led(0x01,led1_sta);
}
else
{
Control_Single_Led(0x01,1);
HAL_TIM_Base_Stop(&htim3);
}
}
}
/*******************************按键操作********************/
void Key_Function()
{
//开关指示灯闪烁报警功能
if(keys[0].key_flg==1)
{
is_open=0;
keys[0].key_flg=0;
}
//切换显示界面
if(keys[1].key_flg==1)
{
menu++;
keys[1].key_flg=0;
}
//切换想要调整的时间是时,还是分,还是秒
if(keys[2].key_flg==1)
{
change_time++;
keys[2].key_flg=0;
}
//更新当前要调整的时间
if(keys[3].key_flg==1)
{
if(change_time%3==0)
{
if(h==23)
h=0;
else
h++;
}
else if(change_time%3==1)
{
if(m==59)
m=0;
else
m++;
}
else
{
if(s==59)
s=0;
else
s++;
}
//更新按键作用下设置的时间
sTime.Hours=h;
sTime.Minutes=m;
sTime.Seconds=s;
HAL_RTC_SetTime(&hrtc, &sTime,RTC_FORMAT_BIN);
//上报电压
Upload_Data_Ontime();
//自动切换到系统界面
menu++;
keys[3].key_flg=0;
}
Display_led();
}
2.串口+ADC
/********************************串口模块***************************/
char RXbuff[30],TXbuff[30];
uint8_t Rxdat,BufIndex=0;
//串口回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance==USART1)
{
RXbuff[BufIndex++]=Rxdat;
HAL_UART_Receive_IT(&huart1,&Rxdat, 1);
}
}
//利用串口通信修改K的值
void Deal_Information()
{
if(BufIndex==0 || BufIndex<6)
return ;
if(RXbuff[0]=='k' && RXbuff[1]=='0' && RXbuff[2]=='.' && (RXbuff[3]>='1' && RXbuff[3]<='9') )
{
k=(RXbuff[3]-'0')/10.0;
sprintf(TXbuff,"ok\n");
HAL_UART_Transmit_IT(&huart1,(uint8_t *)TXbuff,sizeof(TXbuff));
}
BufIndex=0;
}
//定时上报数据
void Upload_Data_Ontime()
{
sprintf(TXbuff,"%.2f+%.1f+%d%d%d\n\r",volt,k,h,m,s);
HAL_UART_Transmit_IT(&huart1,(uint8_t*)TXbuff,sizeof(TXbuff));
}
/*******************************ADC模块************************/
void Get_adc()
{
uint16_t adc;
HAL_ADC_Start(&hadc2);
adc=HAL_ADC_GetValue(&hadc2);
HAL_ADC_Stop(&hadc2);
volt= adc*3.3/4096;
}
3.RTC+自定义的系统函数
整体来说,RTC算是一个用起来比较简单的小模块,这里我就不说了,各位可以去搜搜,有详细的博客讲述
/****************************自定义系统函数******************/
//初始化
void sys_init()
{
//LCD初始化
LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
Display_sys_lcd();
Invoid_Complict();
//LED初始化
Control_All_Led();
//eeprom初始化
I2CInit();
Save_Data_Init();
//打开定时器
HAL_TIM_Base_Start_IT(&htim2);
HAL_UART_Receive_IT(&huart1,&Rxdat, 1);
}
void sys_work()
{
//获取当前的时间
HAL_RTC_GetTime(&hrtc,&sTime,RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc,&sDate,RTC_FORMAT_BIN);
h=sTime.Hours;
m=sTime.Minutes;
s=sTime.Seconds;
Update_Data();
Deal_Information();
Get_adc();
Display_lcd();
Key_Function();
//定时上报电压
//使用标志位,避免重复发送
if(flag==0 && (m==30 || s==30 || m==59 || s==59))
{
Upload_Data_Ontime();
flag=1;
}
if(!(m==30 || s==30 || m==59 || s==59))
flag=0;
}
4.eeprom
这个模块前面在第十三届第二场遇到过,有需要的可以去前面找找。
这次再次遇到,我发现对于i2c的读取和写入这个原理和过程还存在一定的问题,接下来需要赶紧熟悉理解它。
总结
以上,就是我本次的记录,对于题目中的LCD和LED两个模块的实现有需要的话可以去前面几篇看,因为都是一样的,所以就