|
|
|
#include "STC8G.h" #include "intrins.h" // 定義I2C引腳 sbit SDA = P3^2; // 數(shù)據(jù)引腳 sbit SCL = P3^3; // 時(shí)鐘引腳 // INA226地址 (A0和A1接地時(shí)為0x40) #define INA226_ADDR 0x40 // INA226寄存器地址 #define INA226_REG_CONFIG 0x00 #define INA226_REG_SHUNTVOLTAGE 0x01 #define INA226_REG_BUSVOLTAGE 0x02 #define INA226_REG_POWER 0x03 #define INA226_REG_CURRENT 0x04 #define INA226_REG_CALIBRATION 0x05 // 延時(shí)函數(shù) void Delay5us() { _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); } void Delay10us() { Delay5us(); Delay5us(); } // I2C起始信號(hào) void I2C_Start() { SDA = 1; SCL = 1; Delay10us(); SDA = 0; // 在SCL高電平時(shí),SDA由高變低 Delay10us(); SCL = 0; // 鉗住SCL線,準(zhǔn)備發(fā)送或接收數(shù)據(jù) } // I2C停止信號(hào) void I2C_Stop() { SDA = 0; SCL = 1; Delay10us(); SDA = 1; // 在SCL高電平時(shí),SDA由低變高 Delay10us(); } // 發(fā)送應(yīng)答信號(hào) void I2C_Ack() { SDA = 0; SCL = 1; Delay10us(); SCL = 0; SDA = 1; Delay10us(); } // 發(fā)送非應(yīng)答信號(hào) void I2C_NAck() { SDA = 1; SCL = 1; Delay10us(); SCL = 0; Delay10us(); } // 等待應(yīng)答 bit I2C_WaitAck() { bit ackbit; SDA = 1; // 釋放SDA線 Delay10us(); SCL = 1; Delay10us(); ackbit = SDA; // 讀取應(yīng)答信號(hào) SCL = 0; Delay10us(); return ackbit; } // 發(fā)送一個(gè)字節(jié) void I2C_SendByte(unsigned char dat) { unsigned char i; for(i=0; i<8; i++) { SDA = (dat & 0x80) >> 7; // 發(fā)送高位 dat <<= 1; SCL = 1; Delay10us(); SCL = 0; Delay10us(); } I2C_WaitAck(); // 等待應(yīng)答 } // 接收一個(gè)字節(jié) unsigned char I2C_ReceiveByte() { unsigned char i, dat = 0; SDA = 1; // 釋放SDA線 for(i=0; i<8; i++) { SCL = 1; dat <<= 1; dat |= SDA; // 讀取數(shù)據(jù)位 Delay10us(); SCL = 0; Delay10us(); } return dat; } // 向INA226寫入數(shù)據(jù) void INA226_WriteReg(unsigned char reg, unsigned int data) { I2C_Start(); I2C_SendByte(INA226_ADDR << 1); // 發(fā)送地址和寫位 I2C_SendByte(reg); // 發(fā)送寄存器地址 I2C_SendByte(data >> 8); // 發(fā)送高8位數(shù)據(jù) I2C_SendByte(data & 0xFF); // 發(fā)送低8位數(shù)據(jù) I2C_Stop(); } // 從INA226讀取數(shù)據(jù) unsigned int INA226_ReadReg(unsigned char reg) { unsigned int data; unsigned char high, low; I2C_Start(); I2C_SendByte(INA226_ADDR << 1); // 發(fā)送地址和寫位 I2C_SendByte(reg); // 發(fā)送寄存器地址 I2C_Start(); I2C_SendByte((INA226_ADDR << 1) | 0x01); // 發(fā)送地址和讀位 high = I2C_ReceiveByte(); // 讀取高8位 I2C_Ack(); low = I2C_ReceiveByte(); // 讀取低8位 I2C_NAck(); I2C_Stop(); data = (high << 8) | low; return data; } // 初始化INA226 void INA226_Init() { // 配置寄存器: 16次平均, 1.1ms轉(zhuǎn)換時(shí)間(總線), 1.1ms轉(zhuǎn)換時(shí)間(分流), 連續(xù)測(cè)量模式 INA226_WriteReg(INA226_REG_CONFIG, 0x4527); // 校準(zhǔn)寄存器 (根據(jù)實(shí)際分流電阻調(diào)整,這里假設(shè)0.1歐) // 校準(zhǔn)值 = 0.00512 / (分流電阻 * 電流LSB) // 電流LSB = 期望最大電流 / 2^15 // 這里設(shè)置電流LSB為1mA (最大電流32.768A) INA226_WriteReg(INA226_REG_CALIBRATION, 0x0A00); } // 讀取總線電壓 (mV) float INA226_ReadBusVoltage() { unsigned int data; data = INA226_ReadReg(INA226_REG_BUSVOLTAGE); // 總線電壓分辨率為1.25mV,左移3位 return (data >> 3) * 1.25; } // 讀取分流電壓 (uV) float INA226_ReadShuntVoltage() { signed int data; data = (signed int)INA226_ReadReg(INA226_REG_SHUNTVOLTAGE); // 分流電壓分辨率為2.5uV return data * 2.5; } // 讀取電流 (mA) float INA226_ReadCurrent() { signed int data; data = (signed int)INA226_ReadReg(INA226_REG_CURRENT); // 電流LSB為1mA (由校準(zhǔn)寄存器設(shè)置) return data * 1.0; } // 讀取功率 (mW) float INA226_ReadPower() { unsigned int data; data = INA226_ReadReg(INA226_REG_POWER); // 功率LSB為25mW (由校準(zhǔn)寄存器設(shè)置,是電流LSB的25倍) return data * 25.0; } // 初始化UART用于輸出數(shù)據(jù) void UART_Init() { SCON = 0x50; // 8位數(shù)據(jù), 可變波特率 TMOD &= 0x0F; TMOD |= 0x20; // 定時(shí)器1工作在模式2 TL1 = 0xFD; // 波特率9600 (11.0592MHz) TH1 = 0xFD; ET1 = 0; // 禁止定時(shí)器1中斷 TR1 = 1; // 啟動(dòng)定時(shí)器1 ES = 0; // 禁止UART中斷 } // 發(fā)送一個(gè)字符 void UART_SendChar(unsigned char c) { SBUF = c; while(!TI); TI = 0; } // 發(fā)送字符串 void UART_SendString(unsigned char *str) { while(*str) { UART_SendChar(*str++); } } // 發(fā)送浮點(diǎn)數(shù) void UART_SendFloat(float num, unsigned char decimal_places) { unsigned long integer_part; unsigned long fractional_part; unsigned char i; // 處理負(fù)數(shù) if(num < 0) { UART_SendChar('-'); num = -num; } // 提取整數(shù)部分 integer_part = (unsigned long)num; // 提取小數(shù)部分 fractional_part = 0; for(i = 0; i < decimal_places; i++) { num = (num - integer_part) * 10; fractional_part = fractional_part * 10 + (unsigned long)num; integer_part = (unsigned long)num; } // 發(fā)送整數(shù)部分 if(integer_part == 0) { UART_SendChar('0'); } else { // 用于反轉(zhuǎn)數(shù)字的緩沖區(qū) unsigned char buf[10]; unsigned char len = 0; while(integer_part > 0) { buf[len++] = '0' + (integer_part % 10); integer_part /= 10; } // 反轉(zhuǎn)并發(fā)送 for(i = len; i > 0; i--) { UART_SendChar(buf[i-1]); } } // 發(fā)送小數(shù)點(diǎn)和小數(shù)部分 if(decimal_places > 0) { UART_SendChar('.'); // 處理小數(shù)部分前導(dǎo)零 unsigned long temp = fractional_part; unsigned char frac_len = 0; if(temp == 0) { frac_len = decimal_places; } else { while(temp > 0) { frac_len++; temp /= 10; } // 補(bǔ)零 for(i = 0; i < decimal_places - frac_len; i++) { UART_SendChar('0'); } } // 發(fā)送小數(shù)部分 UART_SendString("000000"); // 最多支持6位小數(shù) // 注意:這里簡化處理,實(shí)際應(yīng)用中應(yīng)正確轉(zhuǎn)換fractional_part } } void main() { float voltage, current, power; // 初始化外設(shè) UART_Init(); INA226_Init(); UART_SendString("INA226 Test Program\r\n"); while(1) { // 讀取數(shù)據(jù) voltage = INA226_ReadBusVoltage(); current = INA226_ReadCurrent(); power = INA226_ReadPower(); // 發(fā)送數(shù)據(jù)到UART UART_SendString("Voltage: "); UART_SendFloat(voltage / 1000, 2); // 轉(zhuǎn)換為V UART_SendString("V, Current: "); UART_SendFloat(current, 2); // mA UART_SendString("mA, Power: "); UART_SendFloat(power / 1000, 2); // 轉(zhuǎn)換為W UART_SendString("W\r\n"); // 延時(shí)約1秒 { unsigned int i, j; for(i = 0; i < 1000; i++) for(j = 0; j < 1000; j++) _nop_(); } } } |
|