找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2|回复: 0
收起左侧

水位控制程序不能编译上面原因?

[复制链接]
ID:72649 发表于 2026-4-25 07:47 | 显示全部楼层 |阅读模式
/*
   STC8G1K08水位控制系统
   时钟频率: 11.0592MHz
   编译环境: Keil C51
*/

#include "STC8G.H"
#include <intrins.h>
#include <stdio.h>

// 引脚定义
sbit ON_KEY  = P1^5;     // P1.5 开机按键
sbit OFF_KEY = P1^6;     // P1.6 停止按键
sbit RST_KEY = P1^7;     // P1.7 复位按键

sbit H1_out      = P3^2;  // 输出1
sbit H2_out      = P3^3;  // 输出2
sbit H3_out      = P3^4;  // 输出3
sbit PUMP_out    = P3^5;  // 水泵输出
sbit ALARM_out   = P3^6;  // 报警输出
sbit LED_jiare   = P3^7;  // 加热LED
sbit LED_queshui = P1^3;  // 缺水LED
sbit LED_jiashui = P1^4;  // 加水LED
sbit LED_stop    = P5^4;  // 停止LED
sbit LED_yunxin  = P5^5;  // 运行LED

// 系统状态
bit system_running = 0;     // 系统运行标志
bit adc_running = 0;        // ADC采集标志
bit pump_running = 0;       // 水泵运行标志
bit alarm_state = 0;         // 报警状态
bit level_state[3] = {0};   // 水位状态: 0=无水位, 1=有水位

unsigned int adc_value[3];  // ADC采样值
unsigned int adc_filter[3]; // ADC滤波后值
unsigned char adc_count = 0;// ADC采样计数
bit send_serial = 0;        // 串口发送标志
unsigned int adc_threshold = 1000;  // 水位阈值

//int threshold_str;                    //添加

// 函数声明
void delay_ms(unsigned int ms);
void GPIO_Init(void);
void Timer0_Init(void);
void Timer1_Init(void);
void ADC_Init(void);
void UART1_Init(void);
void UART1_SendByte(unsigned char dat);
void UART1_SendString(char *str);
unsigned int ADC_Read(unsigned char channel);
void ADC_Start(void);
void System_Control(void);
void Key_Scan(void);
void Output_Control(void);
void UART1_SendADCData(void);
void System_Reset(void);
void All_Output_Low(void);

// 延时函数
void delay_ms(unsigned int ms) {
    unsigned int i, j;
    for(i = 0; i < ms; i++)
        for(j = 0; j < 114; j++);
}

// 初始化所有输出为低电平
void All_Output_Low(void) {
    H1_out = 0;
    H2_out = 0;
    H3_out = 0;
    PUMP_out = 0;
    ALARM_out = 0;
    LED_jiare = 0;
    LED_queshui = 0;
    LED_jiashui = 0;
    LED_yunxin = 0;
}

// GPIO初始化
void GPIO_Init(void) {
    // 按键引脚设为高阻输入
    P1M0 &= ~0xE0;  // P1.5, P1.6, P1.7
    P1M1 |= 0xE0;
   
    // LED引脚设为推挽输出
    P1M0 |= 0x18;   // P1.3, P1.4
    P1M1 &= ~0x18;
   
    P3M0 |= 0xFC;   // P3.2-P3.7
    P3M1 &= ~0xFC;
   
    P5M0 |= 0x30;   // P5.4, P5.5
    P5M1 &= ~0x30;
   
    // ADC引脚设为高阻输入
    P1M0 &= ~0x07;  // P1.0, P1.1, P1.2 (ADC0~ADC2)
    P1M1 |= 0x07;
   
    // 上电初始状态
    LED_stop = 1;      // 停止LED亮
    All_Output_Low();  // 其他输出全低
   
    // 内部上拉
    P1 |= 0xE0;  // 按键上拉
}

