标题:
远距离RS485多机通信+LCD显示的单片机源码
[打印本页]
作者:
lostviews
时间:
2018-6-13 17:33
标题:
远距离RS485多机通信+LCD显示的单片机源码
//主机的一部分程序如下
0.png
(45.63 KB, 下载次数: 23)
下载附件
2018-6-14 02:22 上传
单片机源程序如下:
#include <reg51.h>
#include <stdio.h>
#include <string.h>
#include "key.h"
#include "LCD.H"
#include <intrins.h>
unsigned char sendchar[20]; //发送数据数组
unsigned char code table[10]={48,49,50,51,52,53,54,55,56,57}; //字符数组
unsigned char RXDdata[20]; //接收总数据数组
unsigned char save[8]={0,0,0,0,0,0,0,0};
unsigned char count=0; //计数位
unsigned char rx_flag;
sbit RS485E=P3^7; //485使能端
void delay(unsigned char i);
void send_case(); //发送数据存储功能
void main()
{
unsigned char num_counter=0;
unsigned char j=0;
unsigned char i=0;
unsigned char playflag=0; //判断标志位
// unsigned char redata;
unsigned char temdata[10]; //接收温度数据数组
unsigned char anadata1[10]; //接收模拟量1数据数组
unsigned char anadata2[10]; //接收模拟量2数据数组
LCD_Init();
SCON=0x50; //设定串口工作方式
PCON=0x00; //波特率不倍增
TMOD=0x20; //定时器1工作于8位自动重载模式, 用于产生波特率
EA=1;
ES=1; //允许串口中断
TL1=0xe8;
TH1=0xe8; //波特率1200
TR1=1;
RS485E=0;
LCD_WriteStr(2,1,"长春工业大学"); //列8,行4
LCD_WriteStr(3,3,"电气学院");
while(1)
{
KeyValue=0;
KeyDown();
if(KeyValue==34) //接收数据
{
KeyValue=0;
LCD_Clear();
LCD_WriteStr(1,1,"请选择分机");
while(KeyValue==0)
KeyDown();
if(KeyValue==11)
{
LCD_Clear();
LCD_WriteDBC(1,1,save[0]/100+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(2,1,'.');
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(3,1,save[0]/10%10+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(4,1,save[0]%10+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(5,1,save[1]/100+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(6,1,'.');
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(7,1,save[1]/10%10+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(8,1,save[1]%10+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(1,2,save[2]/100+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(2,2,'.');
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(3,2,save[2]/10%10+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(4,2,save[2]%10+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(5,2,save[3]/100+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(6,2,'.');
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(7,2,save[3]/10%10+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(8,2,save[3]%10+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(1,3,save[4]/100+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(2,3,'.');
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(3,3,save[4]/10%10+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(4,3,save[4]%10+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(5,3,save[5]/100+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(6,3,'.');
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(7,3,save[5]/10%10+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(8,3,save[5]%10+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(1,4,save[6]/100+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(2,4,'.');
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(3,4,save[6]/10%10+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(4,4,save[6]%10+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(5,4,save[7]/100+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(6,4,'.');
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(7,4,save[7]/10%10+0x30);
_nop_();
_nop_();
_nop_();
LCD_WriteDBC(8,4,save[7]%10+0x30);
_nop_();
_nop_();
_nop_();
}
if(KeyValue==41) //接收1号分机数据
{
KeyValue=0;
LCD_WriteStr(1,2,"选择1#分机");
ES=0;
RS485E=1;
SBUF=0X11;
while(!TI);
RS485E=0;
TI=0;
ES=1;
LCD_WriteStr(1,3,"#1机故障");
while(count!=14);
for(i=0;i<6;i++)
{
temdata[i]= RXDdata[i];
}
for(i=0;i<4;i++)
{
anadata1[i]=RXDdata[i+6];
}
for(i=0;i<4;i++)
{
anadata2[i]=RXDdata[i+10];
}
LCD_Clear();
LCD_WriteStr(1,1,"当前温度:");
LCD_WriteStr(1,2,temdata);
LCD_WriteStr(1,3,"模拟量1 :");
LCD_WriteStr(6,3,anadata1);
save[0]=(anadata1[0]-0x30)*100+(anadata1[2]-0x30)*10+(anadata1[3]-0x30);
LCD_WriteStr(1,4,"模拟量2 :");
LCD_WriteStr(6,4,anadata2) ;
save[1]=(anadata2[0]-0x30)*100+(anadata2[2]-0x30)*10+(anadata2[3]-0x30);
count=0;
}
if(KeyValue==42)
{
KeyValue=0;
LCD_WriteStr(1,2,"选择2#分机");
ES=0;
RS485E=1;
SBUF=0X12;
while(!TI);
RS485E=0;
TI=0;
ES=1;
LCD_WriteStr(1,3,"#2机故障");
while(count!=14);
for(i=0;i<6;i++)
{
temdata[i]= RXDdata[i];
}
for(i=0;i<4;i++)
{
anadata1[i]=RXDdata[i+6];
}
for(i=0;i<4;i++)
{
anadata2[i]=RXDdata[i+10];
}
LCD_Clear();
LCD_WriteStr(1,1,"当前温度:");
LCD_WriteStr(1,2,temdata);
LCD_WriteStr(1,3,"模拟量1 :");
LCD_WriteStr(6,3,anadata1);
save[2]=(anadata1[0]-0x30)*100+(anadata1[2]-0x30)*10+(anadata1[3]-0x30);
LCD_WriteStr(1,4,"模拟量2 :");
LCD_WriteStr(6,4,anadata2) ;
save[3]=(anadata2[0]-0x30)*100+(anadata2[2]-0x30)*10+(anadata2[3]-0x30);
count=0;
}
if(KeyValue==43)
{
KeyValue=0;
LCD_WriteStr(1,2,"选择3#分机");
ES=0;
RS485E=1;
SBUF=0X13;
while(!TI);
RS485E=0;
TI=0;
ES=1;
LCD_WriteStr(1,3,"#3机故障");
while(count!=14);
for(i=0;i<6;i++)
{
temdata[i]= RXDdata[i];
}
for(i=0;i<4;i++)
{
anadata1[i]=RXDdata[i+6];
}
for(i=0;i<4;i++)
{
anadata2[i]=RXDdata[i+10];
}
LCD_Clear();
LCD_WriteStr(1,1,"当前温度:");
LCD_WriteStr(1,2,temdata);
LCD_WriteStr(1,3,"模拟量1 :");
LCD_WriteStr(6,3,anadata1);
save[4]=(anadata1[0]-0x30)*100+(anadata1[2]-0x30)*10+(anadata1[3]-0x30);
LCD_WriteStr(1,4,"模拟量2 :");
LCD_WriteStr(6,4,anadata2) ;
save[5]=(anadata2[0]-0x30)*100+(anadata2[2]-0x30)*10+(anadata2[3]-0x30);
count=0;
}
if(KeyValue==44)
{
KeyValue=0;
LCD_WriteStr(1,2,"选择4#分机");
ES=0;
RS485E=1;
SBUF=0X14;
while(!TI);
RS485E=0;
TI=0;
ES=1;
LCD_WriteStr(1,3,"#4机故障");
while(count!=14);
for(i=0;i<6;i++)
{
temdata[i]= RXDdata[i];
}
for(i=0;i<4;i++)
{
anadata1[i]=RXDdata[i+6];
}
for(i=0;i<4;i++)
{
anadata2[i]=RXDdata[i+10];
}
LCD_Clear();
LCD_WriteStr(1,1,"当前温度:");
LCD_WriteStr(1,2,temdata);
LCD_WriteStr(1,3,"模拟量1 :");
LCD_WriteStr(6,3,anadata1);
save[6]=(anadata1[0]-0x30)*100+(anadata1[2]-0x30)*10+(anadata1[3]-0x30);
LCD_WriteStr(1,4,"模拟量2 :");
LCD_WriteStr(6,4,anadata2) ;
save[7]=(anadata2[0]-0x30)*100+(anadata2[2]-0x30)*10+(anadata2[3]-0x30);
count=0;
}
}
if(KeyValue==41)
{
LCD_Clear();
LCD_WriteStr(1,1,"1#分机");
LCD_WriteStr(1,2,"请输入8 位data");
sendchar[0]=0x21;
send_case();
}
if(KeyValue==42)
{
LCD_Clear();
LCD_WriteStr(1,1,"2#分机");
LCD_WriteStr(1,2,"请输入8 位data");
sendchar[0]=0x22;
send_case();
}
if(KeyValue==43)
{
LCD_Clear();
LCD_WriteStr(1,1,"3#分机");
LCD_WriteStr(1,2,"请输入8 位data");
sendchar[0]=0x23;
send_case();
}
if(KeyValue==44)
{
LCD_Clear();
LCD_WriteStr(1,1,"4#分机");
LCD_WriteStr(1,2,"请输入8 位data");
sendchar[0]=0x24;
send_case();
}
if(KeyValue==33)
{
RS485E=1;
LCD_WriteStr(3,3,"please wait...");
do
{
SBUF=sendchar[j]; // 发送数据
while(!TI);
TI=0;
j++;
}while(j<9);
j=0;
RS485E=0;
LCD_Clear();
LCD_WriteStr(3,3,"发送成功");
}
}
}
void send_case()
{
unsigned char sendnum;
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
分机源码:
#include <reg52.h>
#include <intrins.h>
#include <math.h>
#include <lcd.h>
#include "ds18b20.h"
#define adc0809_data P1 //模拟量采集总线
sbit sda=P2^0; //IO口定义
sbit scl=P2^1;
bit playflag=0;
sbit ADDA = P3^2;
sbit STR =P3^3; //单片机P3.4接模块STR引脚, 启动转换信号
sbit EOC =P3^5; //单片机P3.5接模块EOC, 转换结束信号,高电平有效
sbit OE =P3^6; //单片机P3.6接模块OE,输出允许信号,高电平有效
sbit RS485=P3^4;
void chushihua(void);
void display(int v);
void play();
void AD(void );
void Conut(void);
void chuanshu(void);
unsigned int tmp;
unsigned char temp,buf,count,counts,mn;
unsigned char datas1[] = {0, 0, 0, 0, 0, 0, 0};
unsigned char data RXDdata[ ] = { 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20};
unsigned char code AD1[] = {"newwendu "}; //显示标准框架
unsigned char code AD2[] = {" "}; //显示标准框架
unsigned char AD_DATA[2]; //保存IN0通道转换后的数据
unsigned char AD_DATA1[14]; //保存IN0通道转换后的数据
unsigned char disbuff[5] ={ 0,0,0,0,0};
unsigned char disbuff1[14];
void nop()
{
_nop_();
_nop_();
}
void delay1(unsigned char m)
{ unsigned int n;
for(n=0;n<m;n++);
}
void init24() //24c02初始化子程序
{
scl=1;
nop();
sda=1;
nop();
}
void start24() //启动I2C总线
{
sda=1;
nop();
scl=1;
nop();
sda=0;
nop();
scl=0;
nop();
}
void stop24() //停止I2C总线
{
sda=0;
nop();
scl=1;
nop();
sda=1;
nop();
}
void writebyte24(unsigned char j) //写一个字节
{
unsigned char i,temp;
temp=j;
for (i=0;i<8;i++)
{
temp=temp<<1;
scl=0;
nop();
sda=CY; //temp左移时,移出的值放入了CY中
nop();
scl=1; //待sda线上的数据稳定后,将scl拉高
nop();
}
scl=0;
nop();
sda=1;
nop();
}
unsigned char readbyte24() //读一个字节
{
unsigned char i,j,k=0;
scl=0; nop(); sda=1;
for (i=0;i<8;i++)
{
nop(); scl=1; nop();
if(sda==1)
j=1;
else
j=0;
k=(k<<1)|j;
scl=0;
}
nop();
return(k);
}
void clock24() //I2C总线时钟
{
unsigned char i=0;
scl=1;
nop();
while((sda==1)&&(i<255))
i++;
scl=0;
nop();
}
////////从24c02的地址address中读取一个字节数据/////
unsigned char read24c02(unsigned char address)
{
unsigned char i;
start24();
writebyte24(0xa0);
clock24();
writebyte24(address);
clock24();
start24();
writebyte24(0xa1);
clock24();
i=readbyte24();
stop24();
delay1(10);
return(i);
}
//////向24c02的address地址中写入一字节数据info/////
void write24c02(unsigned char address,unsigned char info)
{
start24();
writebyte24(0xa0);
clock24();
writebyte24(address);
clock24();
writebyte24(info);
clock24();
stop24();
delay1(50);
}
/**********************************************主函数**********************************************/
void main()
{
unsigned char ff;
init24(); //初始化24C02
sendChangeCmd();
init();
writeComm(0x80);
writeString(AD1,16);
chushihua();
writeComm(0x80);
for(ff=1;ff<9;ff++)
{
writeData(read24c02(ff+1)); //显示字符
delay1(50);
}
while(1)
{
delayMs(1000); //温度转换时间需要750ms以上
writeComm(0xc0);
display(getTmpValue());
play();
AD(); //ADC控制转换
Conut(); //计算---显示
chuanshu();
delayMs(10); //80MS
sendChangeCmd();
}
}
void display(int v)
{
unsigned char count;
unsigned char datas[] = {0, 0, 0, 0, 0,0};
tmp = abs(v);
datas[0] = tmp / 10000; //最高位
datas[1] = tmp % 10000 / 1000; //次高位
datas[2] = tmp % 1000 / 100; //第三位
datas[3] = '.';
datas[4] = tmp % 100 / 10;
datas[5] = tmp % 10;
writeComm(0xc0);
if(v < 0)
{
datas1[0] = '-';
}
else
{
datas1[0] = '+';
}
for(count = 1; count != 6; count++)
{
if(count == 3)
datas1[count] = datas[count];
else
datas1[count] ='0'+datas[count];
}
writeString(datas1, 6);
}
void serial() interrupt 4
{
ES = 0; //关闭串行中断
RI = 0; //清除串行接受标志位
temp = SBUF;
if(counts<9)
{
RXDdata[counts] = temp; //从串口缓冲区取得数据
counts++;
if(counts==9)
{
playflag=1;
}
}
if(temp == 0x14)
{
RS485 = 1;
for(count=0;count<14;count++)
{
SBUF = AD_DATA1[count];
while(!TI);
TI=0;
}
RS485 = 0;
}
ES = 1; //允许串口中断
}
void chushihua(void)
{
SCON=0x50; //设定串口工作方式
PCON=0x00; //波特率不倍增
TMOD=0x20; //定时器1工作于8位自动重载模式, 用于产生波特率
EA=1;
ES = 1; //允许串口中断
TL1=0xe8;
TH1=0xe8; //波特率1200
TR1=1;
RS485=0;
}
/*********************************************************
数据显示函数
*********************************************************/
void play()
{
if(playflag)
{
writeComm(0x80); //设置位置为第1
writeString(AD2, 16);
writeComm(0x80);
for(mn=1;mn<9;mn++)
{
if(RXDdata[0]!=0x24)
break;
writeData(RXDdata[mn]+48); //显示字符
write24c02(mn+1,RXDdata[mn]+48);
delay1(50);
}
playflag=0;
counts=0x00;
}
}
/***********AD转换函数**********/
void AD(void )
{
_nop_();
ADDA=0;
_nop_();
STR=0;
_nop_();
STR=1;
_nop_();
STR=0;
while(0==EOC);
OE=1;
AD_DATA[0]=adc0809_data;
_nop_();
OE=0;
_nop_();
ADDA=1;
_nop_();
STR=0;
_nop_();
STR=1;
_nop_();
STR=0;
while(0==EOC);
OE=1;
AD_DATA[1]=adc0809_data;
_nop_();
OE=0;
}
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
程序.rar
(388.75 KB, 下载次数: 86)
2018-6-13 17:31 上传
点击文件名下载附件
远距离485多机通信+LCD显示
下载积分: 黑币 -5
作者:
admin
时间:
2018-6-14 02:24
能分享下原理图吗?
作者:
bruck
时间:
2019-1-28 00:51
好,谢谢提供~
作者:
rotga
时间:
2019-12-15 20:14
对于多机通讯时从机的地址设定一直不太明白,正好从这个程序中学习学习。谢谢楼主的分享了。
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1