功能介绍:
0.本系统采用STC89C52作为单片机
功能简介:
1.LCD1602实时显示当前时间/温湿度/食物重量
2.当时间到达设定喂食时间,启动步进电机进行投喂,投喂量达到预先设定好的重量后停止投喂
3.按键可更改当前时间/喂食时间/喂食量
4.按键可手动控制喂食(手动控制时,不判断实物重量)
5.采用DC002作为电源接口可直接输入5V给整个系统供电
原理图:
PCB :
主程序:
#include "main.h"
char dis[16];
enum _MODE_DF_ dispMode;
unsigned char setIndex = 0;
bit refreshFlag = 1;
unsigned long initialWeight = 0; //单位g
float objectWeight = 0; //单位g
unsigned char feedTime[3] = {18, 0, 0}; //投喂时间18:00:00
int feedWeight = 100; //100g
bit feedFlag1 = 0; //自动喂食启动标志1
bit feedFlag2 = 0; //手动喂食启动标志2
void main(void)
{
BYJ48 = ((BYJ48 & 0xF0) | REV[0]); //取数据
ULN_DQ3 = BIT3;
ULN_DQ2 = BIT2;
ULN_DQ1 = BIT1;
ULN_DQ0 = BIT0;
Timer0_Init();
Timer1_Init();
DS1302_Init();
// DS1302_Write_Time();
DelayMs(10);
LCD_Init();
LCD_DispStr(0, 0, " Welcome! ");
DelayMs(200);
initialWeight = HX711_GetInitialWeight();
LCD_Clear();
while (1)
{
if (refreshFlag == 1) //每400ms刷新一次屏幕
{
refreshFlag = 0;
if (dispMode == NORMAL)
{
DispNormal();
}
}
if (timeBufDec[4] == feedTime[0] && timeBufDec[5] == feedTime[1] && timeBufDec[6] == feedTime[2])
{
feedFlag1 = 1; //启动喂食
}
if (objectWeight >= feedWeight) //超过喂食重量
{
feedFlag1 = 0; //停止喂食
}
KeyProcess();
}
}
void DispNormal()
{
DS1302_Read_Time(); //读取实时时间
ET1 = 0;
objectWeight = HX711_Read();
objectWeight = (objectWeight - initialWeight) / GAPVALUE; //读取实物重量
objectWeight = (objectWeight<0)?0:objectWeight;
DHT11_0_ReadData(); //读取温湿度
ET1 = 1;
sprintf(dis, "W:%6.3fkg %2d", objectWeight/1000, (int)U8T_data_H);
LCD_DispStr(0, 0, dis);
LCD_DispOneChar(13, 0, 0xdf);
LCD_DispOneChar(14, 0, 'C');
sprintf(dis, "%02d:%02d:%02d Hm:%2d%%", (int)timeBufDec[4], (int)timeBufDec[5], (int)timeBufDec[6], (int)U8RH_data_H);
LCD_DispStr(0, 1, dis);
}
/************************* 设置当前时间 *************************/
void DispSetTime(unsigned char setIndex)
{
sprintf(dis, "%02d:%02d:%02d", (int)timeBufDec[4], (int)timeBufDec[5], (int)timeBufDec[6]);
LCD_DispStr(0, 1, dis);
switch (setIndex)
{
case 1: LCD_SetCursor(1, 1, 1); break;
case 2: LCD_SetCursor(4, 1, 1); break;
case 3: LCD_SetCursor(7, 1, 1); break;
default:break;
}
}
/************************* 设置喂食时间 *************************/
void DispSetFeedTime(unsigned char setIndex)
{
LCD_DispStr(0, 0, " Feed Time ");
//LCD_DispStr(0, 0, " TIME 2 ");
sprintf(dis, " %02d:%02d:%02d ", (int)feedTime[0], (int)feedTime[1], (int)feedTime[2]);
LCD_DispStr(0, 1, dis);
switch (setIndex)
{
case 1: LCD_SetCursor(5, 1, 1); break;
case 2: LCD_SetCursor(8, 1, 1); break;
case 3: LCD_SetCursor(11, 1, 1); break;
default:break;
}
}
/************************* 设置喂食量 *************************/
void DispSetFeedWeight(unsigned char setIndex)
{
LCD_DispStr(0, 0, " Food Weight ");
sprintf(dis, " %6.3fkg ", (float)feedWeight/1000);
LCD_DispStr(0, 1, dis);
switch (setIndex)
{
case 1: LCD_SetCursor(8, 1, 1); break;
default:break;
}
}
void Timer0_Init()
{
TMOD &= 0xF0;
TMOD |= 0x01; //T0 T1 均在工作方式1
PT0 = 1; //优先级设置
TR0 = 0;
ET0 = 1; //T0开中断
EA = 1; //CPU开中断
}
void Timer1_Init()
{
TMOD &= 0x0F;
TMOD |= 0x10; //T0 T1 均在工作方式1
TH1 = (65536 - 18432) / 256; //定时20ms
TL1 = (65536 - 18432) % 256;
TR1 = 1;
ET1 = 1; //T0开中断
EA = 1; //CPU开中断
}
void Timer1(void) interrupt 3 //T1中断程序
{
static unsigned int cnt = 0;
static unsigned int motorCnt = 0;
TL1 = 0x66; //设置定时初始值
TH1 = 0xFC; //设置定时初始值 1ms
cnt++;
if (cnt >= 400)
{
refreshFlag = 1;
cnt = 0;
}
if (feedFlag1 == 1 || feedFlag2 == 1) //启动喂食,正转
{
if (motorCnt <= MAXCNT)
{
BYJ48 = ((BYJ48 & 0xF0) | REV[motorCnt % 8]); //取数据
ULN_DQ3 = BIT3;
ULN_DQ2 = BIT2;
ULN_DQ1 = BIT1;
ULN_DQ0 = BIT0;
motorCnt++;
}
}
else //停止喂食反转
{
if (motorCnt > 0)
{
BYJ48 = ((BYJ48 & 0xF0) | REV[motorCnt % 8]); //取数据
ULN_DQ3 = BIT3;
ULN_DQ2 = BIT2;
ULN_DQ1 = BIT1;
ULN_DQ0 = BIT0;
motorCnt--;
}
}
}
//程序结束