0 前言
🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。
为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是
🚩 便携式STM32的红外信号分析仪
🥇学长这里给一个题目综合评分(每项满分5分)
- 难度系数:3分
- 工作量:3分
- 创新点:5分
🧿 选题指导, 项目分享:
1 简介
由STM32F411CEU6作为主控芯片的带有姿态感应,红外输入,红外输出,可根据任意录入的红外信号进行存储,然后发出红外线控制各种电器设备, 并具有测电流,电压,电阻,电容能力的手表,是对于电子工程师来说具有较强实用性的小工具。
2 主要器件
- STM32F411CEU6主控芯片
- ACS712电流传感器芯片
- TC单片机
3 实现效果
4 设计原理
硬件
- 电压检测电路,主要是将外部-15v15v的电压通过几个限压电阻根据KCL和KVL转化成03.3v,再由ADC芯片采集;
- 电阻检测电路,根据简单的分压原理,将待测电阻通过模拟开关分别与1k和1M欧高精度电阻串联测得分压,从而实现精确测量较大范围内的电阻阻值;
- 电容检测电路,根据电容的一阶零状态响应,算出时间常数,再根据串联的电阻计算出接入电容的电容值;
- )红外接收发射电路,采用外加一块STC单片机(一个模块~~~~),里面预先烧录红外解码程序,再通过串口与STM32通讯,实现对外部输入红外信号的解码和调制发射;
软件
- 姿态解算算法,实现步数计算,抬手感应,翻腕感应,LCD虚拟触屏;
- 针对不同红外信号的解码和发射算法,红外信号存储算法等;
- 电阻,电容测量算法;
- 自制定时器系统任务调度算法。
主要原理图
5 部分核心代码
#include "main.h"
/********************变量声明区_START********************/
u8 flag_Power_On = 1, flag_MPU_Refresh = 0;
bool LCD_Already_Updated = false;
uint8_t RTC_hour = 23, RTC_minute = 14, RTC_second = 10;
u8 IR_flag = 0, IR_Channel = 0x01, flag_BEEP = 0, flag_ADS_readC = 0, flag_ADS_readR = 0;
u8 Arm_Position = -1;
short aacx, aacy, aacz; //加速度传感器原始数据
bool Raised_Flag = false;
bool Reversed_Flag = false;
u8 flag_of_STATE = 0;
uint16_t Menu_Pointer[7] = {1, 35, 69, 103, 137, 171, 205};
u8 Fill_IR_Code[4] = {0, 0, 0, 0}; //显示红外码存储区是否为空:0-空 1-有
uint16_t time_set_Pos[4] = {54, 102, 150, 2};
uint16_t clock_set_Pos[3] = {5, 135, 1};
/**
* @brief 决定系统状态的选择
* @param 菜单;红外收发模式;红外通道选择模式;陀螺仪模式;模拟量测试模式;
*/
enum STATUS {
MENU = 0,
TIMERUN,
TIME_SET,
CLOCK_SET,
IR_REMOTE,
IR_CHANNEL_CHOOSE,
MPU6050,
AD_VAL,
} STATE;
#define PUT_UP 1
#define LAY_DOWN 2
//mpu6050
short cnt_up = 0;
short cnt_down = 0;
short cnt_reverse = 0;
short cnt_raising = 0;
short Stale_aacx_Data = NULL;
short Stale_aacy_Data = NULL;
short Reverse_status = 0;
/********************变量声明区_END********************/
/********************API声明区_START********************/
static void Proc2msTask(void); //处理2ms任务
static void Proc50msTask(void); //处理50ms任务
static void InitSoftware(void);
static void InitHardware(void);
void ST7789_SHOW(void);
void KEY_Process(void);
static void Get_Arm_Position(short* aacx, short* aacy, short* aacz, u8* Arm_Position, bool* Raised_Flag);
static bool Judge_Wrist_Reverse(short* aacx, short* aacy, short* aacz, u8* Arm_Position);
void MPU6050_Process(void);
static void Page0_Menu(void);
static void Page1_TimeRunning(void);
static void Page2_Timeset(void);
//static void Page3_Clockset1(void);
static void Page4_Clockset2(void);
static void Page5_IR_Remote(void);
static void Page7_AD_VAL(void);
/********************API声明区_END********************/
/*********************************************************************************************************
* 函 数: main
* 注 意: 作者为了让main看起来更漂亮,整了些花里胡哨的API QWQ
*********************************************************************************************************/
int main(void) {
InitSoftware();
InitHardware();
STATE = MENU;
ST7789_Fill_Color(WHITE);
while(1) {
if(flag_Power_On)Proc2msTask();
if(flag_MPU_Refresh == 1) {
flag_MPU_Refresh = 0;
ST7789_Fill_Color(BLACK);
if(flag_Power_On){
LCD_Already_Updated = false;
ST7789_Fill_Color(WHITE);
}
}
Proc50msTask();
delay_ms(10);
}
}
/*********************************************************************************************************
* 内部函数实现
*********************************************************************************************************/
/*********************************************************************************************************
* 函数名称: Proc2msTask
* 函数功能: 处理2ms任务
* 输入参数: void
* 输出参数: void
* 返 回 值: void
* 注 意:
*********************************************************************************************************/
static void Proc2msTask(void) {
if(Get2msFlag()) {
static u8 tmp_t = 0;
if(!LCD_Already_Updated) {
ST7789_SHOW();
}
if(flag_BEEP == 1) {
BEEP();
flag_BEEP = 0;
} else if (flag_BEEP == 2) {
for(int i = 0; i < 5; i++) {
BEEP();
}
flag_BEEP = 0;
}
if(tmp_t == 5) {
KEY_Process();
tmp_t = 0;
}
tmp_t++;
Clr2msFlag();
}
}
/*********************************************************************************************************
* 函数名称: Proc50msTask
* 函数功能: 处理50ms任务
* 输入参数: void
* 输出参数: void
* 返 回 值: void
* 注 意:
*********************************************************************************************************/
static void Proc50msTask(void) {
if(Get50msFlag()) {
MPU6050_Process();
Clr50msFlag();
}
}
static void InitSoftware(void) {
}
static void InitHardware(void) {
SystemInit();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(104); //初始化延时函数
uart_init(115200); //初始化串口
InitTimer(); //初始化任务调度定时器
GPIO_ALLInit(); //初始化蜂鸣器,LED,KEY外设
five_keys_exti_config(); //初始化五向按键
ST7789_Init(); //初始化LCD-ST7789
MPU_Init(); //初始化MPU6050
My_RTC_Init();
RTC_Set_WakeUp(RTC_WakeUpClock_CK_SPRE_16bits, 0); //配置WAKE UP中断,1秒钟中断一次
while(mpu_dmp_init()) {
printf("MPU6050 Init Error!\r\n");
delay_ms(200);
}
printf("Init OK\r\n");
}
void ST7789_SHOW(void) {
switch(STATE) {
case MENU: {
SPI_ChangeConfig(LCD);
Page0_Menu();
LCD_Already_Updated = true;
break;
}
case TIMERUN: {
SPI_ChangeConfig(LCD);
Page1_TimeRunning();
LCD_Already_Updated = true;
break;
}
case TIME_SET: {
SPI_ChangeConfig(LCD);
Page2_Timeset();
LCD_Already_Updated = true;
break;
}
case CLOCK_SET: {
SPI_ChangeConfig(LCD);
Page4_Clockset2();
LCD_Already_Updated = true;
break;
}
case IR_REMOTE: {
SPI_ChangeConfig(LCD);
Page5_IR_Remote();
LCD_Already_Updated = true;
break;
}
case IR_CHANNEL_CHOOSE: {
SPI_ChangeConfig(LCD);
ST7789_DrawImage(0, 0, 240, 240, (uint16_t *)IR_ChannelChoosing);
LCD_Already_Updated = true;
break;
}
case AD_VAL: {
SPI_ChangeConfig(ADS);
cin_get_cap_init();
ADS1118GPIOInit();
ADS1118_Init(ADS1118_SS_NONE, ADS1118_MODE_LX, ADS1118_DR_128, ADS1118_PULL_UP_EN_E, ADS1118_NOP_W);
SPI_ChangeConfig(LCD);
Page7_AD_VAL();
break;
}
default : {
LCD_Already_Updated = true;
break;
}
}
}
void KEY_Process(void) {
u8 key = 0;
key = KEY_Scan(0);//得到键值
if(key) {
switch(key) {
case KEY1_PRES:
//红外选择通道:1/2/3/4
if(STATE == IR_CHANNEL_CHOOSE) {
IR_Channel = 0x01;
STATE = MENU;
LCD_Already_Updated = false;
ST7789_Fill_Color(WHITE);
}
//红外收发模式
else if(STATE == IR_REMOTE) {
IR_flag = !IR_flag;
if(IR_flag) {
LED2 = 0;
memset(USART_RX_BUF, 0, sizeof(USART_RX_BUF));
USART1_Tx_Puts(cmd_stor_buffer1, IR_Channel);
} else {
LED2 = 1;
if(flag_USART_Get) {
Fill_IR_Code[IR_Channel - 1] = 1;
LCD_Already_Updated = false;
flag_USART_Get = 0;
} else {
Fill_IR_Code[IR_Channel - 1] = 0;
LCD_Already_Updated = false;
flag_USART_Get = 1;
}
//print_buffer;
}
} else if(STATE == AD_VAL) {
flag_ADS_readC = 1;
LCD_Already_Updated = false;
} else BEEP();
break;
case KEY2_PRES:
//红外选择通道:1/2/3/4
if(STATE == IR_CHANNEL_CHOOSE) {
IR_Channel = 0x02;
STATE = MENU;
LCD_Already_Updated = false;
ST7789_Fill_Color(WHITE);
}
//红外收发模式
else if(STATE == IR_REMOTE) {
USART1_Tx_Puts(cmd_send_buffer1, IR_Channel);
} else if(STATE == AD_VAL) {
flag_ADS_readR = 1;
LCD_Already_Updated = false;
} else BEEP();
break;
case KEY3_PRES:
//红外选择通道:1/2/3/4
if(STATE == IR_CHANNEL_CHOOSE) {
IR_Channel = 0x03;
STATE = MENU;
LCD_Already_Updated = false;
ST7789_Fill_Color(WHITE);
} else if(STATE == TIME_SET) {
ST7789_DrawRectangle(time_set_Pos[time_set_Pos[3]], 110,
time_set_Pos[time_set_Pos[3]] + 36, 148, WHITE);
time_set_Pos[3] = (time_set_Pos[3] == 0) ? 2 : (time_set_Pos[3] - 1);
LCD_Already_Updated = false;
} else if(STATE == CLOCK_SET) {
ST7789_DrawRectangle(clock_set_Pos[clock_set_Pos[2]], 50,
clock_set_Pos[clock_set_Pos[2]] + 100, 150, WHITE);
clock_set_Pos[2] = (clock_set_Pos[2] == 0) ? 1 : 0;
LCD_Already_Updated = false;
} else BEEP();
break;
case KEY4_PRES:
//红外选择通道:1/2/3/4
if(STATE == IR_CHANNEL_CHOOSE) {
IR_Channel = 0x04;
STATE = MENU;
LCD_Already_Updated = false;
ST7789_Fill_Color(WHITE);
} else if(STATE == TIME_SET) {
if(time_set_Pos[3] == 2) {
RTC_second = (RTC_second == 59) ? 0 : RTC_second + 1;
} else if(time_set_Pos[3] == 1) {
RTC_minute = (RTC_minute == 59) ? 0 : RTC_minute + 1;
} else {
RTC_hour = (RTC_hour == 23) ? 0 : RTC_hour + 1;
}
LCD_Already_Updated = false;
} else if(STATE == CLOCK_SET) {
if(clock_set_Pos[2] == 1) {
RTC_minute = (RTC_minute == 59) ? 0 : RTC_minute + 1;
} else {
RTC_hour = (RTC_hour == 23) ? 0 : RTC_hour + 1;
}
LCD_Already_Updated = false;
} else BEEP();
break;
}
LCD_Already_Updated = false;
} //else delay_ms(10);
}