☰
C8051空压机控制软件源码解析:从温度采样到继电器输出
2026/10/19 2:26:35 网站建设 项目流程

简介:这份资源是面向工业自动化初学者与嵌入式开发者的空压机控制软件工程包,基于C8051微控制器与C语言实现,重点解决压缩机运行中温度、压力实时监测与安全保护问题。包内共151个文件,以69个h头文件、39个inc包含文件、12个c源文件为核心代码,另有obj、lst编译中间文件、lib库文件、uvproj与uvopt工程配置、hex烧录文件及少量jpg截图,压缩包约2.66MB,结构完整可直接导入Keil环境编译研究。软件通过ADC采集温度与压力传感器信号,设定阈值触发过温保护与加载卸载调节,并借助UART、SPI及LCD或LED实现人机交互与远程数据交换,还包含Flash读写、按键处理、系统调度等模块,便于理解实际项目代码组织方式。目前已有634人学习下载,适合希望掌握C8051外设驱动、传感器集成与压缩机控制逻辑的读者参考借鉴。

1. 空压机控制软件:从传感器采样到继电器输出的完整闭环

空压机控制软件听起来像是工业现场才用得上的东西,但真把它拆开看,核心逻辑并不复杂:一颗 C8051 单片机定时读温度传感器,跟设定阈值比较,决定压缩机启停、风扇转停,同时把状态码刷到数码管或串口屏上。这套逻辑跑在螺杆机、活塞机、涡旋机的控制板上,管的是排气温度、油温、电机过载这些要命的参数。我手上这份源码包就是一套典型的空压机控制器固件,C8051F 系列 MCU 打底,NTC 热敏电阻做温度采集,继电器组驱动接触器和风扇,带 RS485 上传。适合谁看?做工业控制固件的、接非标设备改造的、想拿一套能跑通的 C8051 项目练手的,都能从里面抠出能直接复用的模块。温度采样这块的玄学在于 NTC 非线性,查表还是算 Steinhart-Hart,代码里怎么处理,后面细说。

2. 硬件抽象层拆解:C8051 外设初始化与温度采样链路

2.1 系统时钟与 ADC 配置

C8051F 系列跟 STM32 不一样,它的交叉开关和优先权交叉开关是绕不开的坎。这份代码里系统时钟配到 24.5MHz 内部振荡器,ADC0 用定时器 2 溢出触发,采样率设在 1kHz 左右。为什么不用软件查询?因为空压机现场干扰大,软件查询容易采到开关噪声,定时器触发能保证采样间隔均匀,后面做滑动滤波才有意义。

// 系统时钟与ADC初始化,C8051F340 void SysClk_Init(void) { OSCICN = 0x83; // 使能内部振荡器,不分频,24.5MHz CLKSEL = 0x00; // 时钟源选内部振荡器 while((OSCICN & 0x10) == 0); // 等待振荡器稳定 } void ADC0_Init(void) { REF0CN = 0x03; // 使能内部基准,VREF=2.4V AMX0P = 0x0C; // P3.0作为ADC0正输入,接NTC分压 ADC0CF = 0xF8; // 转换时钟=系统时钟/8,增益=1 ADC0CN = 0x02; // 定时器2溢出触发,右对齐 EIE1 |= 0x08; // 使能ADC0转换结束中断 AD0EN = 1; // 使能ADC0 }

这里有个参数要盯住:ADC0CF = 0xF8把 SAR 时钟设成 3MHz 左右,24.5MHz 系统时钟下转换一次大概 2.5us,留足了采样保持时间。AMX0P = 0x0C选的是 P3.0 通道,对应 NTC 分压点。如果你换板子,这个通道号得跟着原理图改,改错了采回来就是满量程或者零,别问我是怎么知道的。

2.2 NTC 温度换算:查表加线性插值

NTC 10K 的阻值-温度曲线是非线性的,直接套公式算浮点对 C8051 来说太奢侈。代码里用的是分段查表加线性插值,表按 5℃ 一档存 ADC 码值,实际温度落在两档之间就插值。这样既省 CPU,精度也能做到 ±0.5℃ 以内,对空压机排气温度保护来说够用了。

