自己做自动喂鱼食和开灯 程序 想加入串口控制 请帮改下

moleboy 2013-12-16 02:11:41
这是程序 在别的基础上改的 ,初学单片机所以不懂请帮助
1。本机实现自动定时开灯喂食功能
现在我想通过串口来控制 例如 串口发送 0x20 BEEP=0 喂食 发送 0x21 停止喂食
发送0x30开灯 发送0x31关灯 我自己加入代码 发送没有反应
2.可以将温度数值 通过串口发送回PC
一下程序:
#include <REG51.H>
#include <intrins.h>
//#include "LCD1602.h"
//#include "DS1302.h"
#define uint unsigned int
#define uchar unsigned char
sbit DS1302_CLK = P1^5; //实时时钟时钟线引脚
sbit DS1302_IO = P1^6; //实时时钟数据线引脚
sbit DS1302_RST = P1^7; //实时时钟复位线引脚
sbit wireless_1 = P3^0;
sbit wireless_2 = P3^1;
sbit wireless_3 = P3^2;
sbit wireless_4 = P3^3;
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,时到日,月,年位闪的计数
sbit Set = P2^0; //模式切换键
sbit Up = P2^1; //加法按钮
sbit Down = P2^2; //减法按钮
sbit out = P2^4; //立刻跳出调整模式按钮
/////////////////////////////
sbit B1 = P2^3;
sbit B2 = P2^1;
sbit B3 = P2^2;
sbit B4 = P2^4;

sbit BEEP = P1^3;
sbit DENG = P1^4;
sbit BEIDENG=P3^6; //2^3
sbit DENGSHI=P3^7; //
void weishi(); //定时喂食 //
void kaideng(); //定时开灯 //
/////////////////////////////

sbit DQ = P3^7; //温度传送数据IO口
char done,count,temp,flag,up_flag,down_flag,TMP,TMP1,TMP2;
uchar temp_value; //温度值
uchar TempBuffer[5],week_value[2];







void show_time(); //液晶显示程序
/***********1602液晶显示部分子程序****************/


//Port Definitions**********************************************************
sbit LcdRs = P1^0;
sbit LcdRw = P1^1;
sbit LcdEn = P1^2;
sfr DBPort = 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口

//内部等待函数**************************************************************************
unsigned char LCD_Wait(void)
{
LcdRs=0;
LcdRw=1; _nop_();
LcdEn=1; _nop_();

LcdEn=0;
return DBPort;
}
//向LCD写入命令或数据************************************************************
#define LCD_COMMAND 0 // Command
#define LCD_DATA 1 // Data
#define LCD_CLEAR_SCREEN 0x01 // 清屏
#define LCD_HOMING 0x02 // 光标返回原点
void LCD_Write(bit style, unsigned char input)
{
LcdEn=0;
LcdRs=style;
LcdRw=0; _nop_();
DBPort=input; _nop_();//注意顺序
LcdEn=1; _nop_();//注意顺序
LcdEn=0; _nop_();
LCD_Wait();
}

//设置显示模式************************************************************
#define LCD_SHOW 0x04 //显示开
#define LCD_HIDE 0x00 //显示关

#define LCD_CURSOR 0x02 //显示光标
#define LCD_NO_CURSOR 0x00 //无光标

#define LCD_FLASH 0x01 //光标闪动
#define LCD_NO_FLASH 0x00 //光标不闪动

void LCD_SetDisplay(unsigned char DisplayMode)
{
LCD_Write(LCD_COMMAND, 0x08|DisplayMode);
}

//设置输入模式************************************************************
#define LCD_AC_UP 0x02
#define LCD_AC_DOWN 0x00 // default

#define LCD_MOVE 0x01 // 画面可平移
#define LCD_NO_MOVE 0x00 //default

void LCD_SetInput(unsigned char InputMode)
{
LCD_Write(LCD_COMMAND, 0x04|InputMode);
}

//初始化LCD************************************************************
void LCD_Initial()
{
LcdEn=0;
LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵
LCD_Write(LCD_COMMAND,0x38);
LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标
LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏
LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动
}

//液晶字符输入的位置************************
void GotoXY(unsigned char x, unsigned char y)
{
if(y==0)
LCD_Write(LCD_COMMAND,0x80|x);
if(y==1)
LCD_Write(LCD_COMMAND,0x80|(x-0x40));
}

//将字符输出到液晶显示
void Print(unsigned char *str)
{
while(*str!='\0')
{
LCD_Write(LCD_DATA,*str);
str++;
}
}






/***********DS1302时钟部分子程序******************/
typedef struct __SYSTEMTIME__
{
unsigned char Second;
unsigned char Minute;
unsigned char Hour;
unsigned char Week;
unsigned char Day;
unsigned char Month;
unsigned char Year;
unsigned char DateString[11];
unsigned char TimeString[9];
}SYSTEMTIME; //定义的时间类型
SYSTEMTIME CurrentTime;


#define AM(X) X
#define PM(X) (X+12) // 转成24小时制
#define DS1302_SECOND 0x80 //时钟芯片的寄存器位置,存放时间
#define DS1302_MINUTE 0x82
#define DS1302_HOUR 0x84
#define DS1302_WEEK 0x8A
#define DS1302_DAY 0x86
#define DS1302_MONTH 0x88
#define DS1302_YEAR 0x8C

void DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数)
{
unsigned char i;
ACC = d;
for(i=8; i>0; i--)
{
DS1302_IO = ACC0; //相当于汇编中的 RRC
DS1302_CLK = 1;
DS1302_CLK = 0;
ACC = ACC >> 1;
}
}

unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数)
{
unsigned char i;
for(i=8; i>0; i--)
{
ACC = ACC >>1; //相当于汇编中的 RRC
ACC7 = DS1302_IO;
DS1302_CLK = 1;
DS1302_CLK = 0;
}
return(ACC);
}

void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据
{
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302InputByte(ucAddr); // 地址,命令
DS1302InputByte(ucDa); // 写1Byte数据
DS1302_CLK = 1;
DS1302_RST = 0;
}

unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据
{
unsigned char ucData;
DS1302_RST = 0;
DS1302_CLK = 0;
DS1302_RST = 1;
DS1302InputByte(ucAddr|0x01); // 地址,命令
ucData = DS1302OutputByte(); // 读1Byte数据
DS1302_CLK = 1;
DS1302_RST = 0;
return(ucData);
}



void DS1302_GetTime(SYSTEMTIME *Time) //获取时钟芯片的时钟数据到自定义的结构型数组
{
unsigned char ReadValue;
ReadValue = Read1302(DS1302_SECOND);
Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_MINUTE);
Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_HOUR);
Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_DAY);
Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_WEEK);
Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_MONTH);
Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
ReadValue = Read1302(DS1302_YEAR);
Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);
}

void DateToStr(SYSTEMTIME *Time) //将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]
{ if(hide_year<2) //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为 2007/07/22
{
Time->DateString[0] = '2';
Time->DateString[1] = '0';
Time->DateString[2] = Time->Year/10 + '0';
Time->DateString[3] = Time->Year%10 + '0';
}
else
{
Time->DateString[0] = ' ';
Time->DateString[1] = ' ';
Time->DateString[2] = ' ';
Time->DateString[3] = ' ';
}
Time->DateString[4] = '-';
if(hide_month<2)
{
Time->DateString[5] = Time->Month/10 + '0';
Time->DateString[6] = Time->Month%10 + '0';
}
else
{
Time->DateString[5] = ' ';
Time->DateString[6] = ' ';
}
Time->DateString[7] = '-';
if(hide_day<2)
{
Time->DateString[8] = Time->Day/10 + '0';
Time->DateString[9] = Time->Day%10 + '0';
}
else
{
Time->DateString[8] = ' ';
Time->DateString[9] = ' ';
}
if(hide_week<2)
{
week_value[0] = Time->Week%10 + '0'; //星期的数据另外放到 week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示
}
else
{
week_value[0] = ' ';
}
week_value[1] = '\0';

Time->DateString[10] = '\0'; //字符串末尾加 '\0' ,判断结束字符
}

void TimeToStr(SYSTEMTIME *Time) //将时,分,秒数据转换成液晶显示字符放到数组 TimeString[];
{ if(hide_hour<2)
{
Time->TimeString[0] = Time->Hour/10 + '0';
Time->TimeString[1] = Time->Hour%10 + '0';
}
else
{
Time->TimeString[0] = ' ';
Time->TimeString[1] = ' ';
}
Time->TimeString[2] = ':';
if(hide_min<2)
{
Time->TimeString[3] = Time->Minute/10 + '0';
Time->TimeString[4] = Time->Minute%10 + '0';
}
else
{
Time->TimeString[3] = ' ';
Time->TimeString[4] = ' ';
}
Time->TimeString[5] = ':';
if(hide_sec<2)
{
Time->TimeString[6] = Time->Second/10 + '0';
Time->TimeString[7] = Time->Second%10 + '0';
}
else
{
Time->TimeString[6] = ' ';
Time->TimeString[7] = ' ';
}
Time->DateString[8] = '\0';
}


...全文
164 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
moleboy 2013-12-18
  • 打赏
  • 举报
回复
请帮助一下 各位大侠 光串口是没问题的 但是加到我的程序就完蛋了!
moleboy 2013-12-17
  • 打赏
  • 举报
