链接:https://pan.baidu.com/s/1cHxmXBmJgmD1muW8rbWmgw?pwd=6666
提取码:6666
目录
1.赛题
2.分析及配置
直接观察用到的模块和引脚即可。
ADC、按键、LED、LCD。
然后配置。
2.1 RCC配置
2.2 SYS配置
2.3 按键配置
2.4 ADC配置
2.5 LCD配置
用到的引脚配置为Out_put
2.6 LED配置
LED和LCD公用引脚,只需配置PD2即可,配置为Out_put
默认LED关闭。
配置完毕生成代码。
3.编写代码及解释
代码的编写不是一次成型的写着写着要修改很正常,我们按顺序写就行。
LCD和ADC直接移植官方给的历程即可。
数据定义
typedef struct
{
bool Switch;//界面切换标志位
unsigned char Status;//状态标志位
double ADC;//ADC的数值
double Max_Volt;//电压的上限值
double Min_Volt;//电压的下限值
unsigned char Upper;//电压超过上限的提醒指示灯
unsigned char Lower;//电压低于下限的提醒指示灯
unsigned char Choose;//设置里面的高亮
unsigned int UpperCount;//LED上限中断计数
unsigned int LowerCount;//LED下限中断计数
}Data_TypeDef;
Data_TypeDef Data;
typedef struct
{
unsigned int Value;//按键的值(0或1)
bool Flag;//是否按下的标志
unsigned char State;//按键检测步骤
}Key_TypeDef;
Key_TypeDef B[4];//四个按键
3.2显示功能的编写
用到什么定义什么数据,这里只进行显示,数据的更改放到其他位置。
写道后面可能会修改不过没事一个模块一个模块的写就好。
void Show(void)
{
char arr[30];
if(Data.Switch)//参数配置界面
{
/* 界面名字 */
LCD_DisplayStringLine(Line1, (uint8_t *)" Setting ");
/* Max Volt显示 */
sprintf(arr," Max Volt: %.1fV ",Data.Max_Volt);
if(Data.Choose == 0)//如果选择的是Max Volt则他高亮
LCD_SetBackColor(Blue);
LCD_DisplayStringLine(Line2, (uint8_t *)arr);
LCD_SetBackColor(Black);//高亮完毕之后恢复黑色
/* Min Volt显示 */
sprintf(arr," Min Volt: %.1fV ",Data.Min_Volt);
if(Data.Choose == 1)//如果选择的是Min Volt则他高亮
LCD_SetBackColor(Blue);
LCD_DisplayStringLine(Line4, (uint8_t *)arr);
LCD_SetBackColor(Black);//高亮完毕之后恢复黑色
/* Upper显示 */
sprintf(arr," Upper: LD%d ",Data.Upper);
if(Data.Choose == 2)//如果选择的是Upper则他高亮
LCD_SetBackColor(Blue);
LCD_DisplayStringLine(Line6, (uint8_t *)arr);
LCD_SetBackColor(Black);//高亮完毕之后恢复黑色
/* Lower显示 */
sprintf(arr," Lower: LD%d ",Data.Lower);
if(Data.Choose == 3)//如果选择的是Lower则他高亮
LCD_SetBackColor(Blue);
LCD_DisplayStringLine(Line8, (uint8_t *)arr);
LCD_SetBackColor(Black);//高亮完毕之后恢复黑色
}
else//数据显示界面
{
LCD_DisplayStringLine(Line1, (uint8_t *)" Main ");
sprintf(arr," Volt: %.2fV ",Data.ADC);
LCD_DisplayStringLine(Line4, (uint8_t *)arr);
if(Data.Status == 0)
LCD_DisplayStringLine(Line6, (uint8_t *)" Status: Upper");
else if(Data.Status == 1)
LCD_DisplayStringLine(Line6, (uint8_t *)" Status: Lower");
else if(Data.Status == 2)
LCD_DisplayStringLine(Line6, (uint8_t *)" Status: Normal");
}
}
3.3按键功能
这里只有单机。
回调函数的编写,10毫秒检测一次,按键也消抖了。
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM4)
{
B[0].Value = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0);
B[1].Value = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1);
B[2].Value = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2);
B[3].Value = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0);
for(int i=0;i<4;i++)
{
switch(B[i].State)
{
case 0: if(B[i].Value == 0)
B[i].State = 1;
break;
case 1: if(B[i].Value == 0)
{
B[i].State = 2;
B[i].Flag = 1;
}
else
B[i].State = 0;
break;
case 2: if(B[i].Value == 1)
B[i].State = 0;
break;
default:break;
}
}
LED();
}
}
void Key_Handle(void)
{
if(B[0].Flag==1)
{
LCD_Clear(Black);
Data.Switch = 1 - Data.Switch;
B[0].Flag = 0;
}
if(B[1].Flag==1)
{
if(Data.Switch)
{
Data.Choose++;
if(Data.Choose>=4)
Data.Choose = 0;
}
B[1].Flag = 0;
}
if(B[2].Flag==1)
{
if(Data.Switch)//只在该界面的按键有效
{
if(Data.Choose == 0)
{
Data.Max_Volt += 0.3;
if(Data.Max_Volt>3.3)//数值保护
Data.Max_Volt = 3.3;
}
else if(Data.Choose == 1)
{
Data.Min_Volt += 0.3;
if(Data.Min_Volt>Data.Max_Volt)//不能大于最多相等
Data.Min_Volt = Data.Max_Volt;
}
else if(Data.Choose == 2)
{
Data.Upper++;
//加完之后相等就再加一次
if(Data.Upper == Data.Lower)
{
Data.Upper++;
//再加一次超出数值就还原到初值
if(Data.Upper>=9)
Data.Upper -= 2;
}
//防止超出数值
if(Data.Upper>=9)
Data.Upper = 8;
}
else if(Data.Choose == 3)
{
Data.Lower++;
if(Data.Lower == Data.Upper)
{
Data.Lower++;
if(Data.Lower>=9)
Data.Lower -= 2;
}
if(Data.Lower>=9)
Data.Lower = 8;
}
}
B[2].Flag = 0;
}
if(B[3].Flag==1)
{
if(Data.Switch)
{
if(Data.Choose == 0)
{
Data.Max_Volt -= 0.3;
//不能小于最多相等
if(Data.Max_Volt<Data.Min_Volt)
Data.Max_Volt = Data.Min_Volt;
}
else if(Data.Choose == 1)
{
Data.Min_Volt -= 0.3;
//不能小于0
if(Data.Min_Volt<0)
Data.Min_Volt = 0;
}
else if(Data.Choose == 2)
{
Data.Upper--;
//相等就再减一次
if(Data.Upper == Data.Lower)
{
Data.Upper--;
//如果小于1就让它还原
if(Data.Upper<1)
Data.Upper += 2;
}
if(Data.Upper<1)
Data.Upper = 1;
}
else if(Data.Choose == 3)
{
Data.Lower--;
if(Data.Lower == Data.Upper)
{
Data.Lower--;
if(Data.Lower<1)
Data.Lower += 2;
}
if(Data.Lower<1)
Data.Lower = 1;
}
}
B[3].Flag = 0;
}
}
3.4 LED 指示灯功能
这里我们把LED函数放到定时器4的中断中方便0.2s闪烁。
void LED(void)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);
if(Data.Status == 0)//高
{
Data.UpperCount++;
//十毫秒进来一次
//前20*10 = 200ms = 0.2s灭
//20-40亮
if(Data.UpperCount<=40&&Data.UpperCount>=20)
{
switch(Data.Upper)
{
case 1:HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET);break;
case 2:HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,GPIO_PIN_RESET);break;
case 3:HAL_GPIO_WritePin(GPIOC,GPIO_PIN_10,GPIO_PIN_RESET);break;
case 4:HAL_GPIO_WritePin(GPIOC,GPIO_PIN_11,GPIO_PIN_RESET);break;
case 5:HAL_GPIO_WritePin(GPIOC,GPIO_PIN_12,GPIO_PIN_RESET);break;
case 6:HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);break;
case 7:HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET);break;
case 8:HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_RESET);break;
default:break;
}
}
if(Data.UpperCount>40)
Data.UpperCount = 0;
}
if(Data.Status == 1)//低
{
Data.LowerCount++;
if(Data.LowerCount<=40&&Data.LowerCount>=20)
{
switch(Data.Lower)
{
case 1:HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET);break;
case 2:HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,GPIO_PIN_RESET);break;
case 3:HAL_GPIO_WritePin(GPIOC,GPIO_PIN_10,GPIO_PIN_RESET);break;
case 4:HAL_GPIO_WritePin(GPIOC,GPIO_PIN_11,GPIO_PIN_RESET);break;
case 5:HAL_GPIO_WritePin(GPIOC,GPIO_PIN_12,GPIO_PIN_RESET);break;
case 6:HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);break;
case 7:HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET);break;
case 8:HAL_GPIO_WritePin(GPIOC,GPIO_PIN_15,GPIO_PIN_RESET);break;
default:break;
}
}
if(Data.LowerCount>40)
Data.LowerCount = 0;
}
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET);
}
3.5初始状态说明
初始化,进行数值的初始化,以及定时器中断的开启,LCD初始化
void Init(void)
{
HAL_TIM_Base_Start_IT(&htim4);
LCD_Init();
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
Data.Upper = 1;
Data.Lower = 2;
Data.Max_Volt = 2.4;
Data.Min_Volt = 1.2;
}
while主循环
把函数都写进去,以及一些数值的获取和大小的判断
Data.ADC = getADC()*3.3/4096;
if(Data.ADC<Data.Min_Volt)
Data.Status = 1;
else if(Data.ADC>Data.Max_Volt)
Data.Status = 0;
else
Data.Status = 2;
Show();
Key_Handle();
结果展示
结尾
在按顺序写的过程中可能需要修改之前的地方不过没事,修改着来就可以,不要忘记验证,写一个就验证一个,方便查错误。
到此蓝桥杯嵌入式十届省赛完毕,如有错误还请指正,谢谢。