设计案例介绍
模拟水库自动保值一定蓄水量装置
1.利用单片机与上位机的互相串口通讯、
且拥有最高中断权限保证数据完整
2.设置阈值50%水量少电机抽水速度快正转,
剩余水量多则转速慢若超过50%电机反转泄流
超过80%蜂鸣器报警
3.数码管显示当前水量阈值
4.ON进水开关discharge泄流开关off急停
5.LCD显示状态
中断源及优先级
中断源符号 | 名称 | 中断标志 | 中断引起原因 | 中断号 |
/INT0 | 外部中断0 | IE0 | 低电平或下降沿信号(IT) | 0 |
T0 | 定时器中断0 | TF0 | 定时/计数器0 计数回0溢出 | 1 |
/INT1 | 外部中断1 | IE1 | 低电平或下降沿信号(IT) | 2 |
T1 | 定时器中断1 | TF1 | 定时/计数器1 计数回1溢出 | 3 |
TX/RX | 串行口中断 | TI/RI | 通信完成一帧数据发送或接收 | 4 |
案例硬件设计
案例软件设计
- 上位机
import processing.serial.*;
Serial port;
int speed=0;
int flag=0;//1开
int display=0;//1泄流
int data;//变量存储51传来数据
void setup(){
port=new Serial(this,"COM1",9600); //Arduino板的端口号
size(860,750);
background(255,255,125);
}
void draw(){
//text(50,750,325);
//text(1,750,560);
background(204);
if(port.available()>0)
{
//把51传来的字节存入变量data
data=port.read();
//println(data);
}
textSize(60);
text(data, 0, 50);
RGBDisplay();
frame();
if(flag==1){
if(display==0){
if(speed==-400){speed=-400;}
else{speed=speed-data;}
}
if(display==1){
int a=speed;
if(speed>=-3){speed=speed-data;println(speed);}
if(flag==0){speed=a;}
else{speed=speed+data;}
}
}
float x1=map(speed,0,-400,0,99);
println("wai");
println(speed);
//println(data);
port.write(int(x1));
textSize(50);
fill(0,0,0,100);
text(int(x1),750,100);
text("%",800,100);
fill(0,255,0);
rect(50,600,100,100);
fill(0);
textSize(30);
text("ON",70,660);
fill(0,255,0);
rect(250,600,100,100);
fill(0,0,255);
rect(450,600,100,100);
fill(0);
textSize(25);
text("discharge",450,660);
fill(255,0,0);
rect(650,600,100,100);
fill(0);
textSize(30);
text("OFF",670,660);
}
void frame() //绘制进度条边框函数
{
rectMode(CORNER);
noFill();
stroke(0,0,0);
strokeWeight(2);
rect(50,100,700,400);
}
void RGBDisplay() //绘制进度条函数
{
rectMode(CORNER);
noStroke();
fill(255,0,0);
rect(50,500,700,speed);
}
void mousePressed(){
if((mouseX>=50)&(mouseX<=150)&(mouseY>=600)&(mouseY<=700))
{
flag=1;
display=0;
println("on");
}
else if((mouseX>=650)&(mouseX<=750)&(mouseY>=600)&(mouseY<=700))
{
flag=0;
println("off");
}
else if((mouseX>=450)&(mouseX<=550)&(mouseY>=600)&(mouseY<=700))
{
display=1;
println("discharge");
}
else if((mouseX>=250)&(mouseX<=350)&(mouseY>=600)&(mouseY<=700))
{
speed=0;
println("22");
}
}
单片机1
//接收
#include <reg51.h>//包含头文件reg51.h
sbit led_red=P2^0;
sbit led_green=P2^1;
sbit led_blue=P2^2;
sbit discharge=P2^3;
sbit FM=P2^7;
sbit ee=P2^6;
sbit button=P3^2;
int ount=0;
/*############################初始化############################*/
int val1;
void initinsterrupt0();
int speed=0;
int flag=0;
int count;
/*############################初始化############################*/
/*############################电机设置############################*/
#define uint unsigned int
#define uchar unsigned char
uchar code FFW[]=
{0x01,0x03,0x02,0x06,0x04,0x0c,0x08,0x09};
uchar code REV[]=
{0x09,0x08,0x0c,0x04,0x06,0x02,0x03,0x01};
int step=1;
/*############################电机设置############################*/
uchar i,j;
/*############################数码管定义############################*/
sbit high_bit=P3^6; //定义数码管的高位位选通
sbit low_bit=P3^7; //定义数码管的低位位选通
int num;//定义数码管要显示数字的暂存变量
//段码定义
unsigned char table[]=
{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x83,0xc6,0xa1,0x86,0x8e};//0~F的段码表
void display(int);//显示函数声明
void delayms(unsigned int);//延时函数声明
void LEFT(int speed);
void RIGHT(int speed);
/*############################数码管定义############################*/
int map(float val, float I_Min, float I_Max, float O_Min, float O_Max)
{
return(((val-I_Min)*((O_Max-O_Min)/(I_Max-I_Min)))+O_Min);
}
void LEFT(int speed)
{
uchar i,j;
for(i=0;i<10;i++)
{
for(j=0;j<8;j++)
{
RI=0;//接受完毕一个字符,清零接受中断标志位
val1=SBUF;
num=val1;
if(val1>=80) {led_red=0;led_green=1;led_blue=1;speed=1;}
if(val1>=40&&val1<80) {led_red=1;led_green=0;led_blue=1;speed=10;}
if(val1>=0&&val1<40) {led_red=1;led_green=1;led_blue=0;speed=1;}
SBUF=map(num,150,0,0,3)+0.5;
TI=0;
P1 = FFW[j];
if (num>0&&num<50)break;
display(num);//口相连的数码管显示数字
delayms(speed);
}
}
}
void RIGHT(int speed)
{
uchar i,j;
for(i=0;i<10;i++)
{
for(j=0;j<8;j++)
{
P1 = REV[j];
RI=0;//接受完毕一个字符,清零接受中断标志位
val1=SBUF;
num=val1;
if(val1>=80) {led_red=0;led_green=1;led_blue=1;speed=1;}
if(val1>=40&&val1<80) {led_red=1;led_green=0;led_blue=1;speed=10;}
if(val1>=0&&val1<40) {led_red=1;led_green=1;led_blue=0;speed=1;}
SBUF=map(num,150,0,0,3)+0.5;
TI=0;
if (num>50)break;
display(num);//口相连的数码管显示数字
delayms(speed);
}
}
}
void delay(unsigned int i)
{
unsigned char k,j;
for(j=i;j>0;j--)
for(k=125;k>0;k--);
}
void main()
{
initinsterrupt0(); //中断初始化设置
while (1)
{
int i=0;
while (!RI);
RI=0;//接受完毕一个字符,清零接受中断标志位
val1=SBUF;
num=val1;
while (num>80)
{
ee=0;
FM=0;
delay(10);
FM=1;
delay(5);
display(num);//口相连的数码管显示数字
if(i++>100){break;}
}ee=1;
if(val1>=80) {led_red=0;led_green=1;led_blue=1;speed=1;}
if(val1>=40&&val1<80) {led_red=1;led_green=0;led_blue=1;speed=10;}
if(val1>=0&&val1<40) {led_red=1;led_green=1;led_blue=0;speed=1;}
speed=map(num,150,0,0,3)+0.5;
if(step==1){
num=val1;
if ((num>=0&&num<50))
{
RIGHT(speed);
discharge=1;
}else{
LEFT(speed);
discharge=0;//开启泄流
}
}
while (!TI);
SBUF=map(num,150,0,0,2)+0.5;
TI=0;
}
}
void int0() interrupt 0//开关
{
int i=0;
step=step+1;
ee=0;
if(step>=2)step=0;
while (SBUF>50)
{
FM=0;
delay(10);
FM=1;
delay(5);
display(num);//口相连的数码管显示数字
if(i++>100){break;}
}
}
void initinsterrupt0()
{
TMOD=0x21; //TMOD=0010 0001,定时器1工作为方式2
SCON=0x50;//SCON=0101 0000B,串口工作方式为方式1,允许接受
PCON=0x00;//PCON中的SMOD=0
TH1=0xFD;TL1=0xFD;//波特率为9600b/s
TR1=1;//启动T1,波特率发生器工作
EA=1;
ET0=1;
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
TR0=1;
EX0=1;
IT0=0;
}
void time() interrupt 1
{
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
if(flag==1){
if(--count==0){
flag=0;
}
}
EX0=0;
}
//显示子函数
void display(int num_display)
{
int num_high,num_low;
//把两位十六进制的模数转换结果拆分出低位
num_low=num_display%10;
//把低位数的段码通过P1口送到低位数码管
P0=table[num_low];
low_bit=1;//选通两位数码管的低位
high_bit=0;
delay(10);//延时10ms
low_bit=0;
//把两位十六进制的模数转换结果拆分出高位
num_high=num_display/10;
//把高位数的段码通过P1口送到高位数码管
P0=table[num_high];
high_bit=1;//选通两位数码管的高位
low_bit=0;
delay(10);//延时10ms
high_bit=0;
}
//延时函数
void delayms(unsigned int xms)
{
count=xms;
flag=1;
while (flag);
}
单片机2
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar code table[]=" GOOD ";
uchar code table1[]=" ON ";
sbit lcden=P3^4;
sbit lcdrs=P3^5;
uchar num;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void write_com(uchar com)
{
lcdrs=0;//写命令
P2=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_data(uchar date)
{
lcdrs=1;//写数据
P2=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void init()
{
lcden=0;
write_com(0x38);//初始化
write_com(0x0c);//光标打开
write_com(0x06);
write_com(0x01);
write_com(0x80+0x1);
}
void main()
{
int num;
init();
TMOD=0x21; //TMOD=0010 0001,定时器1工作为方式2
SCON=0x50;//SCON=0101 0000B,串口工作方式为方式1,允许接受
PCON=0x00;//PCON中的SMOD=0
TH1=0xFD;TL1=0xFD;//波特率为9600b/s
TR1=1;//启动T1,波特率发生器工作
EA=1;
while (!RI);
RI=0;//接受完毕一个字符,清零接受中断标志位
num=SBUF;
delay(100);
EA=1;EX0=1;EX1=1;
if(num==1)
{
for(num=0;num<14;num++)//显示"Ying Ming Fei"
{
write_data(table[num]);
delay(20);
}
}else{
for(num=0;num<16;num++)//显示"5071418"
{
write_data(table1[num]);
delay(20);
}
}
}
void int0() interrupt 0
{
for(num=0;num<14;num++)//显示"Ying Ming Fei"
{
write_data(table[num]);
delay(20);
}
// write_com(2);//回车换行
// write_com(0x80+0x40);
// for(num=0;num<16;num++)//显示"5071418"
// {
// write_data(table1[num]);
// delay(20);
// }
}
void int1() interrupt 2
{
write_com(1);//清屏
}
附上程序文件
链接:https://pan.baidu.com/s/1x7nagDCo3NQbTxFClEDvhQ
提取码:md24
--来自百度网盘超级会员V4的分享