?
?
系統總體框圖
功率檢測裝置原理圖功能及模塊連接說明
一、系統功能概述
該裝置以STM32F103C8T6微控制器為核心,集成功率檢測、數據交互、狀態顯示和用戶提示功能,通過模塊化設計實現穩定運行。
二、各模塊功能及連接方式
- 按鍵模塊
功能:用戶交互控制(啟動/停止設備)。
連接方式:
按鍵SW1一端接地(GND),另一端通過電阻R5連接至微控制器GPIO引腳PA0。
按鍵按下時觸發PA0電平變化,觸發中斷或狀態讀取。
- LED指示燈模塊
功能:顯示設備狀態(如運行、告警)。
連接方式:
LED1(R6)和LED2(R7)分別連接至微控制器GPIO引腳PB0和PB1。
GPIO輸出高電平時LED點亮,低電平時熄滅。
- 微控制器(STM32F103C8T6)
功能:系統控制核心,處理數據、控制外設、驅動顯示。
連接方式:
通信接口:
USART1_TX/RX引腳連接調試接口(J4),支持程序燒錄和調試。
I2C接口(SCL/SDA)連接OLED屏幕。
控制引腳:
GPIO引腳控制LED、蜂鳴器、按鍵等外設。
- OLED屏幕模塊
功能:顯示功率檢測結果及系統信息。
連接方式:
I2C接口(SCL/SDA)與微控制器相連。
電源由3.3V降壓電路供電,接地至GND。
- INA226電壓電流檢測模塊
功能:檢測電壓電流以及功率。
連接方式:
I2C接口(SCL/SDA)與微控制器相連。
電源由3.3V降壓電路供電,接地至GND。
- 復位電路模塊
功能:強制復位微控制器。
連接方式:
復位按鈕SW5通過電阻R11連接至NRST引腳,電容C1用于濾波。
- 晶振電路模塊
功能:提供穩定時鐘信號(8MHz主頻)。
連接方式:
晶振X1連接至OSC_IN/OSC_OUT引腳,電容C5/C6接地。
- 蜂鳴器驅動模塊
功能:聲音提示(如異常報警)。
連接方式:
蜂鳴器BUZZER2通過三極管Q3和電阻R79/R80連接至微控制器GPIO(BUZZER_PIN)。
GPIO高電平時三極管導通,蜂鳴器發聲。
- 輸入輸出接口模塊
功能:輸入接口用于采集電壓電流參數,輸出接口接后級用電設備。
連接方式:
通過J2/J3連接器提供VIN+/VIN-/GND等接口。
調試接口模塊
功能:程序燒錄與調試(SWD或UART)。
連接方式:
J4接口提供USART1_TX/RX/GND信號。
- 3.3V降壓電路模塊
功能:將5V轉換為3.3V,為系統供電。
連接方式:
LDO穩壓器MEB211輸入5V,輸出3.3V,電容C3/C4濾波。
三、系統運行邏輯
微控制器通過按鍵檢測用戶輸入,啟動功率檢測。
檢測數據通過輸入接口采集,處理后通過OLED顯示。
異常情況觸發蜂鳴器報警,LED狀態指示同步反饋。
3.3V降壓電路為所有模塊提供穩定電源,晶振電路確保時序精度。
?
/*** @file INA226.c* @brief INA226電流/功率監測芯片的驅動程序* 使用硬件I2C2接口與INA226通信*/#include "ina226.h"
#include "i2c.h"/*** @brief INA226 I2C初始化* @note 使用Core/Src/i2c.c中已初始化的hi2c1,無需重復初始化*/
void INA226_IIC_Init(void)
{// 使用項目中已初始化的hi2c1
}/*** @brief 初始化INA226芯片* 配置芯片工作模式和校準值*/
void INA226_Init(void)
{INA226_IIC_Init();HAL_Delay(10); // 等待芯片上電穩定// 配置寄存器: 64次平均值,全功能,連續模式INA226_SendData(WRITE_ADDR, Config_Reg, 0x4727);// 校準寄存器: 當單位為mA時,0.002R=0xA00;0.01R=0x200 (最大8A)INA226_SendData(WRITE_ADDR, Calib_Reg, 0x200);
}/*** @brief 向INA226寫入數據* @param addr 器件地址(7位)* @param reg 寄存器地址* @param data 要寫入的16位數據*/
void INA226_SendData(uint8_t addr, uint8_t reg, uint16_t data)
{uint8_t buf[2] = {(uint8_t)(data >> 8), (uint8_t)(data & 0xFF)};HAL_I2C_Mem_Write(&hi2c1, addr, reg, I2C_MEMADD_SIZE_8BIT, buf, 2, HAL_MAX_DELAY);
}/*** @brief 設置INA226的寄存器指針* @param addr 器件地址(7位)* @param reg 要設置的寄存器地址*/
void INA226_SetRegPointer(uint8_t addr, uint8_t reg)
{HAL_I2C_Master_Transmit(&hi2c1, addr, ®, 1, HAL_MAX_DELAY);
}/*** @brief 從INA226讀取數據* @param addr 器件地址(7位)* @return 讀取到的16位數據*/
uint16_t INA226_ReadData(uint8_t addr)
{uint8_t buf[2];HAL_I2C_Master_Receive(&hi2c1, addr | 0x01, buf, 2, HAL_MAX_DELAY);return (buf[0] << 8) | buf[1];
}/*** @brief 獲取分流電流值* @param addr 器件地址(7位)* @return 分流電流值(原始數據)*/
uint16_t INA226_GetShuntCurrent(uint8_t addr)
{uint16_t temp = 0;INA226_SetRegPointer(addr, Current_Reg);temp = INA226_ReadData(addr);return temp;
}/*** @brief 獲取器件ID* @param addr 器件地址(7位)* @return 器件ID(應為0x2260)*/
uint16_t INA226_Get_ID(uint8_t addr)
{uint16_t temp = 0;INA226_SetRegPointer(addr, ID_Reg);temp = INA226_ReadData(addr);return temp;
}/*** @brief 獲取校準寄存器值* @param addr 器件地址(7位)* @return 校準寄存器當前值*/
uint16_t INA226_GET_CAL_REG(uint8_t addr)
{uint16_t temp = 0;INA226_SetRegPointer(addr, Calib_Reg);temp = INA226_ReadData(addr);return temp;
}/*** @brief 獲取總線電壓值* @param addr 器件地址(7位)* @return 總線電壓值(1.25mV/bit)*/
uint16_t INA226_GetVoltage(uint8_t addr)
{uint16_t temp = 0;INA226_SetRegPointer(addr, Bus_V_Reg);temp = INA226_ReadData(addr);return temp;
}/*** @brief 獲取分流電壓值* @param addr 器件地址(7位)* @return 分流電壓值(2.5uV/bit),已處理負數情況*/
uint16_t INA226_GetShuntVoltage(uint8_t addr)
{uint16_t temp = 0;INA226_SetRegPointer(addr, Shunt_V_Reg);temp = INA226_ReadData(addr);if (temp & 0x8000) // 處理負數情況temp = ~(temp - 1);return temp;
}/*** @brief 獲取功率值* @param addr 器件地址(7位)* @return 功率值(2.5mW/bit)*/
uint16_t INA226_Get_Power(uint8_t addr)
{uint16_t temp = 0;INA226_SetRegPointer(addr, Power_Reg);temp = INA226_ReadData(addr);return temp;
}
#include "ocv.h"
#include "ina226.h"INA226 CC, OCV; // 定義CC(充電電流)和OCV(開路電壓)監測結構體/*** @brief INA226應用示例* 使用步驟:* 1. 調用INA226_Init()初始化INA226芯片* 2. 定期調用Get_Vol()、Get_Cur()、Get_Pow()獲取測量值* 3. 從CC結構體讀取測量結果*/extern INA226 CC, OCV;
uint8_t CC_MODE[] = "CC MODE";
uint8_t Vol[] = "Voltage:";
uint8_t Cur[] = "Current:";
uint8_t Power[] = "Power:";/*** @brief 測試USB CC模式函數** 在OLED屏幕上顯示電壓、電流和功率值。** @return 無返回值*/
void USB_CC_TESTER(void)
{OLED_Printf(0, 0, OLED_8X16, "電壓電流功率儀");OLED_ShowString(0, 16, (char *)Vol, OLED_8X16);OLED_ShowString(0, 32, (char *)Cur, OLED_8X16);OLED_ShowString(0, 48, (char *)Power, OLED_8X16);OLED_Update();
}/*** @brief 顯示電壓電流功率儀信息** 在OLED顯示屏上顯示電壓、電流和功率信息,并通過串口輸出相同的信息。** @return 無*/
void Show_CC(void)
{OLED_Clear();OLED_Printf(0, 0, OLED_8X16, "電壓電流功率儀");OLED_Printf(0, 16, OLED_8X16, "Voltage:%.2f", ((float)CC.voltage_V + ((float)CC.voltage_mV / 100)) * 500);OLED_Printf(0, 32, OLED_8X16, "Current:%.2f", (float)CC.current_A + ((float)CC.current_mA / 1000));OLED_Printf(0, 48, OLED_8X16, "Power:%.2f", ((float)CC.power_W + ((float)CC.power_mW / 100)) * 500);OLED_Update();Serial_Printf_huart2("Voltage:%.2f,Current:%.2f,Power:%.2f\r\n", ((float)CC.voltage_V + ((float)CC.voltage_mV / 100)) * 500, (float)CC.current_A + ((float)CC.current_mA / 1000), ((float)CC.power_W + ((float)CC.power_mW / 100)) * 500);
}/* 示例1: 完整測量流程 */
void Example_MeasureAll(void)
{// 1. 初始化INA226INA226_Init();// 2. 進行測量Get_Vol(); // 獲取電壓Get_Cur(); // 獲取電流Get_Pow(); // 獲取功率// 3. 使用測量結果// CC.voltage_V - 電壓整數部分(V)// CC.voltage_mV - 電壓小數部分(mV)// CC.current_A - 電流整數部分(A)// CC.current_mA - 電流小數部分(mA)// CC.power_W - 功率整數部分(W)// CC.power_mW - 功率小數部分(mW)
}/* 示例2: 僅電壓測量 */
float Example_GetVoltage(void)
{Get_Vol();return CC.voltage_V + (CC.voltage_mV / 1000.0f);
}/* 示例3: 電流方向檢測 */
uint8_t Example_IsCharging(void)
{Get_Cur();return (CC.current_signed == 1); // 1表示充電,0表示放電
}/*** @brief 獲取電壓測量值* 將原始數據轉換為實際電壓值(V)*/
void Get_Vol(void)
{uint16_t Vol;Vol = INA226_GetVoltage(WRITE_ADDR) / 8; // 1.25mV/bit -> VCC.voltage_V = Vol / 100; // 整數部分(V)CC.voltage_mV = Vol % 100; // 小數部分(mV)
}/*** @brief 獲取電流測量值* 自動檢測電流方向(充電/放電)*/
void Get_Cur(void)
{uint16_t Cur;Cur = INA226_GetShuntCurrent(WRITE_ADDR);CC.current_signed = 1; // 默認充電狀態if (Cur & 0x8000) // 檢測電流方向{Cur = ~(Cur - 1); // 處理負電流值CC.current_signed = 0; // 設置為放電狀態}CC.current_A = Cur / 1000; // 整數部分(A)CC.current_mA = Cur % 1000; // 小數部分(mA)
}/*** @brief 獲取功率測量值* 將原始數據轉換為實際功率值(W)*/
void Get_Pow(void)
{uint16_t Pow;Pow = (INA226_Get_Power(WRITE_ADDR) * 5) / 2; // 2.5mW/bit -> WCC.power_W = Pow / 100; // 整數部分(W)CC.power_mW = Pow % 100; // 小數部分(mW)
}
單片機定制: