电压电流显示波动严重不准 请教ADC采集程
- /***************************************************
- * STC8H3K64S2驱动128x32 OLED电压电流表程序
- * 功能:0-500V电压 0-999mA电压电流表
- * 作者:HSGhxq
- * 版本:V1.0
- * 日期:2026-01-10
- ***************************************************/
- #include "STC8H.H"
- #include <intrins.h>
- // OLED定义
- #define OLED_ADDRESS 0x78 // OLED I2C地址
- #define OLED_CMD 0x00 // 写命令
- #define OLED_DATA 0x40 // 写数据
- // ADC定义
- #define ADC_CH_VOLTAGE 0 // 电压测量通道 (P1.0)
- #define ADC_CH_CURRENT 1 // 电流测量通道 (P1.1)
- // 引脚定义
- sbit SCL = P3^2; // OLED时钟
- sbit SDA = P3^3; // OLED数据
- // 电压电流参数
- unsigned int voltage_adc = 0; // 电压ADC值
- unsigned int current_adc = 0; // 电流ADC值
- float voltage_value = 0; // 电压值
- float current_value = 0; // 电流值
- bit display_flag = 0; // 显示标志,0=开机界面,1=主界面
- // 全局变量
- unsigned int timer_count = 0;
- // 函数声明
- void Delay_us(unsigned int n);
- void Delay_ms(unsigned int n);
- void I2C_Start(void);
- void I2C_Stop(void);
- void I2C_Ack(void);
- void I2C_NoAck(void);
- bit I2C_WaitAck(void);
- void I2C_SendByte(unsigned char dat);
- void OLED_WriteCmd(unsigned char cmd);
- void OLED_WriteData(unsigned char dat);
- void OLED_Init(void);
- void OLED_SetPos(unsigned char x, unsigned char y);
- void OLED_Clear(void);
- void OLED_ShowChar_8x8(unsigned char x, unsigned char y, unsigned char ch);
- void OLED_ShowString_8x8(unsigned char x, unsigned char y, unsigned char *str);
- void Show_Boot_Screen(void);
- void Show_Main_Screen(void);
- void ADC_Init(void);
- unsigned int Get_ADC_Result(unsigned char channel);
- void Measure_Voltage_Current(void);
- void Timer0_Init(void);
- code unsigned char ASCII_8x8[][8] =
- {
- // 0-9
- {0x3E,0x7F,0x71,0x59,0x4D,0x7F,0x3E,0x00}, // 0
- {0x40,0x42,0x7F,0x7F,0x40,0x40,0x00,0x00}, // 1
- {0x62,0x73,0x59,0x49,0x6F,0x66,0x00,0x00}, // 2
- {0x22,0x63,0x49,0x49,0x7F,0x36,0x00,0x00}, // 3
- {0x18,0x1C,0x16,0x53,0x7F,0x7F,0x50,0x00}, // 4
- {0x27,0x67,0x45,0x45,0x7D,0x39,0x00,0x00}, // 5
- {0x3C,0x7E,0x4B,0x49,0x79,0x30,0x00,0x00}, // 6
- {0x03,0x03,0x71,0x79,0x0F,0x07,0x00,0x00}, // 7
- {0x36,0x7F,0x49,0x49,0x7F,0x36,0x00,0x00}, // 8
- {0x06,0x4F,0x49,0x69,0x3F,0x1E,0x00,0x00}, // 9
- // 字母A-Z
- {0x7C,0x7E,0x0B,0x09,0x7F,0x7F,0x00,0x00}, // A
- {0x7F,0x7F,0x49,0x49,0x7F,0x36,0x00,0x00}, // B
- {0x3E,0x7F,0x41,0x41,0x63,0x22,0x00,0x00}, // C
- {0x7F,0x7F,0x41,0x41,0x7F,0x3E,0x00,0x00}, // D
- {0x7F,0x7F,0x49,0x49,0x41,0x41,0x00,0x00}, // E
- {0x7F,0x7F,0x09,0x09,0x01,0x01,0x00,0x00}, // F
- {0x3E,0x7F,0x41,0x49,0x7B,0x3A,0x00,0x00}, // G
- {0x7F,0x7F,0x08,0x08,0x7F,0x7F,0x00,0x00}, // H
- {0x00,0x41,0x7F,0x7F,0x41,0x00,0x00,0x00}, // I
- {0x20,0x60,0x40,0x40,0x7F,0x3F,0x00,0x00}, // J
- {0x7F,0x7F,0x1C,0x36,0x63,0x41,0x00,0x00}, // K
- {0x7F,0x7F,0x40,0x40,0x40,0x40,0x00,0x00}, // L
- {0x7F,0x7F,0x06,0x0C,0x06,0x7F,0x7F,0x00}, // M
- {0x7F,0x7F,0x0E,0x1C,0x7F,0x7F,0x00,0x00}, // N
- {0x3E,0x7F,0x41,0x41,0x7F,0x3E,0x00,0x00}, // O
- {0x7F,0x7F,0x09,0x09,0x0F,0x06,0x00,0x00}, // P
- {0x3E,0x7F,0x41,0x51,0x7F,0x3E,0x00,0x00}, // Q
- {0x7F,0x7F,0x09,0x19,0x7F,0x66,0x00,0x00}, // R
- {0x26,0x6F,0x49,0x49,0x7B,0x32,0x00,0x00}, // S
- {0x01,0x01,0x7F,0x7F,0x01,0x01,0x00,0x00}, // T
- {0x3F,0x7F,0x40,0x40,0x7F,0x3F,0x00,0x00}, // U
- {0x1F,0x3F,0x60,0x60,0x3F,0x1F,0x00,0x00}, // V
- {0x7F,0x7F,0x30,0x18,0x30,0x7F,0x7F,0x00}, // W
- {0x63,0x77,0x1C,0x1C,0x77,0x63,0x00,0x00}, // X
- {0x07,0x0F,0x78,0x78,0x0F,0x07,0x00,0x00}, // Y
- {0x61,0x71,0x59,0x4D,0x47,0x43,0x00,0x00}, // Z
- // 小写字母
- {0x20,0x74,0x54,0x54,0x7C,0x78,0x00,0x00}, // a
- {0x7F,0x7F,0x44,0x44,0x7C,0x38,0x00,0x00}, // b
- {0x38,0x7C,0x44,0x44,0x44,0x00,0x00,0x00}, // c
- {0x38,0x7C,0x44,0x44,0x7F,0x7F,0x00,0x00}, // d
- {0x38,0x7C,0x54,0x54,0x5C,0x18,0x00,0x00}, // e
- {0x04,0x7E,0x7F,0x05,0x05,0x00,0x00,0x00}, // f
- {0x98,0xBC,0xA4,0xA4,0xFC,0x7C,0x00,0x00}, // g
- {0x7F,0x7F,0x04,0x04,0x7C,0x78,0x00,0x00}, // h
- {0x00,0x48,0x7D,0x7D,0x40,0x00,0x00,0x00}, // i
- {0x40,0xC0,0x80,0x80,0xFD,0x7D,0x00,0x00}, // j
- {0x7F,0x7F,0x10,0x38,0x6C,0x44,0x00,0x00}, // k
- {0x00,0x41,0x7F,0x7F,0x40,0x00,0x00,0x00}, // l
- {0x7C,0x7C,0x0C,0x18,0x0C,0x7C,0x78,0x00}, // m
- {0x7C,0x7C,0x04,0x04,0x7C,0x78,0x00,0x00}, // n
- {0x38,0x7C,0x44,0x44,0x7C,0x38,0x00,0x00}, // o
- {0xFC,0xFC,0x24,0x24,0x3C,0x18,0x00,0x00}, // p
- {0x18,0x3C,0x24,0x24,0xFC,0xFC,0x00,0x00}, // q
- {0x7C,0x7C,0x04,0x04,0x0C,0x08,0x00,0x00}, // r
- {0x48,0x5C,0x54,0x54,0x74,0x24,0x00,0x00}, // s
- {0x04,0x3F,0x7F,0x44,0x44,0x00,0x00,0x00}, // t
- {0x3C,0x7C,0x40,0x40,0x7C,0x7C,0x00,0x00}, // u
- {0x1C,0x3C,0x60,0x60,0x3C,0x1C,0x00,0x00}, // v
- {0x3C,0x7C,0x60,0x38,0x60,0x7C,0x3C,0x00}, // w
- {0x44,0x6C,0x38,0x38,0x6C,0x44,0x00,0x00}, // x
- {0x9C,0xBC,0xA0,0xA0,0xFC,0x7C,0x00,0x00}, // y
- {0x4C,0x64,0x74,0x5C,0x4C,0x44,0x00,0x00}, // z
- {0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00}, // -
- {0x00,0x00,0x00,0x14,0x00,0x00,0x00,0x00}, // :
- {0x00,0x36,0x36,0x00,0x00,0x00,0x00,0x00}, // :
- {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 空格
- {0x04,0x04,0x04,0x04,0x04,0x04,0x00,0x00}, // _
- {0x00,0x00,0x03,0x03,0x00,0x00,0x00,0x00}, // "
- {0x2A,0x2A,0x1C,0x1C,0x2A,0x2A,0x00,0x00}, // *
- {0x7F,0x7F,0x49,0x49,0x41,0x41,0x00,0x00}, // E
- {0x08,0x08,0x3E,0x08,0x08,0x00,0x00,0x00}, // +
- {0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00}, // .
- {0x20,0x10,0x08,0x04,0x02,0x01,0x00,0x00}, // /
- {0x7F,0x41,0x41,0x41,0x41,0x7F,0x00,0x00}, //
- {0x00,0x08,0x3E,0x08,0x00,0x00,0x00,0x00}, //
- {0x00,0x08,0x1C,0x2A,0x08,0x08,0x00,0x00}, //
- {0x7E,0x42,0x42,0x42,0x42,0x7E,0x00,0x00}, // 0
- {0x00,0x44,0x7E,0x7F,0x40,0x00,0x00,0x00}, // 1
- {0x7E,0x7F,0x49,0x49,0x49,0x49,0x00,0x00}, // A
- {0x3F,0x7F,0x44,0x44,0x44,0x7C,0x38,0x00}, // d
- {0x3E,0x7F,0x41,0x41,0x41,0x63,0x22,0x00}, // C
- };
- // 开机界面文字
- code unsigned char BootText[] = "HSGhxq VER V1.0";
- /******************************************************/
- void Delay_us(unsigned int n) {
- while(n--) {
- _nop_();
- _nop_();
- _nop_();
- _nop_();
- }
- }
- void Delay_ms(unsigned int n) {
- unsigned int i, j;
- for(i = 0; i < n; i++)
- for(j = 0; j < 1000; j++);
- }
- /***************I2C************************************/
- void I2C_Start(void) {
- SDA = 1;
- SCL = 1;
- Delay_us(5);
- SDA = 0;
- Delay_us(5);
- SCL = 0;
- }
- void I2C_Stop(void) {
- SDA = 0;
- SCL = 1;
- Delay_us(5);
- SDA = 1;
- Delay_us(5);
- }
- void I2C_Ack(void) {
- SDA = 0;
- SCL = 1;
- Delay_us(5);
- SCL = 0;
- SDA = 1;
- }
- void I2C_NoAck(void) {
- SDA = 1;
- SCL = 1;
- Delay_us(5);
- SCL = 0;
- }
- bit I2C_WaitAck(void) {
- SDA = 1;
- SCL = 1;
- Delay_us(5);
- CY = SDA;
- SCL = 0;
- return CY;
- }
- void I2C_SendByte(unsigned char dat) {
- unsigned char i;
- for(i = 0; i < 8; i++) {
- SDA = (dat & 0x80) ? 1 : 0;
- dat <<= 1;
- SCL = 1;
- Delay_us(5);
- SCL = 0;
- }
- I2C_WaitAck();
- }
- /***************************************************
- * OLED函数
- ***************************************************/
- void OLED_WriteCmd(unsigned char cmd) {
- I2C_Start();
- I2C_SendByte(OLED_ADDRESS);
- I2C_SendByte(OLED_CMD);
- I2C_SendByte(cmd);
- I2C_Stop();
- }
- void OLED_WriteData(unsigned char dat) {
- I2C_Start();
- I2C_SendByte(OLED_ADDRESS);
- I2C_SendByte(OLED_DATA);
- I2C_SendByte(dat);
- I2C_Stop();
- }
- void OLED_Init(void) {
- Delay_ms(100);
- OLED_WriteCmd(0xAE); // 关闭显示
- OLED_WriteCmd(0xD5); // 设置时钟分频因子
- OLED_WriteCmd(0x80);
- OLED_WriteCmd(0xA8); // 设置驱动路数
- OLED_WriteCmd(0x1F); // 32-1
- OLED_WriteCmd(0xD3); // 设置显示偏移
- OLED_WriteCmd(0x00);
- OLED_WriteCmd(0x40); // 设置起始行
- OLED_WriteCmd(0xA1); // 设置段重定向
- OLED_WriteCmd(0xC8); // 设置COM扫描方向
- OLED_WriteCmd(0xDA); // 设置COM硬件引脚配置
- OLED_WriteCmd(0x02);
- OLED_WriteCmd(0x81); // 设置对比度
- OLED_WriteCmd(0x7F);
- OLED_WriteCmd(0xA4); // 设置全部像素点ON
- OLED_WriteCmd(0xA6); // 设置正常显示
- OLED_WriteCmd(0xD9); // 设置预充电周期
- OLED_WriteCmd(0xF1);
- OLED_WriteCmd(0xDB); // 设置VCOMH电压倍率
- OLED_WriteCmd(0x30);
- OLED_WriteCmd(0x8D); // 设置充电泵
- OLED_WriteCmd(0x14);
- OLED_WriteCmd(0xAF); // 开启显示
- OLED_Clear();
- }
- void OLED_SetPos(unsigned char x, unsigned char y) {
- OLED_WriteCmd(0xB0 + y);
- OLED_WriteCmd(((x & 0xF0) >> 4) | 0x10);
- OLED_WriteCmd(x & 0x0F);
- }
- void OLED_Clear(void) {
- unsigned char i, j;
- for(i = 0; i < 4; i++) {
- OLED_SetPos(0, i);
- for(j = 0; j < 128; j++) {
- OLED_WriteData(0x00);
- }
- }
- }
- /***************************************************
- * 显示函数
- ***************************************************/
- void OLED_ShowChar_8x8(unsigned char x, unsigned char y, unsigned char ch)
- {
- unsigned char i, c;
- if(ch >= '0' && ch <= '9') {
- c = ch - '0';
- } else if(ch >= 'A' && ch <= 'Z') {
- c = ch - 'A' + 10;
- } else if(ch >= 'a' && ch <= 'z') {
- c = ch - 'a' + 36;
- } else {
- switch(ch) {
- case '-': c = 62; break;
- case ':': c = 63; break;
- case ' ': c = 64; break;
- case '_': c = 65; break;
- case '.': c = 70; break;
- case '@': c = 71; break;
- case 'm': c = 40; break;
- case 'V': c = 21; break;
- case 'v': c = 21; break;
- default : c = 64; break;
- }
- }
- OLED_SetPos(x, y);
- for(i = 0; i < 8; i++) {
- OLED_WriteData(ASCII_8x8[c][i]);
- }
- }
- void OLED_ShowString_8x8(unsigned char x, unsigned char y, unsigned char *str) {
- while(*str) {
- OLED_ShowChar_8x8(x, y, *str);
- x += 8;
- str++;
- }
- }
- void Show_Boot_Screen(void) {
- OLED_Clear();
- OLED_ShowChar_8x8(0, 1, 'H');
- OLED_ShowChar_8x8(8, 1, 'S');
- OLED_ShowChar_8x8(16, 1, 'G');
- OLED_ShowChar_8x8(24, 1, 'h');
- OLED_ShowChar_8x8(32, 1, 'x');
- OLED_ShowChar_8x8(40, 1, 'q');
- OLED_ShowChar_8x8(54, 1, 'V');
- OLED_ShowChar_8x8(62, 1, 'E');
- OLED_ShowChar_8x8(70, 1, 'R');
- OLED_ShowChar_8x8(78, 1, ' ');
- OLED_ShowChar_8x8(86, 1, 'V');
- OLED_ShowChar_8x8(94, 1, '1');
- OLED_ShowChar_8x8(102,1, ',');
- OLED_ShowChar_8x8(110,1, '0');
-
- OLED_ShowChar_8x8(20, 3, '2');
- OLED_ShowChar_8x8(28, 3, '0');
- OLED_ShowChar_8x8(36, 3, '2');
- OLED_ShowChar_8x8(44, 3, '6');
- OLED_ShowChar_8x8(52, 3, '-');
- OLED_ShowChar_8x8(60, 3, '0');
- OLED_ShowChar_8x8(68, 3, '1');
- OLED_ShowChar_8x8(76, 3, '-');
- OLED_ShowChar_8x8(84, 3, '1');
- OLED_ShowChar_8x8(92, 3, '2');
- Delay_ms(3000); // 显示3秒
- OLED_Clear();
- display_flag = 1;
- }
- void Show_Main_Screen(void) {
- unsigned int volt_int, curr_int;
- unsigned char volt_100, volt_10, volt_1, volt_dec;
- unsigned char curr_100, curr_10, curr_1;
- // 提取电压各位数字
- volt_int = (unsigned int)(voltage_value * 10);
- volt_100 = volt_int / 1000 % 10;
- volt_10 = volt_int / 100 % 10;
- volt_1 = volt_int / 10 % 10;
- volt_dec = volt_int % 10;
- // 提取电流各位数字
- curr_int = (unsigned int)current_value;
- curr_100 = curr_int / 100 % 10;
- curr_10 = curr_int / 10 % 10;
- curr_1 = curr_int % 10;
-
- OLED_ShowChar_8x8(96, 1, 'H');
- OLED_ShowChar_8x8(106, 1, 'S');
- OLED_ShowChar_8x8(116, 1, 'G');
- OLED_ShowChar_8x8(90, 3, '2');
- OLED_ShowChar_8x8(100, 3, '0');
- OLED_ShowChar_8x8(110, 3, '2');
- OLED_ShowChar_8x8(120, 3, '6');
-
- OLED_ShowChar_8x8(0, 1, 'V');
- OLED_ShowChar_8x8(8, 1, 'O');
- OLED_ShowChar_8x8(16, 1, 'L');
- OLED_ShowChar_8x8(24, 1, ',');
- // 显示电压值
- OLED_ShowChar_8x8(32, 1, volt_100 + '0');
- OLED_ShowChar_8x8(40, 1, volt_10 + '0');
- OLED_ShowChar_8x8(48, 1, volt_1 + '0');
- //OLED_ShowChar_8x8(56, 1, '.');
- // OLED_ShowChar_8x8(64, 1, volt_dec + '0');
- OLED_ShowChar_8x8(56, 1, 'V');
- // 显示电流标题
- OLED_ShowChar_8x8(0, 3, 'C');
- OLED_ShowChar_8x8(8, 3, 'U');
- OLED_ShowChar_8x8(16, 3, 'R');
- OLED_ShowChar_8x8(24, 3, ',');
-
- // 显示电流值
- OLED_ShowChar_8x8(32, 3, curr_100 + '0');
- OLED_ShowChar_8x8(40, 3, curr_10 + '0');
- OLED_ShowChar_8x8(48, 3, curr_1 + '0');
- OLED_ShowChar_8x8(56, 3, 'm');
- OLED_ShowChar_8x8(64, 3, 'a');
- }
- /*********************ADC******************************/
- void ADC_Init(void) {
- P1M0 = 0x00;
- P1M1 = 0x00;
- ADCCFG = 0x0F;
- ADC_CONTR = 0x80;
- Delay_ms(1);
- }
- unsigned int Get_ADC_Result(unsigned char channel) {
- unsigned int result = 0;
- unsigned char i;
- ADC_CONTR = 0x80 | channel;
- Delay_us(10);
- for(i = 0; i < 4; i++) {
- ADC_CONTR |= 0x40;
- _nop_();
- _nop_();
- while(!(ADC_CONTR & 0x20));
- ADC_CONTR &= ~0x20;
- result += (ADC_RES << 8) | ADC_RESL;
- }
- return result >> 2;
- }
- void Measure_Voltage_Current(void) {
- unsigned int adc_sum;
- unsigned char i;
- // 多次采样平均
- adc_sum = 0;
- for(i = 0; i < 10; i++) {
- adc_sum += Get_ADC_Result(ADC_CH_VOLTAGE);
- Delay_ms(1);
- }
- voltage_adc = adc_sum / 10;
- // 读取电流ADC值,多次采样平均
- adc_sum = 0;
- for(i = 0; i < 10; i++) {
- adc_sum += Get_ADC_Result(ADC_CH_CURRENT);
- Delay_ms(1);
- }
- current_adc = adc_sum / 10;
- voltage_value = (voltage_adc * 5.0 * 50.0) / 4096.0;
- current_value = (current_adc * 5.0 * 100.0) / 4096.0;
- // 限制范围
- if(voltage_value > 500.0) voltage_value = 500.0;
- if(voltage_value < 0.0) voltage_value = 0.0;
- if(current_value > 999.0) current_value = 999.0;
- if(current_value < 0.0) current_value = 0.0;
- }
- /**********************定时器0初始化**************************/
- void Timer0_Init(void) {
- AUXR |= 0x80; // 定时器0为1T模式
- TMOD &= 0xF0; // 设置定时器0为16位自动重装
- TL0 = 0x66; // 设置定时初值
- TH0 = 0xFC; // 设置定时初值
- TF0 = 0; // 清除TF0标志
- TR0 = 1; // 定时器0开始计时
- ET0 = 1; // 允许定时器0中断
- EA = 1; // 打开总中断
- }
- /********************定时器0中断服务函数***********************/
- void Timer0_ISR(void) interrupt 1 {
- timer_count++;
- if(timer_count >= 500) { // 500ms
- timer_count = 0;
- Measure_Voltage_Current(); // 每500ms更新一次测量值
- }
- }
- void main(void)
- {
- // 初始化IO口
- P3M0 = 0x0C; // P3.2, P3.3推挽输出
- P3M1 = 0x00;
- ADC_Init();
- OLED_Init();
- Timer0_Init();
- Show_Boot_Screen(); // 上电显示版本号
- while(1) {
- if(display_flag)
- {
- Show_Main_Screen();
- }
- Delay_ms(100);
- }
- }
复制代码
|