【51单片机】【protues仿真】基于51单片机宠物投食器系统

目录

一、主要功能

二、使用步骤

三、硬件资源

四、软件设计

五、实验现象

一、主要功能

1、LCD1602液晶显示当前时间

2、按键设置时间,5个定时投喂时间​

3、可以通过手动按键进行投喂食物

4、步进电机模拟投喂食物

二、使用步骤

基于51单片机的宠物自动投食器系统设计可实现定时喂食、手动喂食及状态监测等功能。

三、硬件资源

1、51单片机核心模块

2、按键模块

3、时钟模块

4、蜂鸣器模块

5、步进电机模块

6、LCD1602显示模块

四、软件设计

#include "common.h"

#include "lcd1602.h"

#include "eeprom52.h"

#include "DS1302.h"

sbit key1 = P1^0;//切换键

sbit key2 = P1^1;//加键

sbit key3 = P1^2;//减键

sbit key4 = P1^3;//开启

sbit key5 = P1^4;//关闭

sbit beep = P3^7;//蜂鸣器

#define angle 360 //电机旋转的角度

uchar code Clock[]={0x01,0x02,0x04,0x08}; // 步进电机顺时针旋转数组

uchar code AntiClock[]={0x08,0x04,0x02,0x01}; // 步进电机逆时针旋转数组

unsigned char setn = 0;//设置标志

uchar DS1302_Table[7]={0};

uchar sec, min, hour, day, month, week, year;

bit open_flag=0;

bit feeding_time = 0;

typedef struct {

unsigned char shi; //时

unsigned char fen; //分

}user;

user foodtime1={7,00}; //喂食时间1

user foodtime2={11,03}; //喂食时间2

user foodtime3={14,0}; //喂食时间3

user foodtime4={17,0}; //喂食时间4

user foodtime5={22,19}; //喂食时间5

/*********************************************************/

// 毫秒级的延时函数,time是要延时的毫秒数

/*********************************************************/

void DelayMs(uint time)

{

uint i,j;

for(i=0;i<time;i++)

for(j=0;j<112;j++);

}

/*********************************************************/

// 开

/*********************************************************/

void Ul2003_Open()

{

uint i,j;

for(j=0;j<10;j++) // 控制步进电机正转

{

for(i=0;i<4;i++)

{

P2=Clock[i]|0xf0;

DelayMs(10);

}

}

}

/*********************************************************/

// 关

/*********************************************************/

void Ul2003_Close()

{

uint i,j;

for(j=0;j<10;j++) // 控制步进电机反转

{

for(i=0;i<4;i++)

{

P2=AntiClock[i]|0xf0;

DelayMs(10);

}

}

}

void time_init(void) //定时器初始化

{

TMOD |= 0x01; //定时器0工作方式1

TL0 = 0xCD;

TH0 = 0xF8; //定时器定时2ms

TR0 = 1;

ET0 = 1; //开定时器0中断

EA = 1; //开总中断

}

void eepromWriteByte(void)

{

uint addr=0x2000;

SectorErase(addr);//扇区擦除

byte_write(addr++, foodtime1.shi);

byte_write(addr++, foodtime1.fen);

byte_write(addr++, foodtime2.shi);

byte_write(addr++, foodtime2.fen);

byte_write(addr++, foodtime3.shi);

byte_write(addr++, foodtime3.fen);

byte_write(addr++, foodtime4.shi);

byte_write(addr++, foodtime4.fen);

byte_write(addr++, foodtime5.shi);

byte_write(addr++, foodtime5.fen);

byte_write(0x2014, 0xAA);

}

void eepromInit(void)

{

uint addr=0x2000;

if(byte_read(0x2014)!=0xAA)//校验是不是新的单片机

{

eepromWriteByte();

delay_ms(100);

}

}

void displayTime(void)

