|
#include "STC8G.h" #include "intrins.h" // 定义I2C引脚 sbit SDA = P3^2; // 数据引脚 sbit SCL = P3^3; // 时钟引脚 // INA226地址 (A0和A1接地时为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 // 延时函数 void Delay5us() { _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); _nop_();_nop_();_nop_();_nop_(); } void Delay10us() { Delay5us(); Delay5us(); } // I2C起始信号 void I2C_Start() { SDA = 1; SCL = 1; Delay10us(); SDA = 0; // 在SCL高电平时,SDA由高变低 Delay10us(); SCL = 0; // 钳住SCL线,准备发送或接收数据 } // I2C停止信号 void I2C_Stop() { SDA = 0; SCL = 1; Delay10us(); SDA = 1; // 在SCL高电平时,SDA由低变高 Delay10us(); } // 发送应答信号 void I2C_Ack() { SDA = 0; SCL = 1; Delay10us(); SCL = 0; SDA = 1; Delay10us(); } // 发送非应答信号 void I2C_NAck() { SDA = 1; SCL = 1; Delay10us(); SCL = 0; Delay10us(); } // 等待应答 bit I2C_WaitAck() { bit ackbit; SDA = 1; // 释放SDA线 Delay10us(); SCL = 1; Delay10us(); ackbit = SDA; // 读取应答信号 SCL = 0; Delay10us(); return ackbit; } // 发送一个字节 void I2C_SendByte(unsigned char dat) { unsigned char i; for(i=0; i<8; i++) { SDA = (dat & 0x80) >> 7; // 发送高位 dat <<= 1; SCL = 1; Delay10us(); SCL = 0; Delay10us(); } I2C_WaitAck(); // 等待应答 } // 接收一个字节 unsigned char I2C_ReceiveByte() { unsigned char i, dat = 0; SDA = 1; // 释放SDA线 for(i=0; i<8; i++) { SCL = 1; dat <<= 1; dat |= SDA; // 读取数据位 Delay10us(); SCL = 0; Delay10us(); } return dat; } // 向INA226写入数据 void INA226_WriteReg(unsigned char reg, unsigned int data) { I2C_Start(); I2C_SendByte(INA226_ADDR << 1); // 发送地址和写位 I2C_SendByte(reg); // 发送寄存器地址 I2C_SendByte(data >> 8); // 发送高8位数据 I2C_SendByte(data & 0xFF); // 发送低8位数据 I2C_Stop(); } // 从INA226读取数据 unsigned int INA226_ReadReg(unsigned char reg) { unsigned int data; unsigned char high, low; I2C_Start(); I2C_SendByte(INA226_ADDR << 1); // 发送地址和写位 I2C_SendByte(reg); // 发送寄存器地址 I2C_Start(); I2C_SendByte((INA226_ADDR << 1) | 0x01); // 发送地址和读位 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转换时间(总线), 1.1ms转换时间(分流), 连续测量模式 INA226_WriteReg(INA226_REG_CONFIG, 0x4527); // 校准寄存器 (根据实际分流电阻调整,这里假设0.1欧) // 校准值 = 0.00512 / (分流电阻 * 电流LSB) // 电流LSB = 期望最大电流 / 2^15 // 这里设置电流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 (由校准寄存器设置) return data * 1.0; } // 读取功率 (mW) float INA226_ReadPower() { unsigned int data; data = INA226_ReadReg(INA226_REG_POWER); // 功率LSB为25mW (由校准寄存器设置,是电流LSB的25倍) return data * 25.0; } // 初始化UART用于输出数据 void UART_Init() { SCON = 0x50; // 8位数据, 可变波特率 TMOD &= 0x0F; TMOD |= 0x20; // 定时器1工作在模式2 TL1 = 0xFD; // 波特率9600 (11.0592MHz) TH1 = 0xFD; ET1 = 0; // 禁止定时器1中断 TR1 = 1; // 启动定时器1 ES = 0; // 禁止UART中断 } // 发送一个字符 void UART_SendChar(unsigned char c) { SBUF = c; while(!TI); TI = 0; } // 发送字符串 void UART_SendString(unsigned char *str) { while(*str) { UART_SendChar(*str++); } } // 发送浮点数 void UART_SendFloat(float num, unsigned char decimal_places) { unsigned long integer_part; unsigned long fractional_part; unsigned char i; // 处理负数 if(num < 0) { UART_SendChar('-'); num = -num; } // 提取整数部分 integer_part = (unsigned long)num; // 提取小数部分 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; } // 发送整数部分 if(integer_part == 0) { UART_SendChar('0'); } else { // 用于反转数字的缓冲区 unsigned char buf[10]; unsigned char len = 0; while(integer_part > 0) { buf[len++] = '0' + (integer_part % 10); integer_part /= 10; } // 反转并发送 for(i = len; i > 0; i--) { UART_SendChar(buf[i-1]); } } // 发送小数点和小数部分 if(decimal_places > 0) { UART_SendChar('.'); // 处理小数部分前导零 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; } // 补零 for(i = 0; i < decimal_places - frac_len; i++) { UART_SendChar('0'); } } // 发送小数部分 UART_SendString("000000"); // 最多支持6位小数 // 注意:这里简化处理,实际应用中应正确转换fractional_part } } void main() { float voltage, current, power; // 初始化外设 UART_Init(); INA226_Init(); UART_SendString("INA226 Test Program\r\n"); while(1) { // 读取数据 voltage = INA226_ReadBusVoltage(); current = INA226_ReadCurrent(); power = INA226_ReadPower(); // 发送数据到UART UART_SendString("Voltage: "); UART_SendFloat(voltage / 1000, 2); // 转换为V UART_SendString("V, Current: "); UART_SendFloat(current, 2); // mA UART_SendString("mA, Power: "); UART_SendFloat(power / 1000, 2); // 转换为W UART_SendString("W\r\n"); // 延时约1秒 { unsigned int i, j; for(i = 0; i < 1000; i++) for(j = 0; j < 1000; j++) _nop_(); } } } |