// NTC温度查表,-20℃到150℃,5℃一档 const unsigned int NTC_Table[] = { 3720, 3510, 3280, 3040, 2790, 2540, 2290, 2050, 1820, 1600, 1400, 1220, 1060, 920, 790, 680, 580, 495, 420, 355, 300, 253, 213, 180, 152, 128, 108, 91, 77, 65, 55, 47, 40, 34, 29 }; int Get_Temperature(unsigned int adc_val) { unsigned char i; int temp; // 超出表格范围直接返回边界值 if(adc_val >= NTC_Table[0]) return -20; if(adc_val <= NTC_Table[34]) return 150; for(i = 0; i < 34; i++) { if(adc_val >= NTC_Table[i+1] && adc_val < NTC_Table[i]) { // 线性插值:温度 = 低档温度 + 比例 * 5℃ temp = -20 + i * 5; temp += (int)((long)(NTC_Table[i] - adc_val) * 5 / (NTC_Table[i] - NTC_Table[i+1])); return temp; } } return 0; }

NTC_Table数组是按 ADC 码值从大到小排的,因为温度越高 NTC 阻值越小,分压点电压越低,ADC 码值越小。插值那行用long强转是为了防止乘法溢出,C8051 的 int 是 16 位,(NTC_Table[i] - adc_val) * 5最大能到 18000 多,不转 long 会翻车。这个表你得根据自己用的 NTC 型号重新标定,B 值不同曲线差很多,直接抄表温度能偏出十几度。

2.3 滑动滤波与断线检测

ADC 采回来的原始值不能直接用,现场接触器吸合那一下能干扰出几十个码值的跳动。代码里做了 8 点滑动平均,同时判断采样值是否在合理范围内,超出范围认为传感器断线,直接报故障停机。

#define FILTER_LEN 8 unsigned int Adc_Buf[FILTER_LEN]; unsigned char Buf_Index = 0; unsigned int Filter_Adc(unsigned int new_val) { unsigned long sum = 0; unsigned char i; Adc_Buf[Buf_Index] = new_val; Buf_Index = (Buf_Index + 1) % FILTER_LEN; for(i = 0; i < FILTER_LEN; i++) { sum += Adc_Buf[i]; } return (unsigned int)(sum / FILTER_LEN); } // 断线检测:ADC值持续为满量程或零 bit Check_Sensor_Open(unsigned int adc_val) { static unsigned char open_cnt = 0; if(adc_val > 4000 || adc_val < 20) { open_cnt++; if(open_cnt > 50) { // 连续50次异常,约50ms open_cnt = 0; return 1; // 传感器断线 } } else { open_cnt = 0; } return 0; }

滤波长度 8 是我试出来的平衡点,再长响应就迟钝了,排气温度涨得快的时候保护会滞后。断线检测的阈值 4000 和 20 对应分压电路的上拉和下拉极限,你要是改了分压电阻,这两个数得跟着调。open_cnt > 50是防抖,避免干扰脉冲误报。

3. 控制逻辑实现:阈值比较、状态机与继电器输出

3.1 压缩机启停状态机

空压机的启停不是简单的大于开小于关,得有回差、有延时、有故障锁死。代码里用了一个四状态机:待机、启动延时、运行、故障。温度超过上限进入启动延时,延时到了才吸合接触器,温度降到下限以下再延时停机,防止频繁启停把接触器烧了。