回复
在程序中增加 void timer0(void) interrupt 1 {TH0=0x3c; TL0=0xb0; while(!RI); RI=0; m=SBUF; SBUF=m; while(!TI); TI=0; } main里面增加: TMOD=0x20; TH1=0xfd; TL1=0xfd; PCON=0x00; SCON=0x50; TR1=1; 但是 无用没有返回串口数据 应该怎么改?
moleboy 2013-12-17
  • 打赏
  • 举报
回复
能给个代码吗?我初学者就是做个制作 也就是爱好而已 改改 自己用来控制鱼缸 这边吗、玩电脑那边就能控制喂食 不是很拽!
vc8fans 2013-12-17
  • 打赏
  • 举报
回复
太长,粗看了一下,想通过上位机串口发指令给51并控制,,这个时候串口必须得用中断,因为你的温度等控制占了很多CPU时间且51本身很慢,, 我在while(done=1)或while(1) 里面加了 dat=subf 之类的 想法在STM32高速 CPU中完全没有问题,51不行, 所以你必须加个中断来处理串口接收问题,
moleboy 2013-12-16
  • 打赏
  • 举报
回复
不用看程序 我就是在上面加个串口通信。 我在while(done=1)或while(1) 里面加了 dat=subf 之类的 但是串口就是没有信息 或得不到信息
vc8fans 2013-12-16
  • 打赏
  • 举报
回复
太长了,,,看得眼睛都花
moleboy 2013-12-16
  • 打赏
  • 举报