// 系统复位
void System_Reset(void) {
    system_running = 0;
    adc_running = 0;
    pump_running = 0;
    alarm_state = 0;
   
    // 重置水位状态
    level_state[0] = 0;
    level_state[1] = 0;
    level_state[2] = 0;
   
    // 复位ADC值
    adc_value[0] = 0;
    adc_value[1] = 0;
    adc_value[2] = 0;
    adc_filter[0] = 0;
    adc_filter[1] = 0;
    adc_filter[2] = 0;
   
    // 输出控制
    LED_stop = 1;
    All_Output_Low();
   
    // 发送复位信息
    UART1_SendString("System Reset\r\n");
}

// 定时器0初始化(用于按键扫描)
void Timer0_Init(void) {
    AUXR &= 0x7F;      // 定时器时钟12T模式
    TMOD &= 0xF0;      // 设置定时器模式
    TMOD |= 0x01;      // 定时器0模式1
    TL0 = 0x00;        // 设置定时初值
    TH0 = 0xDC;        // 11.0592MHz, 10ms中断
    TR0 = 1;           // 定时器0开始计时
    ET0 = 1;           // 使能定时器0中断
    EA = 1;            // 开总中断
}

// 定时器1初始化(用于系统控制)
void Timer1_Init(void) {
    AUXR &= 0xBF;      // 定时器时钟12T模式
    TMOD &= 0x0F;      // 设置定时器模式
    TMOD |= 0x10;      // 定时器1模式1
    TL1 = 0x00;        // 设置定时初值
    TH1 = 0xDC;        // 11.0592MHz, 10ms
    TR1 = 1;           // 定时器1开始计时
    ET1 = 1;           // 使能定时器1中断
}

// ADC初始化
void ADC_Init(void) {
    ADCCFG = 0x2F;     // 设置ADC时钟为系统时钟/16,右对齐
    ADC_CONTR = 0x80;  // 打开ADC电源
    delay_ms(1);       // 延时等待ADC稳定
}

// 串口1初始化
void UART1_Init(void) {
    // 使用定时器2作为波特率发生器
    AUXR &= 0xFB;      // 定时器2时钟为Fosc/12, 即12T
    T2L = 0xE0;        // 设定定时初值
    T2H = 0xFE;        // 11.0592MHz, 9600波特率
    AUXR |= 0x10;      // 定时器2开始计时
   
    S1CON &= ~0x40;    // 串口1选择定时器2为波特率发生器
    S1CON |= 0x40;     // 允许串口1接收
    P_SW1 &= 0x3F;     // 串口1切换到P3.0/P3.1
   
    // 设置P3.0和P3.1为推挽输出
    P3M0 |= 0x03;
    P3M1 &= ~0x03;
}

// 串口1发送一个字节
void UART1_SendByte(unsigned char dat) {
    S1BUF = dat;
    while((S1CON & 0x02) == 0);  // 等待发送完成
    S1CON &= ~0x02;             // 清除发送完成标志
}

// 串口1发送字符串
void UART1_SendString(char *str) {
    while(*str != '\0') {
        UART1_SendByte(*str++);
    }
}

// ADC采集
unsigned int ADC_Read(unsigned char channel) {
    ADC_CONTR &= 0xF8;           // 清除通道选择
    ADC_CONTR |= (channel & 0x07); // 选择ADC通道
    ADC_CONTR |= 0x40;           // 启动ADC转换
   
    _nop_(); _nop_(); _nop_(); _nop_(); // 等待转换完成
   
    while(!(ADC_CONTR & 0x20));  // 等待转换完成
    ADC_CONTR &= ~0x20;          // 清除转换完成标志
   
    return (ADC_RES << 8) | ADC_RESL;  // 返回12位ADC值
}

