📄 485-slave2.c
字号:
/*--------RS485通信程序从机部分----------*/
#include<reg52.h>
#include<string.h>
#define uchar unsigned char
#define uint unsigned int
#define comm 0 //液晶命令
#define dat 1 //液晶数据
/* 以下为程序协议中使用的握手信号 */
#define __SUCC_ 0x0f // 数据传送成功
#define __ERR_ 0xf0 // 数据传送错误
#define __RDY_ 0x06 // 主机开始通信时发送的呼叫信号
#define __BUSY_ 0x15 // 从机忙应答
#define __OK_ 0x00 // 从机准备好
/*以下为所用的从机地址 */
#define addr1 0x01
#define addr2 0x02
sbit cs_lcd = P2^7;
sbit std = P2^6;
sbit sclk = P2^5;
sbit re_de = P3^7;
void init_serial(); // 串口初始化
unsigned char recv_data(unsigned char *buf); // 接收数据
void wr_lcd (uchar dat_comm,uchar content); //向液晶写数据
void chn_disp (uchar code *chn,uint k);
void delay (uint us);
uchar buf[16];
uchar code tab1[]={"开始接收"};
uchar code tab2[]={"收到命令"};
uchar code tab3[]={"好数据"};
/*------------------初始化液晶-----------------*/
void init_lcd (void)
{
wr_lcd (comm,0x30); /*30---基本指令动作*/
wr_lcd (comm,0x01); /*清屏,地址指针指向00H*/
delay (100);
wr_lcd (comm,0x06); /*光标的移动方向*/
wr_lcd (comm,0x0c); /*开显示,关游标*/
}
/*------------------向LCD发送数据-------------------*/
void wr_lcd (uchar dat_comm,uchar content)
{
uchar a,i,j;
delay (50);
a=content;
cs_lcd=1;
sclk=0;
std=1;
for(i=0;i<5;i++)
{
sclk=1;
sclk=0;
}
std=0;
sclk=1;
sclk=0;
if(dat_comm)
std=1; //data
else
std=0; //command
sclk=1;
sclk=0;
std=0;
sclk=1;
sclk=0;
for(j=0;j<2;j++)
{
for(i=0;i<4;i++)
{
a=a<<1;
std=CY;
sclk=1;
sclk=0;
}
std=0;
for(i=0;i<4;i++)
{
sclk=1;
sclk=0;
}
}
}
/*--------------清DDRAM------------------*/
void clrram (void)
{
wr_lcd (comm,0x30);
wr_lcd (comm,0x01);
delay (180);
}
/*-----------------------------------*/
void delay (uint us) //delay time 微妙
{
while(us--);
}
/*---------------显示汉字或字符----------------*/
void chn_disp (uchar code *chn,uint k)
{
uchar i;
wr_lcd (comm,0x30);
wr_lcd (comm,0x80);
for (i=0;i<k;i++)
wr_lcd (dat,chn[i]);
}
/* 初始化串口 */
void init_serial()
{
TMOD = 0x20; //定时器T1使用工作方式2
TH1 = 250; // 设置初值
TL1 = 250;
TR1 = 1; // 开始计时
PCON =0x00; // 0x80; // SMOD = 1
SCON = 0x50; //0xd0; //工作方式3,9位数据位,波特率9600bps,允许接收
// re_de=0; //485允许接受
}
/* 接收数据,注意该函数使用buf指向的缓冲区保存数据,在数据末尾使用'\0'表示数据结束
返回值为0,数据校验成功,返回值为0xfe,接受过程中接收到地址帧,返回值为0xff,数据校验失败*/
unsigned char recv_data(unsigned char *buf)
{
//unsigned char len; // 该字节用于保存数据长度
//unsigned char ecc; // 该字节用于保存校验字节
unsigned char i,tmp;
/* 接收数据长度 */
//RI = 0;
//while(!RI);
//if(RB8 == 1) // 若当前接收为地址帧则返回0xfe
// return 0xfe;
//len = SBUF;
RI = 0;
/* 使用len的值为校验字节ecc赋初值 */
//ecc = len;
/* 接收数据 */
for(i=0; i<16; i++)
{
while(!RI);
// if(RB8 == 1) // 若当前接收为地址帧则返回0xfe
// return 0xfe;
*buf[i] = SBUF; // 接收数据
//ecc = ecc^(*buf); // 进行字节校验
RI = 0;
buf++;
}
//*buf = 0; // 表示数据结束
/* 接收校验字节 */
//while(!RI);
//if(RB8 == 1) // 若当前接收为地址帧则返回0xfe
// return 0xfe;
//tmp = SBUF;
//RI = 0;
/* 进行数据校验 */
//ecc = tmp^ecc;
//if(ecc != 0) // 校验失败
//{
// *(buf-len) = 0; // 清空数据缓冲区
// TI = 0; // 发送校验失败信号
// TB8 = 0;
// SBUF = __ERR_;
// while(!TI);
// TI = 0;
// return 0xff; // 返回0xff表示校验错误
//}
TI = 0; // 校验成功
TB8 = 0;
SBUF = __SUCC_;
while(!TI);
TI = 0;
return 0; // 校验成功,返回0
}
/*------------主程序---------------*/
void main()
{
unsigned char i = 0;
unsigned char tmp = 0xff;
unsigned char addr; // 保存本机地址
addr =addr1; /*读取本机地址 */
cs_lcd=1;
SP=0x5f;
/* 串口初始化 */
init_serial(); // 初始化串口
EA = 0; // 关闭所有中断
init_lcd (); //初始化液晶
chn_disp (tab1,8);
/* 进入设备应答阶段 */
while(1)
{
//SM2 = 1; // 只接收地址帧
/* 如果接收到的地址帧不是本机地址,则继续等待 */
//tmp = addr-1;
while(tmp !=__RDY_)
{
RI = 0;
while(!RI);
tmp = SBUF;
RI = 0;
}
wr_lcd (comm,0x86);
chn_disp (tab2,8);
/* 发送应答信号,并做好接收数据的准备 */
TI = 0;
//TB8 = 0; // 主机不检测该位
SBUF =__OK_;
while(!TI);
TI = 0;
chn_disp (tab3,6);
//SM2 = 0; // 允许接收数据信息
/* 数据接收 */
tmp = 0xff;
while(tmp == 0xff) // 如果数据校验失败则重新接收数据
{
tmp = recv_data(buf); // 校验失败返回0xff,检测到地址帧则返回0xfe,接收成功则返回0
}
if(tmp == 0xfe) // 在数据接收过程中,如果发现地址帧,则重新开始整个接收过程
continue;
wr_lcd (comm,0x90); //置显示位置
chn_disp (buf,16) ; //显示表示数据接收成功
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -