本帖最后由 thelaker 于 2010-3-22 11:20 编辑
源程序如下,
#include <w77e58.h>
void SendToCoder1(unsigned char data *Send_Buf); //单片机发送数据给编码器1子程序
void SendToCoder2(unsigned char data *Send_Buf); //单片机发送数据给编码器2子程序
void Main_Init(); //初始化子程序
void WDT_Init(); //看门狗初始化子程序
void WDT_Clr(); //喂狗子程序
void SP0_ISR(); //串口0中断服务子程序
void SP1_ISR(); //串口1中断子服务程序
void TR0_ISR(); //定时器0中断服务子程序
//控制用IO引脚定义与说明
unsigned char idata counter_10us; //10us中断计数,用于判断RS485接收超时
unsigned char idata counter_1ms;
unsigned char idata counter_1s;
unsigned char bdata m_flagData;
sbit b_timerOver=m_flagData^0; //单片机接收超时标志
sbit b_RevRight=m_flagData^1; //单片机接收了一个正确的数据帧标志
sbit RE_DE=P1^0; //RS485接收使能或发送使能控制端
//单片机接收端所用变量的定义与说明
unsigned char code RDCoder1_command_table[5]={0x3D,0x30,0x31,0x3E,0x2B};
//编码器1RS485接口使用变量定义与说明,编码器1地址为01
unsigned char code RDCoder2_command_table[5]={0x3D,0x30,0x32,0x3E,0x2B};
//编码器2的RS485接口使用变量定义与说明,编码器2地址为02
//单片机发送端所用变量的定义与说明
unsigned char data Coder1_address_Send[4]={0x26,0x30,0x31,0x0D};
//编码器1的RS485接口使用变量定义与说明,编码器1地址为01
unsigned char data Coder2_address_Send[4]={0x26,0x30,0x32,0x0D};
//编码器1的RS485接口使用变量定义与说明,编码器2地址为02
unsigned char idata RS485_Status1; //编码器1的RS485接口在接收过程中所处的状态
unsigned char idata RS485_Status2; //编码器2的RS485接口在接收过程中所处的状态
unsigned char idata RS485_Data; //RS485接口所接收的数据
unsigned char idata RS485_Data1Buf[10]; //编码器1的RS485接口所接收的ASCII码数据段
unsigned char idata RS485_Data2Buf[10]; //编码器2的RS485接口所接收的ASCII码数据段
unsigned char idata RS485_Data1[10]; //编码器1的RS485接口所接收的16进制数据段
unsigned char idata RS485_Data2[10]; //编码器2的RS485接口所接收的16进制数据段
unsigned char idata M_Coder1ADDrC; //编码器1地址段计数器
unsigned char idata M_Coder1DataC; //编码器1数据段计数器
unsigned char idata M_Coder2ADDrC; //编码器2地址段计数器
unsigned char idata M_Coder2DataC; //编码器2数据段计数器
//AD转换设置
sbit ST=P3^6;
sbit OE=P3^7;
sbit EOC=P3^2;
sbit CLK=P3^3;
unsigned char data Sensor_Data;
unsigned char data AD_Key_channel="0x78"; //P2.0-P2.2为0,模拟量通道为IN0,P2.3-P2.6为1,按键位初始设置为高电平
//按键设置
unsigned char data Key_data[3];
//DTU发送数据
unsigned char data StartBit[2];
unsigned char data SignBit;
unsigned char data DataLen[2];
unsigned char data DTU_SendData[25];
unsigned char data CheckData;
//定义数据接收发送指示灯
sbit McuToCoder1_Rece=P1^4;
sbit McuToCoder2_Rece=P1^5;
sbit McuToCoder_Tran=P1^6;
sbit DTU_Tran=P1^7;
void Main(void)
{
Main_Init(); //串口初始化
WDT_Init(); //看门狗初始化,启动看门狗
while(1)
{
WDT_Clr();
SendToCoder(Coder1_address_Send); //发送编码器1地址
if(McuToCoder1_Rece==1)
{
Delay7ms();
SendToCoder(Coder2_address_Send); //发送编码器2地址
}
if(McuToCoder2_Rece==1)
{
Sensor_AD(); //称重传感器数据AD转换
Key_Data(); //键盘扫描,得到键值
Delay7ms();
DTU_Send(); //给DTU发送所采集的各编码器、传感器和键盘数据
}
}
}
void Main_Init(void)
{
EA=1; //允许总中断
//定时器0初始化:定时方式
TMOD=0x21; //定时器1工作在模式2,定时器0工作模式1
TH0 =0xFF;
TL0 =0xF3; //定时10us
TR0=1; //启动定时器0
ET0=1; //定时器0中断允许
//串口0设置:用定时器1做串口0的波特率发生器
TL1 =0xFE; //波特率=19200,fosc=16MHz/
TH1 =0xFE;
SCON0=0x50; //工作在模式1,允许接收
PCON =0x00; //SM0=0 SM1=1 在10位异步收发模式 SMOD=0
ES=1; //**串口0中断允许**/
TR1=1; //**启动定时器1**/
PS0=1; //**串口0中断优先**/
PS1=1; //串口1中断优先
//串口1设置:用定时器2做串口1的波特率发生器/
SCON1 =0x50; //**工作在模式1,接收允许**/
T2MOD =0x20; //**定时器2工作在模式1,INT3外部中断/ ??
T2CON =0x30; //**用定时器2做串口1的波特率发生器,波特率=19200**/
RCAP2H=0xFF; //** 设置定时器2**/
RCAP2L=0xE6;
ES1=1; //**串口1中断允许**/
TR2=1; //**启动定时器2**/
//串口指示灯初始化
Coder_Rece=0;;
Coder_Tran=0;;
DTU_Tran=0;;
//AD输入通道和按键I/O口置高电平
P2=AD_Key_channel;
}
//** 函数名称: SP0_ISR() **//
//** 功能描述: 定时器T0中断服务程序 **//
void TR0_ISR() interrupt 1 using 1
{
ET0=0; // 关闭定时器T0中断
TR0=0; //停止定时器T0
CLK=~CLK; //AD转换时钟
counter_10us++; //更新10us计数器
if(counter_10us==100) //如果1s的接收时限结束
{
counter_1ms++;
}
if(counter_1ms==100)
{
counter_1s++;
}
if(counter_1s==10)
{
b_timerOver=1; //设置接收超时标志
counter_10us=0x00; //10us计数器复位
counter_1s=0x00;
counter_1ms=0x00;
}
else
{
TH0=0xFF; //重装定时器T0
TL0=0xF3;
}
}
void SendToCoder(unsigned char data *Send_Buf)
{
unsigned char data i;
Coder_Tran=0;
ES=0;
b_RevRight=0; //数据接收正确标志
RE_DE=1; //设置MAX483进入发送状态
for(i=0,i<4,i++)
{
SBUF=Send_Buf; //逐一发送命令缓冲区的数据
delay();
}
RE_DE=0; //设置MAX483进入接收状态
b_timerOver=0; //复位接收超时标志
counter_10ms=0x00; //复位10ms计数器
ET0=1;
TR0=1;
do
{
if(b_timerOver==1) //如果产生接收超时
{
ET0=0;
TR0=0;
b_timerOver=0;
counter_10ms=0x00;
RE_DE=1;
RS485_Status1=0x00;
b_RevRight=0;
return;
}
}while(b_RevRight!=1)
RE_DE=1;
ES=1;
McuToCoder_Tran=1;
}
void SP0_ISR() interrupt 4 using 2
{
unsigned char i,j,k;
k=0;
Coder_Rece=0;
if(RI==1)
{
RI=0;
RS485_Data=SBUF;
if(RS485_Status1==0x00)
{
if(RS485_Data==RDCoder1_command_table[M_Coder1ADDrC]) //**判断缓冲区数区是否为编码器1数据帧起始位**/
{
M_Coder1ADDrC++;
}
else
{
M_Coder1ADDrC=0x00;
}
if(M_Coder1ADDrC==5)
{
M_Coder1ADDrC=0x00;
RS485_Status1=0x01;
}
}
else if(RS485_Status1==0x01)
{
RS485_Data1Buf[M_Coder1DataC]=Rs485_Data;
M_Coder1DataC++;
if(M_Coder1DataC==0x10)
{
RS485_Status1=0x02;
}
}
else if(RS485_Status1==0x02)
{
if(RS485_Data!=0x0D)
{
M_Coder1ADDrC=0x00;
RS485_Status1==0x00;
}
else
{
b_RevRight=1;
RE_DE=1;//关闭MAX483接收模式,进入发送模式
M_Coder1ADDrC=0x00;
RS485_Status1==0x00;
McuToCoder1_Rece=1;
}
}
if(RS485_Status2==0x00)
{
if(RS485_Data==RDCoder2_command_table[M_Coder2ADDrC]) //**判断缓冲区数区是否为编码器2数据帧起始位**/ {
M_Coder2ADDrC++;
}
else
{
M_Coder2ADDrC=0x00;
}
if(M_Coder2ADDrC==5)
{
M_Coder2ADDrC=0x00;
RS485_Status2=0x01;
}
}
else if(RS485_Status2==0x01)
{
RS485_Data2Buf[M_Coder2DataC]=RS485_Data;
M_Coder2DataC++;
if(M_Coder2DataC==0x10)
{
RS485_Status2=0x02;
}
}
else if(RS485_Status2==0x02)
{
if(RS485_Data!=0x0D)
{
M_Coder2ADDrC=0x00;
RS485_Status2==0x00;
}
else
{
b_RevRight=1;
RE_DE=1;//关闭MAX483接收模式,进入发送模式
M_Coder2ADDrC=0x00;
RS485_Status2==0x00;
McuToCoder2_Rece=1;
}
}
}
if(TI)
{
TI=0;//清除发送标志
}
for(j=0;j<10;j++)
{
RS485_Data1[k]=RS485_Data1Buf[j]-0x30; //将ASCII码数据转为16进制数据
RS485_Data2[k]=RS485_Data2Buf[j]-0x30;
k++;
}
} |