#include <STC8H.H> // STC8H系列头文件
#include <intrins.h> // 延时函数需要
#include <stdio.h> // 用于sprintf函数
#include <math.h> // log10函数需要
#define u8 unsigned char
#define u16 unsigned int
#define u32 unsigned long
// ------ 新增宏定义 ------
#define RELAY_PORT0 0 // 控制K1-K8的端口
#define RELAY_PORT4 1 // 控制K9-K16的端口
#define OPAMP_SINGLE 0 // 运放类型
#define OPAMP_DUAL 1
#define OPAMP_QUAD 2
// ADS1115 I2C地址(ADDR接地为0x48,接VCC为0x49)
#define ADS1115_ADDR 0x48
// LCD引脚定义
sbit LCD_E = P3^2; // 使能信号
sbit LCD_DI = P3^3; // 数据/指令选择
sbit LCD_CS1 = P3^4; // 左半屏片选
sbit LCD_CS2 = P3^5; // 右半屏片选
sbit LCD_RST = P3^6; // 复位
sbit LCD_RW = P3^7; // 读写选择
// 全局变量存储测量值(XDATA区)
xdata float Vos = 0.0f;
xdata float IB = 0.0f;
xdata float Vo1 = 0.0f;
xdata float Vo1_prime = 0.0f;
xdata float Aol = 0.0f;
xdata float PSRR = 0.0f;
xdata float VoMax = 0.0f;
// ------ 新增全局变量 ------
xdata u8 OpampType = 0; // 当前运放类型(默认单运放)
bit RST_Flag = 0; // 复位标志
unsigned char code ASCII_FONT[95][16] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"!",0*/
{0x00,0x00,0x10,0x00,0x0C,0x00,0x02,0x00,0x10,0x00,0x0C,0x00,0x02,0x00,0x00,0x00},/*""",1*/
{0x00,0x00,0x40,0x04,0xC0,0x3F,0x78,0x04,0x40,0x04,0xC0,0x3F,0x78,0x04,0x00,0x00},/*"#",2*/
{0x00,0x00,0x70,0x18,0x88,0x20,0x88,0x20,0xFC,0xFF,0x08,0x21,0x30,0x1E,0x00,0x00},/*"$",3*/
{0xF0,0x00,0x08,0x31,0xF0,0x0C,0x80,0x03,0x60,0x1E,0x18,0x21,0x00,0x1E,0x00,0x00},/*"%",4*/
{0x00,0x1E,0xF0,0x21,0x08,0x23,0x88,0x2C,0x70,0x19,0x00,0x27,0x00,0x21,0x00,0x10},/*"&",5*/
{0x00,0x00,0x12,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",6*/
{0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x18,0x18,0x04,0x20,0x02,0x40,0x00,0x00},/*"(",7*/
{0x00,0x00,0x02,0x40,0x04,0x20,0x18,0x18,0xE0,0x07,0x00,0x00,0x00,0x00,0x00,0x00},/*")",8*/
{0x40,0x02,0x40,0x02,0x80,0x01,0xF0,0x0F,0x80,0x01,0x40,0x02,0x40,0x02,0x00,0x00},/*"*",9*/
{0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0xE0,0x0F,0x00,0x01,0x00,0x01,0x00,0x01},/*"+",10*/
{0x00,0x00,0x00,0x90,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*",",11*/
{0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00},/*"-",12*/
{0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*".",13*/
{0x00,0x00,0x00,0x60,0x00,0x18,0x00,0x07,0xC0,0x00,0x38,0x00,0x04,0x00,0x00,0x00},/*"/",14*/
{0x00,0x00,0xE0,0x0F,0x10,0x10,0x08,0x20,0x08,0x20,0x10,0x10,0xE0,0x0F,0x00,0x00},/*"0",15*/
{0x00,0x00,0x00,0x00,0x10,0x20,0x10,0x20,0xF8,0x3F,0x00,0x20,0x00,0x20,0x00,0x00},/*"1",16*/
{0x00,0x00,0x70,0x30,0x08,0x28,0x08,0x24,0x08,0x22,0x08,0x21,0xF0,0x30,0x00,0x00},/*"2",17*/
{0x00,0x00,0x30,0x18,0x08,0x20,0x08,0x21,0x08,0x21,0x88,0x22,0x70,0x1C,0x00,0x00},/*"3",18*/
{0x00,0x00,0x00,0x06,0x80,0x05,0x40,0x24,0x30,0x24,0xF8,0x3F,0x00,0x24,0x00,0x24},/*"4",19*/
{0x00,0x00,0xF8,0x19,0x88,0x20,0x88,0x20,0x88,0x20,0x08,0x11,0x08,0x0E,0x00,0x00},/*"5",20*/
{0x00,0x00,0xE0,0x0F,0x10,0x11,0x88,0x20,0x88,0x20,0x90,0x20,0x00,0x1F,0x00,0x00},/*"6",21*/
{0x00,0x00,0x18,0x00,0x08,0x00,0x08,0x3E,0x88,0x01,0x68,0x00,0x18,0x00,0x00,0x00},/*"7",22*/
{0x00,0x00,0x70,0x1C,0x88,0x22,0x08,0x21,0x08,0x21,0x88,0x22,0x70,0x1C,0x00,0x00},/*"8",23*/
{0x00,0x00,0xF0,0x01,0x08,0x12,0x08,0x22,0x08,0x22,0x10,0x11,0xE0,0x0F,0x00,0x00},/*"9",24*/
{0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x30,0xC0,0x30,0x00,0x00,0x00,0x00,0x00,0x00},/*":",25*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*";",26*/
{0x00,0x00,0x00,0x01,0x80,0x02,0x40,0x04,0x20,0x08,0x10,0x10,0x08,0x20,0x00,0x00},/*"<",27*/
{0x00,0x00,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x00,0x00},/*"=",28*/
{0x00,0x00,0x08,0x20,0x10,0x10,0x20,0x08,0x40,0x04,0x80,0x02,0x00,0x01,0x00,0x00},/*">",29*/
{0x00,0x00,0x70,0x00,0x48,0x00,0x08,0x30,0x08,0x37,0x88,0x00,0x70,0x00,0x00,0x00},/*"?",30*/
{0xC0,0x07,0x30,0x18,0xC8,0x27,0x28,0x28,0xE8,0x2F,0x10,0x28,0xE0,0x17,0x00,0x00},/*"@",31*/
{0x00,0x20,0x00,0x3C,0xC0,0x23,0x38,0x02,0xE0,0x02,0x00,0x27,0x00,0x38,0x00,0x20},/*"A",32*/
{0x08,0x20,0xF8,0x3F,0x88,0x20,0x88,0x20,0x88,0x20,0x70,0x11,0x00,0x0E,0x00,0x00},/*"B",33*/
{0xC0,0x07,0x30,0x18,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x10,0x38,0x08,0x00,0x00},/*"C",34*/
{0x08,0x20,0xF8,0x3F,0x08,0x20,0x08,0x20,0x08,0x20,0x10,0x10,0xE0,0x0F,0x00,0x00},/*"D",35*/
{0x08,0x20,0xF8,0x3F,0x88,0x20,0x88,0x20,0xE8,0x23,0x08,0x20,0x10,0x18,0x00,0x00},/*"E",36*/
{0x08,0x20,0xF8,0x3F,0x88,0x20,0x88,0x00,0xE8,0x03,0x08,0x00,0x10,0x00,0x00,0x00},/*"F",37*/
{0xC0,0x07,0x30,0x18,0x08,0x20,0x08,0x20,0x08,0x22,0x38,0x1E,0x00,0x02,0x00,0x00},/*"G",38*/
{0x08,0x20,0xF8,0x3F,0x08,0x21,0x00,0x01,0x00,0x01,0x08,0x21,0xF8,0x3F,0x08,0x20},/*"H",39*/
{0x00,0x00,0x08,0x20,0x08,0x20,0xF8,0x3F,0x08,0x20,0x08,0x20,0x00,0x00,0x00,0x00},/*"I",40*/
{0x00,0xC0,0x00,0x80,0x08,0x80,0x08,0x80,0xF8,0x7F,0x08,0x00,0x08,0x00,0x00,0x00},/*"J",41*/
{0x08,0x20,0xF8,0x3F,0x88,0x20,0xC0,0x01,0x28,0x26,0x18,0x38,0x08,0x20,0x00,0x00},/*"K",42*/
{0x08,0x20,0xF8,0x3F,0x08,0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0x30,0x00,0x00},/*"L",43*/
{0x08,0x20,0xF8,0x3F,0xF8,0x01,0x00,0x3E,0xF8,0x01,0xF8,0x3F,0x08,0x20,0x00,0x00},/*"M",44*/
{0x08,0x20,0xF8,0x3F,0x30,0x20,0xC0,0x00,0x00,0x07,0x08,0x18,0xF8,0x3F,0x08,0x00},/*"N",45*/
{0xE0,0x0F,0x10,0x10,0x08,0x20,0x08,0x20,0x08,0x20,0x10,0x10,0xE0,0x0F,0x00,0x00},/*"O",46*/
{0x08,0x20,0xF8,0x3F,0x08,0x21,0x08,0x01,0x08,0x01,0x08,0x01,0xF0,0x00,0x00,0x00},/*"P",47*/
{0xE0,0x0F,0x10,0x10,0x08,0x28,0x08,0x28,0x08,0x30,0x10,0x50,0xE0,0x4F,0x00,0x00},/*"Q",48*/
{0x08,0x20,0xF8,0x3F,0x88,0x20,0x88,0x00,0x88,0x03,0x88,0x0C,0x70,0x30,0x00,0x20},/*"R",49*/
{0x00,0x00,0x70,0x38,0x88,0x20,0x08,0x21,0x08,0x21,0x08,0x22,0x38,0x1C,0x00,0x00},/*"S",50*/
{0x18,0x00,0x08,0x00,0x08,0x20,0xF8,0x3F,0x08,0x20,0x08,0x00,0x18,0x00,0x00,0x00},/*"T",51*/
{0x08,0x00,0xF8,0x1F,0x08,0x20,0x00,0x20,0x00,0x20,0x08,0x20,0xF8,0x1F,0x08,0x00},/*"U",52*/
{0x08,0x00,0x78,0x00,0x88,0x07,0x00,0x38,0x00,0x0E,0xC8,0x01,0x38,0x00,0x08,0x00},/*"V",53*/
{0x08,0x00,0xF8,0x03,0x00,0x3E,0xF8,0x01,0x00,0x3E,0xF8,0x03,0x08,0x00,0x00,0x00},/*"W",54*/
{0x08,0x20,0x18,0x30,0x68,0x2C,0x80,0x03,0x80,0x03,0x68,0x2C,0x18,0x30,0x08,0x20},/*"X",55*/
{0x08,0x00,0x38,0x00,0xC8,0x20,0x00,0x3F,0xC8,0x20,0x38,0x00,0x08,0x00,0x00,0x00},/*"Y",56*/
{0x10,0x20,0x08,0x38,0x08,0x26,0x08,0x21,0xC8,0x20,0x38,0x20,0x08,0x18,0x00,0x00},/*"Z",57*/
{0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x7F,0x02,0x40,0x02,0x40,0x02,0x40,0x00,0x00},/*"[",58*/
{0x00,0x00,0x04,0x00,0x38,0x00,0xC0,0x01,0x00,0x06,0x00,0x38,0x00,0xC0,0x00,0x00},/*"\",59*/
{0x00,0x00,0x02,0x40,0x02,0x40,0x02,0x40,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0x00},/*"]",60*/
{0x00,0x00,0x00,0x00,0x04,0x00,0x02,0x00,0x02,0x00,0x04,0x00,0x00,0x00,0x00,0x00},/*"^",61*/
{0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80},/*"_",62*/
{0x00,0x00,0x02,0x00,0x02,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",63*/
{0x00,0x00,0x00,0x19,0x80,0x24,0x80,0x24,0x80,0x12,0x00,0x3F,0x00,0x20,0x00,0x00},/*"a",64*/
{0x10,0x00,0xF0,0x3F,0x00,0x11,0x80,0x20,0x80,0x20,0x00,0x11,0x00,0x0E,0x00,0x00},/*"b",65*/
{0x00,0x00,0x00,0x0E,0x00,0x11,0x80,0x20,0x80,0x20,0x80,0x20,0x00,0x11,0x00,0x00},/*"c",66*/
{0x00,0x00,0x00,0x1F,0x80,0x20,0x80,0x20,0x80,0x20,0x90,0x10,0xF0,0x3F,0x00,0x20},/*"d",67*/
{0x00,0x00,0x00,0x1F,0x80,0x24,0x80,0x24,0x80,0x24,0x80,0x24,0x00,0x17,0x00,0x00},/*"e",68*/
{0x00,0x00,0x80,0x20,0x80,0x20,0xE0,0x3F,0x90,0x20,0x90,0x20,0x20,0x00,0x00,0x00},/*"f",69*/
{0x00,0x00,0x00,0x6B,0x80,0x94,0x80,0x94,0x80,0x94,0x80,0x93,0x80,0x60,0x00,0x00},/*"g",70*/
{0x10,0x20,0xF0,0x3F,0x00,0x21,0x80,0x00,0x80,0x00,0x80,0x20,0x00,0x3F,0x00,0x20},/*"h",71*/
{0x00,0x00,0x80,0x20,0x98,0x20,0x98,0x3F,0x00,0x20,0x00,0x20,0x00,0x00,0x00,0x00},/*"i",72*/
{0x00,0x00,0x00,0xC0,0x00,0x80,0x80,0x80,0x98,0x80,0x98,0x7F,0x00,0x00,0x00,0x00},/*"j",73*/
{0x10,0x20,0xF0,0x3F,0x00,0x24,0x00,0x06,0x80,0x29,0x80,0x30,0x80,0x20,0x00,0x00},/*"k",74*/
{0x00,0x00,0x10,0x20,0x10,0x20,0xF8,0x3F,0x00,0x20,0x00,0x20,0x00,0x00,0x00,0x00},/*"l",75*/
{0x80,0x20,0x80,0x3F,0x80,0x20,0x80,0x00,0x80,0x3F,0x80,0x20,0x80,0x00,0x00,0x3F},/*"m",76*/
{0x80,0x20,0x80,0x3F,0x00,0x21,0x80,0x00,0x80,0x00,0x80,0x20,0x00,0x3F,0x00,0x20},/*"n",77*/
{0x00,0x00,0x00,0x1F,0x80,0x20,0x80,0x20,0x80,0x20,0x80,0x20,0x00,0x1F,0x00,0x00},/*"o",78*/
{0x80,0x80,0x80,0xFF,0x00,0x91,0x80,0x20,0x80,0x20,0x00,0x11,0x00,0x0E,0x00,0x00},/*"p",79*/
{0x00,0x00,0x00,0x0E,0x00,0x11,0x80,0x20,0x80,0x20,0x00,0x91,0x80,0xFF,0x00,0x80},/*"q",80*/
{0x80,0x20,0x80,0x20,0x80,0x3F,0x00,0x21,0x80,0x20,0x80,0x00,0x80,0x01,0x00,0x00},/*"r",81*/
{0x00,0x00,0x00,0x33,0x80,0x24,0x80,0x24,0x80,0x24,0x80,0x24,0x80,0x19,0x00,0x00},/*"s",82*/
{0x00,0x00,0x80,0x00,0x80,0x00,0xE0,0x1F,0x80,0x20,0x80,0x20,0x00,0x10,0x00,0x00},/*"t",83*/
{0x80,0x00,0x80,0x1F,0x00,0x20,0x00,0x20,0x00,0x20,0x80,0x10,0x80,0x3F,0x00,0x20},/*"u",84*/
{0x80,0x00,0x80,0x03,0x80,0x0C,0x00,0x30,0x80,0x0C,0x80,0x03,0x80,0x00,0x00,0x00},/*"v",85*/
{0x80,0x01,0x80,0x0E,0x00,0x30,0x80,0x0C,0x80,0x07,0x00,0x38,0x80,0x06,0x80,0x01},/*"w",86*/
{0x00,0x00,0x80,0x20,0x80,0x31,0x80,0x0E,0x00,0x2E,0x80,0x31,0x80,0x20,0x00,0x00},/*"x",87*/
{0x80,0x00,0x80,0x81,0x80,0x86,0x00,0x78,0x00,0x18,0x80,0x06,0x80,0x01,0x80,0x00},/*"y",88*/
{0x00,0x00,0x80,0x21,0x80,0x30,0x80,0x2C,0x80,0x22,0x80,0x21,0x80,0x30,0x00,0x00},/*"z",89*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFC,0x3E,0x02,0x40,0x02,0x40},/*"{",90*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00},/*"|",91*/
{0x02,0x40,0x02,0x40,0xFC,0x3E,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"}",92*/
{0x00,0x00,0x02,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x04,0x00,0x02,0x00,0x00,0x00},/*"~",93*/
};
/*********************
函数声明
*********************/
void Delay1ms(u16 n);
void I2C_Init();
void ADS1115_Write(u8 reg, u16 value);
u16 ADS1115_Read(u8 reg);
void LCD_WriteCmd(u8 cmd);
void LCD_Writevalue(u8 dat);
void LCD_Init();
void LCD_Clear();
void LCD_ShowStr(u8 x, u8 y, u8 *str);
void MeasureVos();
void MeasureIB();
void MeasureAol();
void MeasurePSRR();
void MeasureVoMax();
void DisplayResults();
void I2C_Ack(u8 ack);
u8 I2C_RecvByte(void);
void I2C_Start(void);
void I2C_Stop(void);
void I2C_SendByte(u8 dat);
void RelayControl(u8 port, u8 state); // 修改继电器控制函数
void CheckButtons(); // 新增按键检测函数
/*********************
主函数
*********************/
void main()
{
// 初始化部分
// 初始化时强制关闭所有继电器
P0 = 0x00;
P4 = 0x00;
// 新增端口初始化
P0M0 = 0xFF; // P0推挽输出(驱动K1-K8)
P0M1 = 0x00;
P5M0 = 0x00; // P5.4准双向(RST按键)
P5M1 = 0x00;
P4M0 = 0xFF; // P4推挽输出模式(驱动继电器)
P4M1 = 0x00;
P7M0 = 0x00; // P7.0准双向(按键输入)
P7M1 = 0x00;
I2C_Init(); // 初始化I2C
LCD_Init(); // 初始化LCD
LCD_Clear(); // 清屏
while(1)
{
CheckButtons(); // 新增按键检测
if(RST_Flag) { // 处理复位
LCD_Clear();
Vos = IB = Aol = PSRR = VoMax = 0;
RelayControl(RELAY_PORT0, 0x00);
RelayControl(RELAY_PORT4, 0x00);
RST_Flag = 0;
}
// 原按键S1检测修改为复合功能
if(P70 == 0)
{
Delay1ms(20);
if(P70 == 0)
{
// 根据运放类型执行测试
switch(OpampType) {
case OPAMP_SINGLE:
MeasureVos(); // 单运放测试
MeasureIB();
MeasureAol();
MeasurePSRR();
MeasureVoMax();
break;
case OPAMP_DUAL:
MeasureVos();
MeasureIB();
MeasureAol();
MeasurePSRR();
MeasureVoMax();// 双运放测试流程
break;
case OPAMP_QUAD:
MeasureVos();
MeasureIB();
MeasureAol();
MeasurePSRR();
MeasureVoMax();// 四运放测试流程(需补充)
break;
}
DisplayResults();
while(P70 == 0);
}
}
}
}
/*********************
新增按键检测函数
*********************/
static bit S2_Last = 1; // 移出函数外声明
static bit RST_Last = 1;
void CheckButtons()
{
// 检测运放类型切换按键(S2)
if(P71 == 0 && S2_Last) {
Delay1ms(50);
if(P71 == 0) {
if(++OpampType > 2)
OpampType = 0;
// 根据运放类型设置基础继电器
switch(OpampType) {
case OPAMP_SINGLE:
RelayControl(RELAY_PORT0, 0x01);
break;
case OPAMP_DUAL:
RelayControl(RELAY_PORT0, 0x03);
break;
case OPAMP_QUAD:
RelayControl(RELAY_PORT0, 0xFF);
break;
}
}
while(P71 == 0);
}
S2_Last = P71;
// 检测RST按键(P5.4)
if(P54 == 0 && RST_Last) {
Delay1ms(50);
if(P54 == 0) RST_Flag = 1;
while(P54 == 0);
}
RST_Last = P54;
}
/*********************
修改后的继电器控制函数
参数:port-0控制P0(K1-K8),1控制P4(K9-K16)
*********************/
void RelayControl(u8 port, u8 state) {
if(port == RELAY_PORT0) {
P0 = state; // 控制K1-K8
} else {
P4 = state; // 控制K9-K16
}
Delay1ms(200); // 增加200ms延时,防止抖动
}
/*********************
测量Vos(状态1)
*********************/
void MeasureVos()
{
// 状态1:闭合K9,K10,K14(P4.0, P4.1, P4.5)
RelayControl(RELAY_PORT4, 0x23); // 二进制00100011(低8位)
Delay1ms(1000); // 延时1秒
// 读取AIN1(Vo1)电压
ADS1115_Write(0x01, 0xD283); // 配置AIN1单端,4.096V量程
Delay1ms(10);
Vo1 = (float)ADS1115_Read(0x00) * 4.096 / 32768.0;
// 计算Vos
Vos = Vo1 / 501.0;
// 继电器复位(全部断开)
RelayControl(RELAY_PORT4, 0x00);
}
/*********************
测量IB(状态2)
*********************/
void MeasureIB()
{
// 第一次测量:闭合K9,K14(P4.0, P4.5)
RelayControl(RELAY_PORT4, 0x21); // 00100001
Delay1ms(500);
ADS1115_Write(0x01, 0xD283);
Delay1ms(10);
Vo1 = (float)ADS1115_Read(0x00) * 4.096 / 32768.0;
// 第二次测量:闭合K10,K14(P4.1, P4.5)
RelayControl(RELAY_PORT4, 0x22); // 00100010
Delay1ms(500);
ADS1115_Write(0x01, 0xD283);
Delay1ms(10);
Vo1_prime = (float)ADS1115_Read(0x00) * 4.096 / 32768.0;
// 计算IB
IB = (Vo1_prime - Vo1) / (2 * 50000.0 * 501.0); // 结果单位是安培
// 继电器复位
RelayControl(RELAY_PORT4, 0x00);
}
/*********************
状态3:测量开环增益Aol
*********************/
void MeasureAol()
{
float vo1_aol, vo1_aol_prime;
// 第一次测量:K9,10,13,14闭合(P4.0,1,4,5)
RelayControl(RELAY_PORT4, 0x33); // 00110011
Delay1ms(1000); // 稳定时间
ADS1115_Write(0x01, 0xD283); // 读取AIN1
vo1_aol = (float)ADS1115_Read(0x00) * 4.096 / 32768.0;
// 第二次测量:K9,10,13,14,15,16闭合(添加P4.6,7)
RelayControl(RELAY_PORT4, 0xF3); // 11110011
Delay1ms(1000);
ADS1115_Write(0x01, 0xD283);
vo1_aol_prime = (float)ADS1115_Read(0x00) * 4.096 / 32768.0;
// 计算Aol(避免除零错误)
if(fabs(vo1_aol_prime - vo1_aol) > 0.001) {
Aol = 501.0 * 12.0 / (vo1_aol_prime - vo1_aol);
}
else {
Aol = 0;
}
RelayControl(RELAY_PORT4, 0x00); // 断开所有
}
/*********************
状态4:测量电源抑制比PSRR
*********************/
void MeasurePSRR()
{
float vo1_psrr, vo1_psrr_prime;
// 第一次测量:K9,10,13,14闭合(同状态3首次)
RelayControl(RELAY_PORT4, 0x33);
Delay1ms(1000);
ADS1115_Write(0x01, 0xD283);
vo1_psrr = (float)ADS1115_Read(0x00) * 4.096 / 32768.0;
// 第二次测量:K9,10,11,12,13,14闭合(添加P4.2,3)
RelayControl(RELAY_PORT4, 0x3F); // 00111111
Delay1ms(1000);
ADS1115_Write(0x01, 0xD283);
vo1_psrr_prime = (float)ADS1115_Read(0x00) * 4.096 / 32768.0;
// 计算PSRR(12-5=7V变化量)
PSRR = (1.0/501.0) * (vo1_psrr - vo1_psrr_prime) / (2.0 * 7.0);
RelayControl(RELAY_PORT4, 0x00);
}
/*********************
状态5:测量VoMax
*********************/
void MeasureVoMax()
{
// 闭合K9,10,13,14,15,16(同状态3第二次)
RelayControl(RELAY_PORT4, 0xF3);
Delay1ms(1000);
// 读取AIN3(Vo2)
ADS1115_Write(0x01, 0xE283); // 配置AIN3单端
VoMax = (float)ADS1115_Read(0x00) * 4.096 / 32768.0;
RelayControl(RELAY_PORT4, 0x00);
}
/*********************
I2C初始化
*********************/
void I2C_Init() {
// STC8H的I2C配置(使用官方推荐配置)
I2CMSST = 0xFF; // 延长SCL高电平时间(进一步降速)
I2CCFG = 0xE0; // 使能I2C,时钟分频
I2CMSAUX = 0x00;
I2CMSCR = 0x00;// 主模式控制寄存器初始化
// 配置P1.0和P1.1为开漏模式
P1M0 &= ~0x03; // P1.0/P1.1开漏
P1M1 |= 0x03;
P1PU |= 0x03; // 启用P1.0和P1.1的内部弱上拉(关键修改!)
}
/*********************
ADS1115写寄存器
*********************/
void ADS1115_Write(u8 reg, u16 value)
{
I2C_Start();
I2C_SendByte(ADS1115_ADDR<<1); // 写操作
I2C_SendByte(reg);
I2C_SendByte(value >> 8); // 高字节
I2C_SendByte(value & 0xFF); // 低字节
I2C_Stop();
}
/*********************
ADS1115读寄存器
*********************/
u16 ADS1115_Read(u8 reg)
{
u16 result;
I2C_Start();
I2C_SendByte(ADS1115_ADDR<<1); // 写操作
I2C_SendByte(reg);
I2C_Start();
I2C_SendByte((ADS1115_ADDR<<1)|1); // 读操作
result = I2C_RecvByte() << 8;
I2C_Ack(1);
result |= I2C_RecvByte();
I2C_Ack(0);
I2C_Stop();
return result;
}
/*********************
LCD显示字符串函数
参数:x-列坐标(0-127), y-行坐标(0-7), str-字符串
*********************/
void LCD_ShowStr(u8 x, u8 y, u8 *str) {
u8 page = y / 8; // 计算页地址
u8 col = x % 64; // 列地址(每半屏64列)
// 选择左/右半屏
if(x < 64) {
LCD_CS1 = 0;
LCD_CS2 = 1;
} else {
LCD_CS1 = 1;
LCD_CS2 = 0;
col = x - 64; // 右半屏列地址
}
// 设置地址
LCD_WriteCmd(0xB8 | page); // 页地址
LCD_WriteCmd(0x40 | col); // 列地址
// 写入字符串数据
while(*str) {
LCD_Writevalue(*str++);
}
}
/*********************
LCD基础函数
*********************/
void LCD_WriteCmd(u8 cmd) {
LCD_DI = 0; // 命令模式
LCD_RW = 0; // 写操作
P2 = cmd; // 命令数据
LCD_E = 1;
Delay1ms(1); // 增加延时确保脉冲宽度
LCD_E = 0;
Delay1ms(1);
}
void LCD_Writevalue(u8 dat)
{
LCD_DI = 1; // 数据模式
LCD_RW = 0;
P2 = dat;
LCD_E = 1;
Delay1ms(1); // 增加延时确保脉冲宽度
LCD_E = 0;
Delay1ms(1);
}
void LCD_Init() {
LCD_RST = 0;
Delay1ms(100);
LCD_RST = 1;
LCD_CS1 = 1;
LCD_CS2 = 1;
// 初始化指令序列
LCD_WriteCmd(0x3F); // 显示开
LCD_WriteCmd(0xC0); // 起始行设为第0行
LCD_WriteCmd(0xB8 | 0); // 设置页地址为0(第一页)
LCD_WriteCmd(0x40 | 0); // 设置列地址为0
LCD_Clear(); // 清屏
}
void LCD_Clear()
{
u16 i;
LCD_CS1 = 0; LCD_CS2 = 1; // 清左半屏
for(i=0; i<512; i++) LCD_Writevalue(0x00);
LCD_CS1 = 1; LCD_CS2 = 0; // 清右半屏
for(i=0; i<512; i++) LCD_Writevalue(0x00);
LCD_CS1 = 1; LCD_CS2 = 1;
}
/*********************
显示测量结果
*********************/
void DisplayResults()
{
char buf[32];
const char *OpampTypeStr[] = {"Single"," Dual "," Quad "};
// 显示运放类型
sprintf(buf, "OP:%s", OpampTypeStr[OpampType]);
LCD_ShowStr(64, 6, buf);
// 第一列显示主要参数
// 统一显示格式模板:
// %[占位][宽度][.精度][单位]
// Vos显示为mV,保留3位小数
sprintf(buf, "Vos:%7.3fmV", Vos*1000);
LCD_ShowStr(0, 0, buf);
// IB显示为nA,保留2位小数
sprintf(buf, "IB:%8.2fnA", IB*1e9);
LCD_ShowStr(0, 1, buf);
// Aol显示为dB,保留1位小数
sprintf(buf, "Aol:%7.1fdB", 20*log10(fabs(Aol)));
LCD_ShowStr(0, 2, buf);
// PSRR显示为dB,保留1位小数
sprintf(buf, "PSRR:%6.1fdB", 20*log10(fabs(PSRR)));
LCD_ShowStr(0, 3, buf);
// VoMax显示为V,保留3位小数
sprintf(buf, "VoMax:%6.3fV", VoMax);
LCD_ShowStr(0, 4, buf);
// 第二列显示原始电压(右半屏)
// 调整X坐标为64(假设12864屏分左右半屏)
sprintf(buf, "Vo1:%6.3fV", Vo1);
LCD_ShowStr(64, 0, buf);
sprintf(buf, "Vo1':%5.3fV", Vo1_prime);
LCD_ShowStr(64, 1, buf);
}
/*********************
通用延时函数
*********************/
void Delay1ms(u16 n)
{
u16 i,j;
for(i=n; i>0; i--)
for(j=830; j>0; j--);
}
|