基于便攜式STM32的紅外信號分析儀 - 單片機 物聯(lián)網(wǎng) 嵌入式(含代碼)
- 難度系數(shù):3分
- 工作量:3分
-
創(chuàng)新點:5分
1 簡介
由STM32F411CEU6作為主控芯片的帶有姿態(tài)感應,紅外輸入,紅外輸出,可根據(jù)任意錄入的紅外信號進行存儲,然后發(fā)出紅外線控制各種電器設備, 并具有測電流,電壓,電阻,電容能力的手表,是對于電子工程師來說具有較強實用性的小工具。
2 主要器件
- STM32F411CEU6主控芯片
- ACS712電流傳感器芯片
- TC單片機
3 實現(xiàn)效果
4 設計原理
硬件
- 電壓檢測電路,主要是將外部-15v15v的電壓通過幾個限壓電阻根據(jù)KCL和KVL轉(zhuǎn)化成03.3v,再由ADC芯片采集;
- 電阻檢測電路,根據(jù)簡單的分壓原理,將待測電阻通過模擬開關(guān)分別與1k和1M歐高精度電阻串聯(lián)測得分壓,從而實現(xiàn)精確測量較大范圍內(nèi)的電阻阻值;
- 電容檢測電路,根據(jù)電容的一階零狀態(tài)響應,算出時間常數(shù),再根據(jù)串聯(lián)的電阻計算出接入電容的電容值;
- )紅外接收發(fā)射電路,采用外加一塊STC單片機(一個模塊~~~~),里面預先燒錄紅外解碼程序,再通過串口與STM32通訊,實現(xiàn)對外部輸入紅外信號的解碼和調(diào)制發(fā)射;
軟件
- 姿態(tài)解算算法,實現(xiàn)步數(shù)計算,抬手感應,翻腕感應,LCD虛擬觸屏;
- 針對不同紅外信號的解碼和發(fā)射算法,紅外信號存儲算法等;
- 電阻,電容測量算法;
- 自制定時器系統(tǒng)任務調(diào)度算法。
主要原理圖
5 部分核心代碼
#include "main.h" /********************變量聲明區(qū)_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; //加速度傳感器原始數(shù)據(jù)
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}; //顯示紅外碼存儲區(qū)是否為空:0-空 1-有
uint16_t time_set_Pos[4] = {54, 102, 150, 2};
uint16_t clock_set_Pos[3] = {5, 135, 1};
/** * @brief 決定系統(tǒng)狀態(tài)的選擇 * @param 菜單;紅外收發(fā)模式;紅外通道選擇模式;陀螺儀模式;模擬量測試模式;
*/
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;
/********************變量聲明區(qū)_END********************/
/********************API聲明區(qū)_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聲明區(qū)_END********************/
/********************************************************************************************************* * 函 數(shù): 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); } }
/********************************************************************************************************* * 內(nèi)部函數(shù)實現(xiàn) *********************************************************************************************************/
/********************************************************************************************************* * 函數(shù)名稱: Proc2msTask * 函數(shù)功能: 處理2ms任務 * 輸入?yún)?shù): void * 輸出參數(shù): 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(); } }
/********************************************************************************************************* * 函數(shù)名稱: Proc50msTask * 函數(shù)功能: 處理50ms任務 * 輸入?yún)?shù): void * 輸出參數(shù): 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);//設置系統(tǒng)中斷優(yōu)先級分組2 delay_init(104); //初始化延時函數(shù) uart_init(115200); //初始化串口 InitTimer(); //初始化任務調(diào)度定時器 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); } //紅外收發(fā)模式 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); } //紅外收發(fā)模式 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); }
完整代碼可進群免費領(lǐng)取。
5 最后
嵌入式物聯(lián)網(wǎng)的學習之路非常漫長,不少人因為學習路線不對或者學習內(nèi)容不夠?qū)I(yè)而錯失高薪offer。不過別擔心,我為大家整理了一份150多G的學習資源,基本上涵蓋了嵌入式物聯(lián)網(wǎng)學習的所有內(nèi)容。點擊下方鏈接,0元領(lǐng)取學習資源,讓你的學習之路更加順暢!記得點贊、關(guān)注、收藏、轉(zhuǎn)發(fā)哦!
點擊這里找小助理0元領(lǐng)取:掃碼進群領(lǐng)資料
- 贊