您的当前位置:首页正文

第21章 单片机远距离通信模块

2020-03-14 来源:易榕旅网


21.2.3单片机与PC机通信模块的的程序设计

sbit RE_DE=P1^0;

unsigned chard_rightframe;//正确数据帧标志

unsigned char P_RS485;//RS485中断接收数据帧的位置

unsigned char idata d_addresscode;//数据帧的地址信息

unsigned char idata d_mandcode[2];//数据帧命令码

unsigned char idata d_databuff[i];//数据帧数据序列

unsigned char idata d_checkdata;//数据帧累加和校验码

unsigned char idata d_end;//数据帧结束符

unsigned char idata d_syscheck;//中断接收程序计算所得到的累加和校验码

sys_initial()

{

TMOD=0x21;//定时器1定义为方式2,定时器0定义为工作方式1

1 / 18

PCON=0x00;//数据传输速率选择

SCON=0x88; //串行口为方式2

ES=1;//允许串行口中断

PS=1;//设置串口中断优先级

TL1=0xE6;

TH1=0xE6;//置初值,对应于2400bit/s的波特率

TR1=1;

EA=1;//打开单片机中断允许

}

receive_isp(void)interrupt4 using3

{

if(RI) //处理接收中断

{

2 / 18

RI=0; //清除中断标志

if(P_RS485==0) //串口接收中断处于接收帧起始字节阶段

{

if(SBUF!==0x02) //是否为有效的帧起始字节

{

P_RS485=0;

}

else

{

P_RS485==1; //串口接收状态标志更新

}

}

else if(P_RS485==1)

3 / 18

{

d_addresscode=SBUF; //保存接收的单片机地址信息

P_RS485=2;

d_syscheck=0x00; //准备进行数据和校验

}

else if(P_RS485==2)

{

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

{ d_mandcode=SBUF; //保存命令码信息

d_syscheck+=d_mandcode; //更新累加和校验信息

}

P_RS485=3;

}

4 / 18

else if(P_RS485==3)

{

for(i=0;i{

d_databuff[i]=SBUF; //保存数据序列信息

d_syscheck+=d_databuff[i]; //更新和校验码

}

P_RS485=4;

}

else if(P_RS485==4)

{

d_checkdata=SBUF; //保存校验码

if(d_syscheck!=d_checkdata) //累加和校验和错误

5 / 18

{

d_rightframe=0; //置数据无效标志

P_RS485=0; //复位RS485接收中断程序状态

}

else

{

P_RS485=5;

}

}

else if(P_RS485==5)

{

d_end=SBUF; //保存结束码

if(d_end!=0x16) //错误的帧结束标志

6 / 18

{

d_rightframe=0; //置数据无效标志

P_RS485=0; //复位RS485接收中断程序状态

}

elseif(d_end==0x16)

{

d_rightframe=1; //置数据有效标志

P_RS485=0; //置RS485接收中断程序状态为0

}

if(TI)

{

TI=0; //处理发送中断

}

7 / 18

}

//延时函数

void delay()

{

unsigned int i;

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

{

}

}

//串口数据发送程序

void send_data()

{

d_checkdata=0x00;//累加和校验码清零

8 / 18

RE_DE=1; //设置MAX485发送状态

SBUF=0x02;//发送帧起始标志

delay(); //延时

SBUF=d_addresscode;//发送单片机地址信息

delay(); //延时

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

{

SBUF=d_mandcode;//发送命令码

d_checkdata+=d_mandcode;//更新累加和校验信息

delay(); //延时

}

for(i=0;i{

9 / 18

SBUF=d_databuff[i];//发送数据序列

d_checkdata+=d_databuff[i];//更新累加和校验信息

delay(); //延时

}

SBUF=d_checkdata;//发送累加和校验码

delay(); //延时

SBUF=0x16;//发送帧结束标志

delay(); //延时

RE_DE=0; //设置MAX485接收状态

}

21.3.3 基于SJA1000的CAN总线通信模块的程序的设计

//SJA1000的各寄存器的地址定义

#define Can_CR 0xE800 //定义控制寄存器地址

10 / 18

#define Can_CMR 0xE801 //定义命令寄存器地址

#define Can_SR 0xE802 //定义状态寄存器地址

#define Can_IR 0xE803 //定义中断寄存器地址

#define Can_ACR 0xE804 //定义验收码寄存器地址

#define Can_AMR 0xE805 //定义验收屏蔽寄存器地址

#define Can_BT0 0xE806 //定义总线定时寄存器0地址

#define Can_BT1 0xE807 //定义总线定时寄存器1地址

#define Can_OCR 0xE808 //定义输出控制寄存器地址

#define Send_Start 0xE80A //定义发送缓冲器的起始地址

#define Receive_Start 0xE814 //定义接收缓冲器的起始地址

#define Can_CLOCK 0xE81F //定义时钟分频寄存器的地址

#define Data_Storeadr 0xE850 //单片机暂存报文的起始地址

//SJA1000的初始化函数

11 / 18

void SJA_Intial()

{

XBYTE[Can_CR]=0x01; //关闭所有中断源,置复位状态

if(XBYTE[Can_CR]&0xFF==1)

{

XBYTE[Can_CLOCK]=0x08; //设置为Basic_CAN模式,CLOCKOFF不输出

XBYTE[Can_ACR]=0x01; //设置验收码为00000001b

XBYTE[Can_AMR]=0xFE; //设置验收屏蔽码,仅最低位为相关位

XBYTE[Can_BT0]=0x00; //设置系统时钟为振荡器时钟的两倍,同步跳转宽度等于系统时钟

XBYTE[Can_BT1]=0x80; //SAM位置高,采用低/中速总线速率

XBYTE[Can_OCR]=0xAA; //设置输出寄存器,使输出方式为正常输出模式

}

XBYTE[Can_CR]=0x1A; //开SJA1000接收中断、超载中断,置系统为正

12 / 18

常运行状态

}

//外部中断0设置

void Int0_Intial()

{

IP=0x00; //优先级设置为0

IT0=0; //设置中断触发方式为低电平触发

EA=1; //中断允许

EX0=1;//开外部中断0

}

//中断接收函数

void Int0_receieve() interrupt 0

{

13 / 18

unsigned char sign,int_receive;

unsigned char data_receive;

unsigned char receive_over;

EA=0; //关中断

sign=XBYTE[Can_IR];

if(sign&0x01==1) //如果该中断信号为接收中断

{

XBYTE[Can_CMR]=0x04; //释放接收缓冲器

XBYTE[Can_CMR]=0x00;

int_receive=1; //置接收中断标志

}

else if(sign&0x02==8) //如果该中断信号为超载中断

{

14 / 18

XBYTE[Can_CMR]=0x08; //清除超载状态

XBYTE[Can_CMR]=0x00;

}

if(int_receive=1) //如果中断接收标志被置位

{

data_receive=XBYTE[Receive_Start];

for(i=0;i<10;i++) //单片机读取接收缓冲器的标识符、RTR位、数据长度码何数据场

{

data_receive=XBYTE[Receive_Start];

XBYTE[Data_Storeadr]=data_receive;

Receive_Start++;

Data_Storeadr++;

}

15 / 18

receive_over=1; //置报文接收完成标志

EA=1; //开中断

}

}

void data_send()

{

unsigned char flag;

unsigned char send_over;

unsigned char data_send;

flag=XBYTE[Can_SR];

if(flag&0x10==16) //判断SR.4位是否为1?

{

if(flag&0x04==4) //判断SR.2位是否为1?

16 / 18

{

for(i=0;i<10;i++) //将数据帧和数据写入发送缓冲器

{

data_send=XBYTE[Send_Start];

XBYTE[Data_Storeadr]=data_send;

Send_Start++;

Data_Storeadr++; //将报文写入发送缓冲器

}

}

}

XBYTE[Can_CMR]=0x01; //置发送请求

if(flag&0x08==8) //判断报文是否完成?

{

17 / 18

send_over=1; //如果完成,置发送完成标志

}

}

18 / 18

因篇幅问题不能全部显示,请点此查看更多更全内容