typedef enum { STATE_IDLE = 0, STATE_START_DELAY, STATE_RUNNING, STATE_FAULT } SystemState; SystemState sys_state = STATE_IDLE; unsigned int delay_cnt = 0; void Control_Logic(int temp) { switch(sys_state) { case STATE_IDLE: if(temp >= TEMP_START) { // 超过启动阈值 sys_state = STATE_START_DELAY; delay_cnt = 0; } break; case STATE_START_DELAY: delay_cnt++; if(delay_cnt >= START_DELAY_MS) { // 启动延时到 RELAY_MAIN = 1; // 吸合主接触器 RELAY_FAN = 1; // 风扇同时启动 sys_state = STATE_RUNNING; } if(temp < TEMP_START - TEMP_HYST) { // 温度回落,取消启动 sys_state = STATE_IDLE; } break; case STATE_RUNNING: if(temp <= TEMP_STOP) { // 低于停机阈值 RELAY_MAIN = 0; RELAY_FAN = 0; sys_state = STATE_IDLE; } if(temp >= TEMP_FAULT) { // 超温故障 RELAY_MAIN = 0; RELAY_FAN = 0; sys_state = STATE_FAULT; } break; case STATE_FAULT: RELAY_MAIN = 0; RELAY_FAN = 0; // 需要手动复位或断电重启才能退出 if(FAULT_RESET_BTN == 0 && temp < TEMP_START) { sys_state = STATE_IDLE; } break; } }

TEMP_START、TEMP_STOP、TEMP_FAULT这三个阈值一般设 85℃、75℃、105℃,回差TEMP_HYST给 5℃。启动延时START_DELAY_MS通常 3000 到 5000ms,看电机功率。故障状态必须手动复位,这是血泪教训——自动复位的话,传感器真坏了会反复启停,把机头干废。

3.2 继电器输出与互锁

继电器输出这块有个坑:C8051 的 IO 口上电默认是高阻,如果继电器驱动电路是低电平有效,上电瞬间会全部吸合一下。代码里在初始化最前面就把所有继电器口置高,硬件上再加下拉电阻。

// 继电器引脚定义,低电平有效 sbit RELAY_MAIN = P1^0; // 主接触器 sbit RELAY_FAN = P1^1; // 风扇 sbit RELAY_ALARM = P1^2; // 报警输出 void Relay_Init(void) { P1MDOUT |= 0x07; // P1.0-P1.2推挽输出 P1 |= 0x07; // 先全部置高,继电器不动作 RELAY_MAIN = 1; RELAY_FAN = 1; RELAY_ALARM = 1; } // 互锁:风扇故障时禁止启动主电机 bit Check_Interlock(void) { if(RELAY_FAN == 0 && FAN_FEEDBACK == 1) { return 0; // 风扇没转起来,不允许启动主机 } return 1; }

P1MDOUT设推挽是为了驱动能力够,直接推光耦或者三极管。互锁逻辑里FAN_FEEDBACK是风扇接触器的辅助触点,没有这个反馈,风扇皮带断了主机还在转,机头几分钟就过热。这个互锁在代码里是硬判断,不经过状态机,任何情况下风扇没反馈都不让主机吸合。

3.3 故障码存储与串口上传

故障码存在片内 Flash 里,掉电不丢。C8051F340 有 4KB 的 Flash 可以当 EEPROM 用,代码里划了最后 512 字节存故障记录,每条记录 8 字节,循环覆盖。

#define FAULT_BASE 0xF000 // 故障记录起始地址 #define FAULT_MAX 64 // 最多存64条 typedef struct { unsigned char code; // 故障码 int temp; // 故障时温度 unsigned int runtime; // 累计运行时间 unsigned char reserved; } FaultRecord; void Save_Fault(unsigned char code, int temp) { unsigned char i; FaultRecord rec; unsigned int addr; rec.code = code; rec.temp = temp; rec.runtime = total_runtime; // 找空位或覆盖最旧 for(i = 0; i < FAULT_MAX; i++) { addr = FAULT_BASE + i * sizeof(FaultRecord); if(Flash_Read_Byte(addr) == 0xFF) { break; } } if(i >= FAULT_MAX) i = 0; // 满了从头覆盖 addr = FAULT_BASE + i * sizeof(FaultRecord); Flash_Write(addr, (unsigned char *)&rec, sizeof(FaultRecord)); }

Flash_Write是底层擦写函数,C8051 写 Flash 前必须先擦除整个扇区,所以实际代码里是先把整个扇区读到 RAM,改完再擦再写回去。这个操作耗时大概 20ms,期间不能断电,否则记录全丢。我一般会在写之前先把看门狗喂了,再关中断,写完再开。

4. 避坑与排查:C8051 空压机控制器的常见翻车点

4.1 温度跳变导致频繁启停

现象是空压机运行几分钟就停,停了没一会又启,接触器啪啪响。原因多半是 NTC 采样线跟电机线走在一起了,变频器或者接触器线圈的干扰耦合进来,ADC 值跳变超过回差。解决分两步:硬件上把 NTC 线换成屏蔽线,屏蔽层单端接地;软件上把滑动滤波长度从 8 加到 16,同时在状态机里加一个“温度必须连续 3 次超过阈值才动作”的判断。

4.2 上电继电器瞬间吸合

前面提过,C8051 的 IO 上电默认高阻,如果驱动电路是低有效,上电瞬间继电器会抖一下。现象是每次上电空压机“啪”一声,接触器吸合又断开。解决是在main函数最开头、任何外设初始化之前,先把继电器口置高,同时硬件上加 10K 下拉电阻到地。代码顺序不能反,先配P1MDOUT再置高,否则推挽没开,置高也没驱动能力。

4.3 Flash 写故障记录导致看门狗复位

C8051 擦写 Flash 的时候 CPU 会停顿,如果看门狗没处理,直接复位。现象是每次存故障记录就重启,故障码还存不进去。解决是在Flash_Write前后加WDT_Feed(),并且把看门狗超时设到最长。更稳妥的做法是存故障前先关看门狗,存完再开,但这样万一写 Flash 卡死就没救了,我一般还是喂狗。

4.4 RS485 通信在电机启动时丢包

现象是空压机一启动,上位机就报通信中断。原因是 RS485 收发器跟电机共地,地电位跳变导致差分信号超范围。解决是给 RS485 加隔离模块,或者至少把 A/B 线换成双绞屏蔽线,屏蔽层接大地。软件上把通信超时从 1s 放宽到 3s,给重传留时间。

4.5 温度查表精度不够

有人直接抄了 10K B=3950 的表,结果实际用的 NTC 是 B=3435,温度差出 8℃ 以上。现象是排气温度显示 95℃,实际才 87℃,保护提前动作。解决是拿恒温槽标定,从 20℃ 到 120℃ 每隔 10℃ 记 ADC 值,重新生成表格。没有恒温槽的话,至少用冰水混合物和沸水标两个点,反推 B 值修正。

5. 二次开发改造:从单机控制到多机联控的扩展思路

拿到这份源码想改造成自己的东西,最直接的路子是先把温度采样和继电器输出这两个模块吃透,然后按自己的硬件改引脚和阈值。但如果你要做多台空压机联控,就得动架构了。我一般会这么干:把单机控制逻辑封装成一个独立的任务函数,主循环里用时间片轮询,每台机器一个状态机实例,通过 RS485 或者 CAN 交换启停请求和故障状态。

// 多机联控的调度框架 #define MAX_UNITS 4 typedef struct { SystemState state; int temp; unsigned int delay_cnt; unsigned char fault_code; unsigned char addr; // 从站地址 } CompressorUnit; CompressorUnit units[MAX_UNITS]; void Main_Loop(void) { unsigned char i; static unsigned int tick = 0; for(i = 0; i < MAX_UNITS; i++) { // 每10ms调度一台,4台轮一圈40ms if((tick % MAX_UNITS) == i) { units[i].temp = Get_Temperature( Filter_Adc(ADC_Read(units[i].addr))); Control_Logic_Unit(&units[i]); } } tick++; // 联控逻辑:根据总管压力决定启停台数 if(tick % 100 == 0) { Cascade_Control(units, MAX_UNITS); } }

这个框架的关键是把Control_Logic改成带实例参数的版本,所有状态变量从全局挪到结构体里。Cascade_Control负责读总管压力,压力低于下限就按运行时间最短的优先启动,高于上限就按运行时间最长的优先停。轮询周期 40ms 对空压机来说绰绰有余,温度变化是秒级的。

改造时验证方法很简单:先用信号发生器模拟 NTC 分压,从 0.5V 扫到 2.0V,看每台机器的状态切换和继电器动作是否跟单机版一致。然后接实际传感器,用热风枪加热,看联控逻辑能不能正确加减载。最后跑 72 小时老化,重点盯 Flash 故障记录有没有丢、RS485 有没有累积错误。

从那以后我每次改完控制逻辑,都强制走一遍“模拟传感器全量程扫描 + 继电器动作记录 + 故障注入”这三步,少一步都不敢上机。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询