{

//显示时间

lcd_write_com(0x80);

lcd_write_data(DS1302_Table[0]/10+0x30);

lcd_write_data(DS1302_Table[0]%10+0x30);

lcd_write_data('/');

lcd_write_data(DS1302_Table[1]/10+0x30);

lcd_write_data(DS1302_Table[1]%10+0x30);

lcd_write_data('/');

lcd_write_data(DS1302_Table[2]/10+0x30);

lcd_write_data(DS1302_Table[2]%10+0x30);

lcd_write_com(0x80+0x40);

lcd_write_data(DS1302_Table[4]/10+0x30);

lcd_write_data(DS1302_Table[4]%10+0x30);

lcd_write_data(':');

lcd_write_data(DS1302_Table[5]/10+0x30);

lcd_write_data(DS1302_Table[5]%10+0x30);

lcd_write_data(':');

lcd_write_data(DS1302_Table[6]/10+0x30);

lcd_write_data(DS1302_Table[6]%10+0x30);

}

void write_week(uchar week)//写星期函数

{

lcd_write_com(0x80+9);//星期字符的显示位置

switch(week)

{

case 1:

lcd_write_data('M');//星期数为1时,显示

lcd_write_data('O');

lcd_write_data('N');

break;

case 2:

lcd_write_data('T');//星期数据为2时显示

lcd_write_data('U');

lcd_write_data('E');

break;

case 3:

lcd_write_data('W');//星期数据为3时显示

lcd_write_data('E');

lcd_write_data('D');

break;

case 4:

lcd_write_data('T');//星期数据为4是显示

lcd_write_data('H');

lcd_write_data('U');

break;

case 5:

lcd_write_data('F');//星期数据为5时显示

lcd_write_data('R');

lcd_write_data('I');

break;

case 6:

lcd_write_data('S');//星期数据为6时显示

lcd_write_data('A');

lcd_write_data('T');

break;

case 0:

lcd_write_data('S');//星期数据为7时显示

lcd_write_data('U');

lcd_write_data('N');

break;

}

}

void Run_DS1302(void)//DS1302运行

{

//获取时间:年月日时分秒

v_W1302(0x8f, 0);

sec = bcdtodec(uc_R1302(0x81));

v_W1302(0x8f, 0);

min = bcdtodec(uc_R1302(0x83));

v_W1302(0x8f, 0);

hour = bcdtodec(uc_R1302(0x85));

v_W1302(0x8f, 0);

day = bcdtodec(uc_R1302(0x87));

v_W1302(0x8f, 0);

month = bcdtodec(uc_R1302(0x89));

v_W1302(0x8f, 0);

week = bcdtodec(uc_R1302(0x8b));

v_W1302(0x8f, 0);

year = bcdtodec(uc_R1302(0x8d));

DS1302_Table[0]=year;

DS1302_Table[1]=month;

DS1302_Table[2]=day;

DS1302_Table[3]=week;

DS1302_Table[4]=hour;

DS1302_Table[5]=min;

DS1302_Table[6]=sec;

displayTime();

// write_week(week);

}

void displayUserSetValue(const user * const date)//显示设置值

{

lcd_write_char(6,1,date ->shi / 10+'0');

lcd_write_char(7,1,date ->shi % 10+'0');

lcd_write_char(9,1,date ->fen / 10+'0');

lcd_write_char(10,1,date ->fen % 10+'0');

}

void keyscan()