回复
void Initial_DS1302(void) //时钟芯片初始化 { unsigned char Second=Read1302(DS1302_SECOND); if(Second&0x80) //判断时钟芯片是否关闭 { Write1302(0x8e,0x00); //写入允许 Write1302(0x8c,0x07); //以下写入初始化时间 日期:07/07/25.星期: 3. 时间: 23:59:55 Write1302(0x88,0x07); Write1302(0x86,0x25); Write1302(0x8a,0x07); Write1302(0x84,0x23); Write1302(0x82,0x59); Write1302(0x80,0x55); Write1302(0x8e,0x80); //禁止写入 } } /***********ds18b20子程序*************************/ /***********ds18b20延迟子函数(晶振12MHz )*******/ void delay_18B20(unsigned int i) { while(i--); } /**********ds18b20初始化函数**********************/ void Init_DS18B20(void) { unsigned char x=0; DQ = 1; //DQ复位 delay_18B20(8); //稍做延时 DQ = 0; //单片机将DQ拉低 delay_18B20(80); //精确延时 大于 480us DQ = 1; //拉高总线 delay_18B20(14); x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败 delay_18B20(20); } /***********ds18b20读一个字节**************/ unsigned char ReadOneChar(void) { uchar i=0; uchar dat = 0; for (i=8;i>0;i--) { DQ = 0; // 给脉冲信号 dat>>=1; DQ = 1; // 给脉冲信号 if(DQ) dat|=0x80; delay_18B20(4); } return(dat); } /*************ds18b20写一个字节****************/ void WriteOneChar(uchar dat) { unsigned char i=0; for (i=8; i>0; i--) { DQ = 0; DQ = dat&0x01; delay_18B20(5); DQ = 1; dat>>=1; } } /**************读取ds18b20当前温度************/ void ReadTemp(void) { unsigned char a=0; unsigned char b=0; unsigned char t=0; Init_DS18B20(); WriteOneChar(0xCC); // 跳过读序号列号的操作 WriteOneChar(0x44); // 启动温度转换 delay_18B20(100); // this message is wery important Init_DS18B20(); WriteOneChar(0xCC); //跳过读序号列号的操作 WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度 delay_18B20(100); a=ReadOneChar(); //读取温度值低位 b=ReadOneChar(); //读取温度值高位 temp_value=b<<4; temp_value+=(a&0xf0)>>4; } void temp_to_str() //温度数据转换成液晶字符显示 { TempBuffer[0]=temp_value/10+'0'; //十位 TempBuffer[1]=temp_value%10+'0'; //个位 TempBuffer[2]=0xdf; //温度符号 TempBuffer[3]='C'; TempBuffer[4]='\0'; } void Delay1ms(unsigned int count) { unsigned int i,j; for(i=0;i<count;i++) for(j=0;j<120;j++); } /*延时子程序*/ void mdelay(uint delay) { uint i; for(;delay>0;delay--) {for(i=0;i<62;i++) //1ms延时. {;} } } void outkey() //跳出调整模式,返回默认显示 { uchar Second; if(out==0||wireless_1==1) { mdelay(8); count=0; hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_month=0,hide_year=0; Second=Read1302(DS1302_SECOND); Write1302(0x8e,0x00); //写入允许 Write1302(0x80,Second&0x7f); Write1302(0x8E,0x80); //禁止写入 done=0; while(out==0); while(wireless_1==1); } } void show_time() //液晶显示程序 { DS1302_GetTime(¤tTime); //获取时钟芯片的时间数据 TimeToStr(¤tTime); //时间数据转换液晶字符 DateToStr(¤tTime); //日期数据转换液晶字符 ReadTemp(); //开启温度采集程序 temp_to_str(); //温度数据转换成液晶字符 GotoXY(11,1); //液晶字符显示位置 Print(TempBuffer); //显示温度 GotoXY(0,1); Print(CurrentTime.TimeString); //显示时间 GotoXY(0,0); Print(CurrentTime.DateString); //显示日期 // GotoXY(15,0); //Print(week_value); //显示星期 //Print("0"); GotoXY(11,0); Print("APM:"); //在液晶上显示 字母 week weishi(); kaideng(); Delay1ms(400); //扫描延时 } main() { LCD_Initial(); //液晶初始化 BEIDENG=0; Delay1ms(400); GotoXY(1,0); Print("Now Loading...."); Delay1ms(50000); GotoXY(10,0); Print(" "); GotoXY(15,0); Print(" "); TMP2=0; BEEP==0; DENG==0; BEIDENG=0; //开液晶屏背灯BEIDENG=0; flag=1; //时钟停止标志 LCD_Initial(); //液晶初始化 Init_DS18B20( ) ; //DS18B20初始化 Initial_DS1302(); //时钟芯片初始化 up_flag=0; down_flag=0; done=0; //进入默认液晶显示 wireless_1=0; wireless_2=0; wireless_3=0; wireless_4=0; while(1) { while(done==1) keydone(); //进入调整模式 while(done==0) { show_time(); //液晶显示数据 flag=0; Setkey(); //扫描各功能键 TMP=Read1302(DS1302_SECOND); if(B1==0&BEEP==1) //手动喂食 { BEEP=0; // BEIDENG=0; Delay1ms(10000); BEEP=1; // BEIDENG=1; } if(B2==0&DENG==1) //手动开灯 {DENG=0;Delay1ms(300); } if(B2==0&DENG==0) //手动关灯 {DENG=1;Delay1ms(300); } if(B3==0&BEIDENG==1) //手动开背灯 {BEIDENG=0;Delay1ms(300);} if(B3==0&BEIDENG==0) //手动关背灯 {BEIDENG=1;Delay1ms(300);} } } } void weishi() { //--------------------- 开始喂食1---------------- temp=Read1302(DS1302_HOUR); //读取小时数 if (temp==0x09) { temp=Read1302(DS1302_MINUTE); //读取分钟数 if (temp==0x10) { temp=Read1302(DS1302_SECOND); //读取秒钟数 if (temp==0x00) { BEEP=0; } } } temp=Read1302(DS1302_HOUR); //读取小时数 if (temp==0x09) { temp=Read1302(DS1302_MINUTE); //读取分钟数 if (temp==0x10) { temp=Read1302(DS1302_SECOND); //读取秒钟数 if (temp>0x15) { BEEP=1; GotoXY(15,0); Print("1"); } } } //--------------------- 开始喂食2---------------- temp=Read1302(DS1302_HOUR); //读取小时数 if (temp==0x17) { temp=Read1302(DS1302_MINUTE); //读取分钟数 if (temp==0x00) { temp=Read1302(DS1302_SECOND); //读取秒钟数 if (temp==0x00) { BEEP=0; } } } temp=Read1302(DS1302_HOUR); //读取小时数 if (temp==0x17) { temp=Read1302(DS1302_MINUTE); //读取分钟数 if (temp==0x00) { temp=Read1302(DS1302_SECOND); //读取分钟数 if (temp>0x15) { BEEP=1; GotoXY(15,0); Print("2"); } } } } void kaideng() { //--------------------- 开灯1---------------- temp=Read1302(DS1302_HOUR); //读取小时数 if (temp==0x16) { temp=Read1302(DS1302_MINUTE); //读取分钟数 if (temp==0x20) { temp=Read1302(DS1302_SECOND); //读取秒钟数 if (temp==0x00) { DENG=0; } } } temp=Read1302(DS1302_HOUR); //读取小时数 if (temp==0x21) { temp=Read1302(DS1302_MINUTE); //读取分钟数 if (temp==0x15) { temp=Read1302(DS1302_SECOND); //读取分钟数 if (temp>0x01) { DENG=1; GotoXY(15,0); Print("3"); } } } } //===================================

27,375

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