![](https://img-blog.csdnimg.cn/img_convert/8bfe388a724980cb92aa66135fc1db63.png)
![](https://img-blog.csdnimg.cn/img_convert/35a5686dc7150759e96f95a70a59c989.png)
![](https://img-blog.csdnimg.cn/img_convert/e6630423163665b33e3c7dafcd59b725.png)
![](https://img-blog.csdnimg.cn/img_convert/0571e281dfcaed8a0796b68790d00697.png)
![](https://img-blog.csdnimg.cn/img_convert/8a6aa73fdb5e38c35625ee7db7354e7f.png)
![](https://img-blog.csdnimg.cn/img_convert/b1412c41167e876205fc9bdc70b82c0d.png)
![](https://img-blog.csdnimg.cn/img_convert/c92f712fd14562732e65cc49b42909cd.png)
![](https://img-blog.csdnimg.cn/img_convert/3f8c33599d000be7deb0d3da624b105f.png)
- STM32CubeMX
-
引脚功能一览:包括LED1、LED2、LED3、LED8;按键B1、B2、B3、B4;
-
时钟树配置:80MHz系统主频
-
TIM2配置:PA15捕获A通道XL555频率(频率大小受R40电位器调控)、TIM3配置:PB4捕获B通道XL555频率(频率大小受R39电位器调控)
- 工程代码
- 主程序
/**********************************main.h*************************************/
//枚举变量、结构体变量定义
enum
{
DATAf = 1,
DATAt,
PARA,
RECD,
} ;
typedef struct
{
char MyStr[21];
uint8_t ucBrush;
uint8_t Interface;
} LCD;
extern LCD Lcd;
typedef struct
{
double dFreq;
double dTime;
double Max;
double Min;
uint8_t ucBrush;
uint8_t ND;
uint8_t NH;
} TIM;
extern TIM myR40A;
extern TIM myR39B;
/**********************************main.c*************************************/
#include "main.h"
#include "tim.h"
#include "gpio.h"
#include <stdio.h>
#include "key.h"
#include "lcd.h"
#include "led.h"
LCD Lcd; //LCD相关结构体变量
TIM myR40A; //TIM2相关结构体变量
TIM myR39B; //TIM3相关结构体变量
uint16_t PD = 1000; //PD参数,默认值1000
uint16_t PH = 5000; //PH参数,默认值5000
int PX = 0; //PX参数,默认值0
uint8_t ParaChoice = 1; //参数选择标志
uint16_t t3s = 0; //3s窗口时间
void SystemClock_Config(void);
void LCD_Proc(void);
void R40A_Capture(void);
void R39B_Capture(void);
void Measured_Proc(void);
void InitMySystem(void)
{
LCD_Init(); //LCD初始化
LCD_Clear(Black);
LCD_SetBackColor(Black);
LCD_SetTextColor(White);
Lcd.Interface = DATAf; //默认界面
HAL_TIM_IC_Start(&htim2,TIM_CHANNEL_1); //开启TIM2输入捕获
HAL_TIM_IC_Start(&htim3,TIM_CHANNEL_1); //开启TIM3输入捕获
HAL_Delay(10); //上电延时10ms
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM2_Init();
MX_TIM3_Init();
InitMySystem();
/*数据预处理BEGIN*/
R40A_Capture();
R39B_Capture();
myR40A.dFreq += PX;
myR39B.dFreq += PX;
if(myR40A.dFreq > 20000) //限幅,频率测量最大值20KHz
myR40A.dFreq = 20000;
if(myR39B.dFreq > 20000)
myR39B.dFreq = 20000;
myR40A.Max = myR40A.Min = myR40A.dFreq;
myR39B.Max = myR39B.Min = myR39B.dFreq;
/*数据预处理END*/
while (1)
{
Key_Proc(); //按键
LED_Proc(); //LED
LCD_Proc(); //LCD
Measured_Proc(); //数据
}
}
void R40A_Capture(void)
{
myR40A.dTime = HAL_TIM_ReadCapturedValue(&htim2,TIM_CHANNEL_1); //周期
myR40A.dFreq = 1000000 / myR40A.dTime; //1M(us)/T(us) 频率
}
void R39B_Capture(void)
{
myR39B.dTime = HAL_TIM_ReadCapturedValue(&htim3,TIM_CHANNEL_1);
myR39B.dFreq = 1000000 / myR39B.dTime;
}
void Measured_Proc(void)
{
static uint8_t nhflagA = 0;
static uint8_t nhflagB = 0;
/*Version2 轮询执行 BEGIN*/
if(t3s >= 3000) //3s窗口期
{
t3s = 0;
if(myR40A.Max - myR40A.Min > PD) //判断结果
myR40A.ND ++;
if(myR39B.Max - myR39B.Min > PD)
myR39B.ND ++;
myR40A.Max = myR40A.Min = myR40A.dFreq;//判断完自动更新最大最小值
myR39B.Max = myR39B.Min = myR39B.dFreq;
}
else
{
if(myR40A.dFreq >= myR40A.Max)
{
myR40A.Max = myR40A.dFreq;
}
else if(myR40A.dFreq <= myR40A.Min)
{
myR40A.Min = myR40A.dFreq;
}
if(myR39B.dFreq >= myR39B.Max)
{
myR39B.Max = myR39B.dFreq;
}
else if(myR39B.dFreq <= myR39B.Min)
{
myR39B.Min = myR39B.dFreq;
}
}
/*Version2 轮询执行 End*/
if(myR40A.ucBrush < 100) //100ms刷新数据
return ;
myR40A.ucBrush = 0;
R40A_Capture();
R39B_Capture();
myR40A.dFreq += PX;
myR39B.dFreq += PX;
if(myR40A.dFreq > 20000)
myR40A.dFreq = 20000;
if(myR39B.dFreq > 20000)
myR39B.dFreq = 20000;
if(myR40A.dFreq <= PH)
nhflagA = 1;
else
{
if(nhflagA == 1)
{
myR40A.NH ++;
nhflagA = 0;
}
}
if(myR39B.dFreq <= PH)
nhflagB = 1;
else
{
if(nhflagB == 1)
{
myR39B.NH ++;
nhflagB = 0;
}
}
}
/*4个界面*/
void LCD_InterfaceDATAf(void) //1
{
LCD_DisplayStringLine(Line1,(u8*)" DATA ");
if(myR40A.dFreq < 0)
sprintf(Lcd.MyStr," A=NULL ");
else if(myR40A.dFreq <= 1000)
sprintf(Lcd.MyStr," A=%.fHz ",myR40A.dFreq);
else
sprintf(Lcd.MyStr," A=%.2fKHz ",myR40A.dFreq/1000);
LCD_DisplayStringLine(Line3,(u8*)Lcd.MyStr);
if(myR39B.dFreq < 0)
sprintf(Lcd.MyStr," B=NULL ");
else if(myR39B.dFreq <= 1000)
sprintf(Lcd.MyStr," B=%.fHz ",myR39B.dFreq);
else
sprintf(Lcd.MyStr," B=%.2fKHz ",myR39B.dFreq/1000);
LCD_DisplayStringLine(Line4,(u8*)Lcd.MyStr);
}
void LCD_InterfaceDATAt(void) //2
{
LCD_DisplayStringLine(Line1,(u8*)" DATA ");
if(myR40A.dTime <= 1000)
sprintf(Lcd.MyStr," A=%.fuS ",myR40A.dTime);
else
sprintf(Lcd.MyStr," A=%.2fmS ",myR40A.dTime/1000);
LCD_DisplayStringLine(Line3,(u8*)Lcd.MyStr);
if(myR39B.dTime <= 1000)
sprintf(Lcd.MyStr," B=%.fuS ",myR39B.dTime);
else
sprintf(Lcd.MyStr," B=%.2fmS ",myR39B.dTime/1000);
LCD_DisplayStringLine(Line4,(u8*)Lcd.MyStr);
}
void LCD_InterfacePARA(void) //3
{
LCD_DisplayStringLine(Line1,(u8*)" PARA ");
sprintf(Lcd.MyStr," PD=%dHz ",PD);
LCD_DisplayStringLine(Line3,(u8*)Lcd.MyStr);
sprintf(Lcd.MyStr," PH=%dHz ",PH);
LCD_DisplayStringLine(Line4,(u8*)Lcd.MyStr);
sprintf(Lcd.MyStr," PX=%dHz ",PX);
LCD_DisplayStringLine(Line5,(u8*)Lcd.MyStr);
}
void LCD_InterfaceRECD(void) //4
{
LCD_DisplayStringLine(Line1,(u8*)" RECD ");
sprintf(Lcd.MyStr," NDA=%d ",myR40A.ND);
LCD_DisplayStringLine(Line3,(u8*)Lcd.MyStr);
sprintf(Lcd.MyStr," NDB=%d ",myR39B.ND);
LCD_DisplayStringLine(Line4,(u8*)Lcd.MyStr);
sprintf(Lcd.MyStr," NHA=%d ",myR40A.NH);
LCD_DisplayStringLine(Line5,(u8*)Lcd.MyStr);
sprintf(Lcd.MyStr," NHB=%d ",myR39B.NH);
LCD_DisplayStringLine(Line6,(u8*)Lcd.MyStr);
}
void LCD_Proc(void)
{
if(Lcd.ucBrush < 100)
return ;
Lcd.ucBrush = 0;
switch(Lcd.Interface)
{
case DATAf: LCD_InterfaceDATAf(); break;
case DATAt: LCD_InterfaceDATAt(); break;
case PARA: LCD_InterfacePARA(); break;
case RECD: LCD_InterfaceRECD(); break;
}
}
void HAL_IncTick(void)
{
uwTick += uwTickFreq;
Lcd.ucBrush ++;
Key.ucBrush ++;
myR40A.ucBrush ++;
t3s ++;
/*Version1 中断执行 BEGIN*/
if(t3s == 3000)
{
t3s = 0; //3s窗口期
if(myR40A.Max - myR40A.Min > PD) //判断结果
myR40A.ND ++;
if(myR39B.Max - myR39B.Min > PD)
myR39B.ND ++;
myR40A.Max = myR40A.Min = myR40A.dFreq;//判断完自动更新最大最小值
myR39B.Max = myR39B.Min = myR39B.dFreq;
}
else
{
if(myR40A.dFreq >= myR40A.Max)
{
myR40A.Max = myR40A.dFreq;
}
else if(myR40A.dFreq <= myR40A.Min)
{
myR40A.Min = myR40A.dFreq;
}
if(myR39B.dFreq >= myR39B.Max)
{
myR39B.Max = myR39B.dFreq;
}
else if(myR39B.dFreq <= myR39B.Min)
{
myR39B.Min = myR39B.dFreq;
}
}
/*Version1 中断执行 BEGIN*/
/*Version2 轮询执行 -- Measured_Proc*/
}
- 按键模块
/**********************************key.h*************************************/
#ifndef _KEY_H_
#define _KEY_H_
#include "main.h"
enum
{
KEY1 = 1,
KEY2,
KEY3,
KEY4,
};
typedef struct
{
uint8_t ucBrush;
} KEY;
extern KEY Key;
void Key_Proc(void);
#endif
/**********************************key.c*************************************/
#include "key.h"
#include "led.h"
#include "lcd.h"
KEY Key;
extern uint8_t ParaChoice;
extern uint16_t PD;
extern uint16_t PH;
extern int PX;
uint8_t Key_Read(void) //键值获取
{
if(!(GPIOB->IDR & GPIO_PIN_0)) return 1;
if(!(GPIOB->IDR & GPIO_PIN_1)) return 2;
if(!(GPIOB->IDR & GPIO_PIN_2)) return 3;
if(!(GPIOA->IDR & GPIO_PIN_0)) return 4;
return 0;
}
void Key1_Function(void) //+
{
if(Lcd.Interface != PARA)
return ;
if(ParaChoice == 1)
{
if(PD < 1000)
PD += 100;
}
else if(ParaChoice == 2)
{
if(PH < 10000)
PH += 100;
}
else if(ParaChoice == 3)
{
if(PX < 1000)
PX += 100;
}
}
void Key2_Function(void) //-
{
if(Lcd.Interface != PARA)
return ;
if(ParaChoice == 1)
{
if(PD > 100)
PD -= 100;
else
PD = 100;
}
else if(ParaChoice == 2)
{
if(PH > 1000)
PH -= 100;
else
PH = 1000;
}
else if(ParaChoice == 3)
{
if(PX > -1000)
PX -= 100;
else
PX = -1000;
}
}
void Key3_Function(void)
{
if(Lcd.Interface == PARA)
{
ParaChoice = ParaChoice % 3 + 1;
}
if(Lcd.Interface == DATAf)
{
LCD_Clear(Black);
Lcd.Interface = DATAt;
}
else if(Lcd.Interface == DATAt)
{
LCD_Clear(Black);
Lcd.Interface = DATAf;
}
}
void Key3_LongClick(void) //长按功能
{
//20ms once
static uint16_t key_cnt = 0;
static uint8_t longflag = 0;
if(Lcd.Interface != RECD)
return ;
if((GPIOB->IDR & GPIO_PIN_2) == 0)
{
key_cnt ++;
if(key_cnt >= 50) //20ms * 50
{
if(longflag == 0)
{
longflag = 1;
}
}
}
else
{
if(longflag == 1)
{
/*long click*/
myR40A.ND = 0; //清零参数
myR39B.ND = 0;
myR40A.NH = 0;
myR39B.NH = 0;
}
key_cnt = 0;
longflag = 0;
}
}
void Key4_Function(void) //界面切换
{
LCD_Clear(Black);
ParaChoice = 1;
if(Lcd.Interface == DATAf)
Lcd.Interface = PARA;
else
Lcd.Interface = Lcd.Interface % 4 + 1;
}
void Key_Proc(void)
{
uint8_t new_key;
static uint8_t old_key;
if(Key.ucBrush < 20) //20ms
return;
Key.ucBrush = 0;
new_key = Key_Read();
if(new_key == old_key)
new_key = 0;
else
old_key = new_key;
switch(new_key)
{
case KEY1: Key1_Function(); break;
case KEY2: Key2_Function(); break;
case KEY3: Key3_Function(); break;
case KEY4: Key4_Function(); break;
}
Key3_LongClick();
}
- LED灯模块
/**********************************led.h*************************************/
#ifndef _LED_H_
#define _LED_H_
#include "main.h"
#define LED1 0x01
#define LED2 0x02
#define LED3 0x04
#define LED8 0x80
typedef struct
{
uint8_t State;
} LED;
extern LED Led;
void LED_Proc(void);
#endif
/**********************************led.c*************************************/
#include "led.h"
LED Led;
extern uint16_t PH;
void LED_Disp(uint8_t state)
{
GPIOC->ODR = ~ state << 8;
GPIOD->BSRR = GPIO_PIN_2;
GPIOD->BRR = GPIO_PIN_2;
}
void LED_Proc(void)
{
if(Lcd.Interface == DATAf || Lcd.Interface == DATAt)
Led.State |= LED1;
else
Led.State &= ~LED1;
if(myR40A.dFreq > PH)
Led.State |= LED2;
else
Led.State &= ~LED2;
if(myR39B.dFreq > PH)
Led.State |= LED3;
else
Led.State &= ~LED3;
if(myR39B.ND >= 3 || myR40A.ND >= 3)
Led.State |= LED8;
else
Led.State &= ~LED8;
LED_Disp(Led.State);
}