{

if(key1 == 0)//设置键

{

delay_ms(10);

if(key1 == 0)

{

beep = 0;

delay_ms(100);

beep = 1;

while(key1 == 0);//等待按键松开

setn++;

if(setn > 16)//按下次数超过16次,退出设置

{

setn = 0;

lcd_write_com(0x0c);//关闭光标

lcd_clear();

lcd_write_str(0, 0, " / / ");

lcd_write_str(0, 1, " : : ");

eepromWriteByte(); //退出设置之后,把数据保存一遍

}

if(setn == 1)//设置年

{

displayTime();

lcd_write_com(0x80+1);

lcd_write_com(0x0f);

}

if(setn == 2)//设置月

{

lcd_write_com(0x80+4);

lcd_write_com(0x0f);

}

if(setn == 3)//日

{

lcd_write_com(0x80+7);

lcd_write_com(0x0f);

}

if(setn == 4)//时

{

lcd_write_com(0x80+0x40+1);

lcd_write_com(0x0f);

}

if(setn == 5)//分

{

lcd_write_com(0x80+0x40+4);

lcd_write_com(0x0f);

}

if(setn == 6)//秒

{

lcd_write_com(0x80+0x40+7);

lcd_write_com(0x0f);

}

if(setn == 7)

{

lcd_write_str(0, 0, "set food time 1 ");

lcd_write_str(0, 1, " 00:00 ");

displayUserSetValue(&foodtime1);

lcd_write_com(0x80+0x40+7);

lcd_write_com(0x0f);

}

if(setn == 8)

{

lcd_write_com(0x80+0x40+10);

lcd_write_com(0x0F);

}

if(setn == 9)

{

lcd_write_str(0, 0, "set food time 2 ");

lcd_write_str(0, 1, " 00:00 ");

displayUserSetValue(&foodtime2);

lcd_write_com(0x80+0x40+7);

lcd_write_com(0x0f);

}

if(setn == 10)

{

lcd_write_com(0x80+0x40+10);

lcd_write_com(0x0F);

}

if(setn == 11)

{

lcd_write_str(0, 0, "set food time 3 ");

lcd_write_str(0, 1, " 00:00 ");

displayUserSetValue(&foodtime3);

lcd_write_com(0x80+0x40+7);

lcd_write_com(0x0f);

}

if(setn == 12)

{

lcd_write_com(0x80+0x40+10);

lcd_write_com(0x0F);

}

if(setn == 13)

{

lcd_write_str(0, 0, "set food time 4 ");

lcd_write_str(0, 1, " 00:00 ");

displayUserSetValue(&foodtime4);

lcd_write_com(0x80+0x40+7);

lcd_write_com(0x0f);

}

if(setn == 14)

{

lcd_write_com(0x80+0x40+10);

lcd_write_com(0x0F);

}

if(setn == 15)

{

lcd_write_str(0, 0, "set food time 5 ");

lcd_write_str(0, 1, " 00:00 ");

displayUserSetValue(&foodtime5);

lcd_write_com(0x80+0x40+7);

lcd_write_com(0x0f);

}

if(setn == 16)

{

lcd_write_com(0x80+0x40+10);

lcd_write_com(0x0F);

}

}

}

if(key2 == 0)

{

delay_ms(10);

if(key2 == 0)

{

beep = 0;

delay_ms(100);

beep = 1;

while(key2 == 0);

if(setn == 1)//设置年

{

DS1302_Table[0]++;

if(DS1302_Table[0] == 100)//最大到100

DS1302_Table[0] = 0;

Write_DS1302Init(DS1302_Table[0],DS1302_Table[1],DS1302_Table[2],0,DS1302_Table[4],DS1302_Table[5],DS1302_Table[6]);//写入DS1302

displayTime();//显示

lcd_write_com(0x80+1);

lcd_write_com(0x0f);//光标闪烁

}

else if(setn == 2)//设置月

{

DS1302_Table[1]++;

if(DS1302_Table[1]==13)//最大12个月

DS1302_Table[1]=1;

Write_DS1302Init(DS1302_Table[0],DS1302_Table[1],DS1302_Table[2],0,DS1302_Table[4],DS1302_Table[5],DS1302_Table[6]);//写入DS1302

displayTime();//显示

lcd_write_com(0x80+4);

lcd_write_com(0x0f);//光标闪烁

}

else if(setn == 3)//设置日

{

DS1302_Table[2]++;

if(DS1302_Table[2]==32)

DS1302_Table[2]=1;

Write_DS1302Init(DS1302_Table[0],DS1302_Table[1],DS1302_Table[2],0,DS1302_Table[4],DS1302_Table[5],DS1302_Table[6]);//写入DS1302

displayTime();//显示

lcd_write_com(0x80+7);

lcd_write_com(0x0f);//光标闪烁

}

else if(setn == 4)//设置时

{

DS1302_Table[4]++;

if(DS1302_Table[4] == 24)//到0点

DS1302_Table[4] = 0;

Write_DS1302Init(DS1302_Table[0],DS1302_Table[1],DS1302_Table[2],0,DS1302_Table[4],DS1302_Table[5],DS1302_Table[6]);//写入DS1302

displayTime();//显示

lcd_write_com(0x80+0x40+1);

lcd_write_com(0x0f);//光标闪烁

}

else if(setn == 5)//设置分

{

DS1302_Table[5]++;

if(DS1302_Table[5] == 60)//60分钟

DS1302_Table[5] = 0;

Write_DS1302Init(DS1302_Table[0],DS1302_Table[1],DS1302_Table[2],0,DS1302_Table[4],DS1302_Table[5],DS1302_Table[6]);//写入DS1302

displayTime();//显示

lcd_write_com(0x80+0x40+4);

lcd_write_com(0x0f);//光标闪烁

}

else if(setn == 6)//设置分

{

DS1302_Table[6]++;

if(DS1302_Table[6] == 60)//60秒

DS1302_Table[6] = 0;

Write_DS1302Init(DS1302_Table[0],DS1302_Table[1],DS1302_Table[2],0,DS1302_Table[4],DS1302_Table[5],DS1302_Table[6]);//写入DS1302

displayTime();//显示

lcd_write_com(0x80+0x40+7);

lcd_write_com(0x0f);//光标闪烁

}

else if(setn == 7)

{

foodtime1.shi++;

if(foodtime1.shi==24)

foodtime1.shi=0;

displayUserSetValue(&foodtime1);

lcd_write_com(0x80+0x40+7);

lcd_write_com(0x0f);

}

else if(setn == 8)

{

foodtime1.fen++;

if(foodtime1.fen==60)

foodtime1.fen=0;

displayUserSetValue(&foodtime1);

lcd_write_com(0x80+0x40+10);

lcd_write_com(0x0F);

}

else if(setn == 9)

{

foodtime2.shi++;

if(foodtime2.shi==24)

foodtime2.shi=0;

displayUserSetValue(&foodtime2);

lcd_write_com(0x80+0x40+7);

lcd_write_com(0x0f);

}

else if(setn == 10)

{

foodtime2.fen++;

if(foodtime2.fen==60)

foodtime2.fen=0;

displayUserSetValue(&foodtime2);

lcd_write_com(0x80+0x40+10);

lcd_write_com(0x0F);

}

else if(setn == 11)

{

foodtime3.shi++;

if(foodtime3.shi==24)

foodtime3.shi=0;

displayUserSetValue(&foodtime3);

lcd_write_com(0x80+0x40+7);

lcd_write_com(0x0f);

}

else if(setn == 12)

{

foodtime3.fen++;

if(foodtime3.fen==60)

foodtime3.fen=0;

displayUserSetValue(&foodtime3);

lcd_write_com(0x80+0x40+10);

lcd_write_com(0x0F);

}

else if(setn == 13)

{

foodtime4.shi++;

if(foodtime4.shi==24)

foodtime4.shi=0;

displayUserSetValue(&foodtime4);

lcd_write_com(0x80+0x40+7);

lcd_write_com(0x0f);

}

else if(setn == 14)

{

foodtime4.fen++;

if(foodtime4.fen==60)

foodtime4.fen=0;

displayUserSetValue(&foodtime4);

lcd_write_com(0x80+0x40+10);

lcd_write_com(0x0F);

}

else if(setn == 15)

{

foodtime5.shi++;

if(foodtime5.shi==24)

foodtime5.shi=0;

displayUserSetValue(&foodtime5);

lcd_write_com(0x80+0x40+7);

lcd_write_com(0x0f);

}

else if(setn == 16)

{

foodtime5.fen++;

if(foodtime5.fen==60)

foodtime5.fen=0;

displayUserSetValue(&foodtime5);

lcd_write_com(0x80+0x40+10);

lcd_write_com(0x0F);

}

}

}

if(key3 == 0)

{

delay_ms(10);

if(key3 == 0 )

{

beep = 0;

delay_ms(100);

beep = 1;

while(key3 == 0);

if(setn == 1)//设置年

{

if(DS1302_Table[0] == 0)

DS1302_Table[0] = 100;

DS1302_Table[0]--;

Write_DS1302Init(DS1302_Table[0],DS1302_Table[1],DS1302_Table[2],0,DS1302_Table[4],DS1302_Table[5],DS1302_Table[6]);

displayTime();

lcd_write_com(0x80+1);

lcd_write_com(0x0f);

}

else if(setn == 2)//设置月

{

DS1302_Table[1]--;

if(DS1302_Table[1]==0)

DS1302_Table[1]=12;

Write_DS1302Init(DS1302_Table[0],DS1302_Table[1],DS1302_Table[2],0,DS1302_Table[4],DS1302_Table[5],DS1302_Table[6]);

displayTime();

lcd_write_com(0x80+4);

lcd_write_com(0x0f);

}

else if(setn == 3)//设置日

{

DS1302_Table[2]--;

if(DS1302_Table[2]==0)

DS1302_Table[2]=31;

Write_DS1302Init(DS1302_Table[0],DS1302_Table[1],DS1302_Table[2],0,DS1302_Table[4],DS1302_Table[5],DS1302_Table[6]);

displayTime();

lcd_write_com(0x80+7);

lcd_write_com(0x0f);

}

else if(setn == 4)//设置时

{

if(DS1302_Table[4] == 0)

DS1302_Table[4] = 24;

DS1302_Table[4]--;

Write_DS1302Init(DS1302_Table[0],DS1302_Table[1],DS1302_Table[2],0,DS1302_Table[4],DS1302_Table[5],DS1302_Table[6]);

displayTime();

lcd_write_com(0x80+0x40+1);

lcd_write_com(0x0f);

}

else if(setn == 5)//设置分

{

if(DS1302_Table[5] == 0)

DS1302_Table[5] = 60;

DS1302_Table[5]--;

Write_DS1302Init(DS1302_Table[0],DS1302_Table[1],DS1302_Table[2],0,DS1302_Table[4],DS1302_Table[5],DS1302_Table[6]);

displayTime();

lcd_write_com(0x80+0x40+4);

lcd_write_com(0x0f);

}

else if(setn == 6)//设置秒

{

if(DS1302_Table[6] == 0)

DS1302_Table[6] = 60;

DS1302_Table[6]--;

Write_DS1302Init(DS1302_Table[0],DS1302_Table[1],DS1302_Table[2],0,DS1302_Table[4],DS1302_Table[5],DS1302_Table[6]);

displayTime();

lcd_write_com(0x80+0x40+7);

lcd_write_com(0x0f);

}

else if(setn == 7)

{

if(foodtime1.shi==0)

foodtime1.shi=24;

foodtime1.shi--;

displayUserSetValue(&foodtime1);

lcd_write_com(0x80+0x40+7);

lcd_write_com(0x0f);

}

else if(setn == 8)

{

if(foodtime1.fen==0)

foodtime1.fen=60;

foodtime1.fen--;

displayUserSetValue(&foodtime1);

lcd_write_com(0x80+0x40+10);

lcd_write_com(0x0F);

}

else if(setn == 9)

{

if(foodtime2.shi==0)

foodtime2.shi=24;

foodtime2.shi--;

displayUserSetValue(&foodtime2);

lcd_write_com(0x80+0x40+7);

lcd_write_com(0x0f);

}

else if(setn == 10)

{

if(foodtime2.fen==0)

foodtime2.fen=60;

foodtime2.fen--;

displayUserSetValue(&foodtime2);

lcd_write_com(0x80+0x40+10);

lcd_write_com(0x0F);

}

else if(setn == 11)

{

if(foodtime3.shi==0)

foodtime3.shi=24;

foodtime3.shi--;

displayUserSetValue(&foodtime3);

lcd_write_com(0x80+0x40+7);

lcd_write_com(0x0f);

}

else if(setn == 12)

{

if(foodtime3.fen==0)

foodtime3.fen=60;

foodtime3.fen--;

displayUserSetValue(&foodtime3);

lcd_write_com(0x80+0x40+10);

lcd_write_com(0x0F);

}

else if(setn == 13)

{

if(foodtime4.shi==0)

foodtime4.shi=24;

foodtime4.shi--;

displayUserSetValue(&foodtime4);

lcd_write_com(0x80+0x40+7);

lcd_write_com(0x0f);

}

else if(setn == 14)

{

if(foodtime4.fen==0)

foodtime4.fen=60;

foodtime4.fen--;

displayUserSetValue(&foodtime4);

lcd_write_com(0x80+0x40+10);

lcd_write_com(0x0F);

}

else if(setn == 15)

{

if(foodtime5.shi==0)

foodtime5.shi=24;

foodtime5.shi--;

displayUserSetValue(&foodtime5);

lcd_write_com(0x80+0x40+7);

lcd_write_com(0x0f);

}

else if(setn == 16)

{

if(foodtime5.fen==0)

foodtime5.fen=60;

foodtime5.fen--;

displayUserSetValue(&foodtime5);

lcd_write_com(0x80+0x40+10);

lcd_write_com(0x0F);

}

}

}

if(key4 == 0) //手动开

{

delay_ms(10);

if(key4 == 0 )

{

beep = 0;

delay_ms(100);

beep = 1;

while(key4 == 0);

if(setn != 0)

{

setn = 0;

lcd_write_com(0x0c);//关闭光标

lcd_clear();

lcd_write_str(0, 0, " / / ");

lcd_write_str(0, 1, " : : ");

eepromWriteByte(); //退出设置之后,把数据保存一遍

}

else

{

Ul2003_Open();

open_flag=1;

}

}

}

if(key5 == 0) //手动关

{

delay_ms(10);

if(key5 == 0 )

{

beep = 0;

delay_ms(100);

beep = 1;

while(key5 == 0);

if(setn != 0)

{

setn = 0;

lcd_write_com(0x0c);//关闭光标

lcd_clear();

lcd_write_str(0, 0, " / / ");

lcd_write_str(0, 1, " : : ");

eepromWriteByte(); //退出设置之后,把数据保存一遍

}

else

{

Ul2003_Close();

open_flag=0;

}

}

}

}

