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 因篇幅问题不能全部显示,请点此查看更多更全内容