// 启动ADC采集
void ADC_Start(void) {
    static unsigned char adc_channel = 0;
    unsigned int adc_val;
   
    if(!adc_running) return;
   
    // 采集当前通道
    adc_val = ADC_Read(adc_channel);
   
    // 一阶低通滤波
    adc_filter[adc_channel] = (adc_filter[adc_channel] * 7 + adc_val) / 8;
    adc_value[adc_channel] = adc_filter[adc_channel];
   
    // 检测水位
    if(adc_value[adc_channel] > adc_threshold) {
        level_state[adc_channel] = 1;  // 有水位
    } else {
        level_state[adc_channel] = 0;  // 无水
    }
   
    adc_channel++;
    if(adc_channel >= 3) {
        adc_channel = 0;
        adc_count++;
        
        if(adc_count >= 5) {  // 采集5轮后发送数据
            adc_count = 0;
            send_serial = 1;   // 设置发送标志
        }
    }
}

// 按键扫描
void Key_Scan(void) {
    static bit on_key_pressed = 0;
    static bit off_key_pressed = 0;
    static bit rst_key_pressed = 0;
    static unsigned int on_key_time = 0;
    static unsigned int off_key_time = 0;
    static unsigned int rst_key_time = 0;
   
    // 开机按键检测
    if(!ON_KEY) {
        if(!on_key_pressed) {
            on_key_pressed = 1;
            on_key_time = 0;
        } else {
            on_key_time++;
            if(on_key_time >= 5) {  // 50ms去抖
                if(on_key_time == 5) {  // 首次按下
                    system_running = 1;   // 系统启动
                    adc_running = 1;      // 启动ADC采集
                    LED_stop = 0;         // 关闭停止LED
                    LED_yunxin = 1;       // 打开运行LED
                    
                    // 初始状态:无水位
                    ALARM_out = 1;        // 报警
                    LED_queshui = 1;      // 缺水指示灯
                    UART1_SendString("System Started\r\n");
                }
            }
        }
    } else {
        on_key_pressed = 0;
    }
   
    // 停止按键检测
    if(!OFF_KEY) {
        if(!off_key_pressed) {
            off_key_pressed = 1;
            off_key_time = 0;
        } else {
            off_key_time++;
            if(off_key_time >= 5) {  // 50ms去抖
                if(off_key_time == 5) {  // 首次按下
                    LED_stop = 1;         // 停止LED亮
                    All_Output_Low();     // 其他输出全低
                    UART1_SendString("System Stopped\r\n");
                }
            }
        }
    } else {
        off_key_pressed = 0;
    }
   
    // 复位按键检测
    if(!RST_KEY) {
        if(!rst_key_pressed) {
            rst_key_pressed = 1;
            rst_key_time = 0;
        } else {
            rst_key_time++;
            if(rst_key_time >= 5) {  // 50ms去抖
                if(rst_key_time == 5) {  // 首次按下
                    System_Reset();  // 系统复位
                }
            }
        }
    } else {
        rst_key_pressed = 0;
    }
}

// 输出控制逻辑
void Output_Control(void) {
    if(!system_running) return;
   
    // 检查所有水位状态
    if(level_state[0] == 0 && level_state[1] == 0 && level_state[2] == 0) {
        // 情况2:所有ADC都没有检测到水位
        H1_out = 0;
        H2_out = 0;
        H3_out = 0;
        PUMP_out = 0;
        LED_jiare = 0;
        LED_queshui = 1;  // 缺水指示灯亮
        LED_jiashui = 0;
        ALARM_out = 1;    // 报警
    }
    else if(level_state[0] == 1 && level_state[1] == 0 && level_state[2] == 0) {
        // 情况3:只有ADC0检测到水位
        ALARM_out = 0;    // 关闭报警
        PUMP_out = 1;     // 开启水泵
        H1_out = 0;
        H2_out = 0;
        H3_out = 0;
        LED_jiare = 0;
        LED_queshui = 0;
        LED_jiashui = 1;  // 加水指示灯
    }
    else if(level_state[0] == 1 && level_state[1] == 1) {
        // 情况4:ADC0和ADC1检测到水位
        ALARM_out = 0;    // 关闭报警
        PUMP_out = 1;     // 开启水泵
        H1_out = 1;       // 输出高电平
        H2_out = 1;
        H3_out = 1;
        LED_jiare = 1;    // 加热指示灯
        LED_queshui = 0;
        LED_jiashui = 0;
    }
    else if(level_state[0] == 1 && level_state[1] == 1 && level_state[2] == 1) {
        // 情况5:所有ADC都检测到水位
        ALARM_out = 0;    // 关闭报警
        PUMP_out = 0;     // 关闭水泵
        H1_out = 1;       // 输出高电平
        H2_out = 1;
        H3_out = 1;
        LED_jiare = 1;    // 加热指示灯
        LED_queshui = 0;
        LED_jiashui = 0;
    }
    else {
        // 其他组合状态
        // 可以添加其他逻辑或保持当前状态
    }
}

// 串口发送ADC数据
void UART1_SendADCData(void) {
    char buffer[80];
   
    if(!send_serial) return;
   
    // 格式化发送数据
    sprintf(buffer, "ADC0:%04u(%s) ADC1:%04u(%s) ADC2:%04u(%s) | OUT:H1=%d H2=%d H3=%d PUMP=%d ALARM=%d\r\n",
            adc_value[0], level_state[0] ? "H" : "L",
            adc_value[1], level_state[1] ? "H" : "L",
            adc_value[2], level_state[2] ? "H" : "L",
            H1_out, H2_out, H3_out, PUMP_out, ALARM_out);
    UART1_SendString(buffer);
   
    send_serial = 0;  // 清除发送标志
}

// 定时器0中断服务函数(按键扫描)
void Timer0_ISR() interrupt 1 {
    TL0 = 0x00;  // 重装定时器初值
    TH0 = 0xDC;
   
    Key_Scan();  // 扫描按键
}

// 定时器1中断服务函数(主控制)
void Timer1_ISR() interrupt 3 {
    static unsigned char timer_count = 0;
   
    TL1 = 0x00;  // 重装定时器初值
    TH1 = 0xDC;
   
    timer_count++;
   
    // 20ms任务
    if(timer_count % 2 == 0) {
        if(system_running) {
            ADC_Start();       // 启动ADC采集
        }
    }
   
    // 50ms任务
    if(timer_count % 5 == 0) {
        if(system_running) {
            Output_Control();  // 输出控制
        }
    }
   
    // 100ms任务
    if(timer_count % 10 == 0) {
        UART1_SendADCData();  // 串口发送数据
    }
   
    // 500ms任务
    if(timer_count % 50 == 0) {
        if(system_running) {
            LED_yunxin = !LED_yunxin;  // 运行LED闪烁
        }
    }
   
    if(timer_count >= 100) {  // 1秒周期
        timer_count = 0;
    }
}

// 主函数
void main(void) {
    // 系统初始化
    GPIO_Init();
    Timer0_Init();
    Timer1_Init();
    ADC_Init();
    UART1_Init();
   
    delay_ms(100);  // 延时稳定
   
    // 初始状态
    system_running = 0;
    adc_running = 0;
    LED_stop = 1;       // 停止LED亮
    All_Output_Low();   // 其他输出全低
   
    // 发送启动信息
    UART1_SendString("Water Level Control System Started\r\n");
    UART1_SendString("Threshold: ");
   
    // 发送阈值
    char threshold_str[10];       
    sprintf(threshold_str, "%d\r\n", adc_threshold);
    UART1_SendString(threshold_str);
   
    // 主循环
    while(1) {
        // 系统监控
        if(!system_running) {
            LED_stop = 1;  // 确保停止LED亮
        }
        
        // 空闲时进入低功耗模式
        PCON |= 0x01;  // 进入IDLE模式
        _nop_();
        _nop_();
    }
}







回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表