功能:
0.本系统采用STC89C52作为单片机
1、LCD1602实时显示当前滴速控制等级及当前滴速检测值
2、系统通过控制步进电机来控制滴速,同时使用单片机外部中断检测当前滴速
3、按键可启动/停止输液,按键可更改滴速等级
4、当液位低于最低液位时,系统检测到一个高电平,蜂鸣器报警同时停止输液
5.采用DC002作为电源接口可直接输入5V给整个系统供电
原理图:
PCB :
主程序:
#include "main.h"
#include "lcd1602.h"
#include "key.h"
#include "28byj48.h"
bit dispFlag = 1;
bit startFlag = 0;
bit refreshFlag = 0;
bit updateFlag = 0;
unsigned int timeCnt = 0; //滴速检测计数
float speedNow = 0; // 滴速
unsigned char datIndex = 0;
int speedNowBuf[2] = 0; // 滴速缓存
unsigned char speedLevel = 1; // 滴速档位, 取1~10
unsigned char tab0[16]; //显示内容缓存
unsigned char index=0;
unsigned char cnt2=0;
void main()
{
/* 初始化 */
Timer0_Init();
Timer1_Init();
Ext0_Init();
LCD_Init();
LCD_Clear();
LCD_DispStr(0, 0, "SpeedLevel: ");
LCD_DispStr(0, 1, "Speed: d/min");
while(1)
{
if (startFlag == 1 && refreshFlag == 1) //刷新数据
{
refreshFlag = 0;
EX0 = 0; //关闭外部中断0
TR1 = 0; //关闭定时器1
speedNowBuf[datIndex] = timeCnt * 5; //计算n*5ms
datIndex++;
if (datIndex >= 2)
{
datIndex = 0;
updateFlag = 1;
}
timeCnt = 0;
TH1 = (65536 - 4608 + 900) / 256; //(65536 - 0.005*11059200/12) / 256
TL1 = (65536 - 4608 + 900) % 256; //(65536 - 0.005*11059200/12) % 256 5ms
EX0 = 1; //打开外部中断0
TR1 = 1; //打开定时器1
}
if (dispFlag == 1) //定时刷新显示
{
dispFlag = 0;
if (startFlag == 1)
{
if (updateFlag == 0) //不更新数据
{
speedNow = 0;
}
else //更新数据,求平均值
{
speedNow = 60000 / ((speedNowBuf[0]/2) + (speedNowBuf[1]/2)); //液滴速度计算 2次求平均值
}
}
else
{
speedNow = 0;
updateFlag = 0;
datIndex = 0;
}
sprintf(tab0, "%2d", (int)speedLevel);
LCD_DispStr(13, 0, tab0);
sprintf(tab0, "%5.1f", (float)speedNow);
LCD_DispStr(6, 1, tab0);
}
if (startFlag == 1) //点滴开启状态
{
LED_GREEN_ON;
LED_RED_OFF;
if (LIQUID_LEVEL_CHECK == 1) //液位低于最低液位,报警
{
BUZZER_ON; //蜂鸣器报警
startFlag = 0; //停止输液
}
else
{
BUZZER_OFF;
}
}
else
{
LED_GREEN_OFF;
LED_RED_ON;
}
if (startFlag == 1) //控制电机转动
{
cnt2++;
if (cnt2 == 15 - speedLevel)
{
cnt2 = 0;
index++;
if (index > 8)
{
index = 0;
}
BYJ48 = ((BYJ48 & 0xF0) | FFW[index]); //取数据
ULN_DQ3 = BIT3; ULN_DQ2 = BIT2; ULN_DQ1 = BIT1; ULN_DQ0 = BIT0;
}
DelayUs10x(10);
}
KeyProcess();
}
}
/***********外部中断0初始化程序****************/
void Ext0_Init() //外部中断0初始化程序
{
IT0 = 1; //外部中断0负跳变中断
PX0 = 1; //设置高优先级
EX0 = 1; //允许外部中断0中断
}
void Ext0_Interrupt() interrupt 0
{
if (timeCnt < 80) //当连续两次检测时间间隔小于80*5ms=400ms不处理
{
TR1 = 1; //开定时器
}
else
{
refreshFlag = 1;
}
}
void Timer0_Init(void)
{
TMOD &= 0xF0;
TMOD |= 0x01;
TH0 = 0xDC; //10ms
TL0 = 0x00;
TR0 = 1; //启动T0计时
ET0 = 1; //打开T0中断
EA = 1; //打开总中断
}
void Timer0_Intterupt(void) interrupt 1
{
static unsigned int cnt=0;
TL0 = 0x66; //设置定时初始值
TH0 = 0xFC; //设置定时初始值 1ms
cnt++;
//cnt2++;
if (cnt >= 500) //500ms
{
cnt = 0;
dispFlag = 1;
}
// if (startFlag == 1 && cnt2 == 11 - speedLevel) //控制电机转动
// {
// cnt2 = 0;
// index++;
// if (index > 8)
// {
// index = 0;
// }
// BYJ48 = ((BYJ48 & 0xF0) | FFW[index]); //取数据
// ULN_DQ3 = BIT3; ULN_DQ2 = BIT2; ULN_DQ1 = BIT1; ULN_DQ0 = BIT0;
// }
}
void Timer1_Init(void)
{
TMOD &= 0x0F;
TMOD |= 0x10;
TH1 = (65536 - 4608 + 900) / 256; //(65536 - 0.005*11059200/12) / 256
TL1 = (65536 - 4608 + 900) % 256; //(65536 - 0.005*11059200/12) % 256 5ms
PT1 = 1;
TR1 = 0; //暂停T1计时
ET1 = 1; //打开T1中断
EA = 1; //打开总中断
}
void Timer1_Intterupt(void) interrupt 3
{
TH1 = (65536 - 4608 + 900) / 256; //(65536 - 0.005*11059200/12) / 256
TL1 = (65536 - 4608 + 900) % 256; //(65536 - 0.005*11059200/12) % 256 5ms
timeCnt++; //每5ms计数一次
if (timeCnt >= 4000) //20s如果没检测到信号,则清空数据
{
datIndex = 0; //数据个数清零
timeCnt = 0; //5ms计数清零
updateFlag = 0;
TR1 = 0; //暂停T1计时
}
}