void main()

{

lcd_init();//1602液晶初始化

eepromInit();

lcd_write_str(0, 0, "00/00/00 ");

lcd_write_str(0, 1, "00:00:00 ClOSE ");

time_init();

while(1)

{

keyscan();//按键扫描

if(setn == 0)

{

Run_DS1302(); //获取时间

if(open_flag==0)lcd_write_str(9, 1, "ClOSE");

else lcd_write_str(9, 1, "OPEN ");

/***************************************************/

/************* 喂食时间到了 ************/

/***************************************************/

if( (foodtime1.shi == hour && foodtime1.fen == min && sec == 0) ||

(foodtime2.shi == hour && foodtime2.fen == min && sec == 0) ||

(foodtime3.shi == hour && foodtime3.fen == min && sec == 0) ||

(foodtime4.shi == hour && foodtime4.fen == min && sec == 0) ||

(foodtime5.shi == hour && foodtime5.fen == min && sec == 0)

)

{

if(feeding_time==0)

{

open_flag=1; //开启喂食标志

Ul2003_Open();

}

feeding_time = 1;

}

}

delay_ms(1);

}

}

五、实验现象

演示视频:

相关推荐
国科安芯43 分钟前
高速CANFD收发器ASM1042在割草机器人轮毂电机通信系统中的适配性研究
网络·单片机·嵌入式硬件·性能优化·机器人·硬件工程
CC呢1 小时前
基于单片机智能路灯控制
单片机·嵌入式硬件·智能路灯
DDUU__1 小时前
STM32低功耗模式
stm32·单片机·嵌入式硬件
逼子格3 小时前
【Protues仿真】基于AT89C52单片机的数码管驱动事例
单片机·嵌入式硬件·硬件工程·硬件工程师·protues·数码管·电路仿真
躲着人群3 小时前
次短路&&P2865 [USACO06NOV] Roadblocks G题解
c语言·数据结构·c++·算法·dijkstra·次短路
風清掦3 小时前
零基础玩转STM32:深入理解ARM Cortex-M内核与寄存器编程
stm32·单片机·嵌入式硬件·mcu·物联网
芯岭技术8 小时前
PY32F003国产单片机、外设丰富、高性价比的国产替代方案
单片机·嵌入式硬件
qq_479875438 小时前
设置接收超时(SO_RCVTIMEO)
c语言·算法
麦麦在写代码9 小时前
内存操作函数
c语言