基于can的控制系统中温度节点的程序如下: 包括单片机等的初始化还包括测温部分以及数据的传送, 希望有谁能帮我看一下哪里还有些问题。 #include <reg51.h> #include <absacc.h>
#define uchar unsigned char #define uint unsigned int uchar tplsb,tpmsb; //温度值低位、高位字节 uint Temperature;
unsigned char xdata Reg_CAN_MODE _at_ 0xfd00; //模式寄存器的地址 unsigned char xdata Reg_CAN_CMR _at_ 0xfd01; //命令寄存器 unsigned char xdata Reg_CAN_SR _at_ 0xfd02; //状态寄存 unsigned char xdata Reg_CAN_IR _at_ 0xfd03; //中断寄存器 unsigned char xdata Reg_CAN_IER _at_ 0xfd04; //中断使能寄存器 unsigned char xdata Reg_CAN_BTR0 _at_ 0xfd06; //总线时序寄存器0 unsigned char xdata Reg_CAN_BTR1 _at_ 0xfd07; //总线时序寄存器1 unsigned char xdata Reg_CAN_OCR _at_ 0xfd08; //输出控制寄存器的地址 unsigned char xdata Reg_CAN_TXB[1] _at_ 0xfd10; //标准帧,数据字节长度为2,帧状态,节点号, unsigned char xdata Reg_CAN_AMR[1] _at_ 0xfd14; //验收屏蔽寄存器 unsigned char xdata Reg_CAN_RBSA _at_ 0xfd1e; //接受缓冲器区起始地址寄存器 unsigned char xdata Reg_CAN_CDR _at_ 0xfd1f; //时钟分频寄存器的地址 unsigned char data Data_receive[5]={0x02,0x80,0x10,0x00,0x00}; // 存储收到的信息 unsigned char data Data_send[5]={0x02,0x00,0x10,0x00,0x00}; //can下发数据信息 bit INT=0; sbit DQ=P1^5; //数据通信线 sbit p10=P1^0; sbit connect_ok=P1^1; unsigned char data judge=3;
//检查设备连接标志位 /* sja1000初始化子程序*/ void SJA1000_config_normal(void) { unsigned char xdata *addr; unsigned char i; Reg_CAN_BTR0=0x00; Reg_CAN_BTR1=0x1C; //设置1M波特率 Reg_CAN_MODE=0x01; //进入复位模式 Reg_CAN_IER=0x01; //接受中断使能 Reg_CAN_CDR=0x88; //工作于PeliCAN模式下 Reg_CAN_OCR=0xBA; //TX1下拉,TX0推挽 addr=&Reg_CAN_AMR; for(i=1;i<=4;i++) {*addr=0xff; addr++; } //屏蔽验收滤波器 Reg_CAN_RBSA=0x00; //设置接受缓冲寄存器FIFO的起始地址为0 Reg_CAN_MODE=0x00; //进入工作模式 } /*SJA1000初始化完成*/ /*检查硬件连接*/ void Work_test(void ) { Reg_CAN_TXB[13]=0x11; if(Reg_CAN_TXB[13]==0x11) connect_ok=1; //设备连接正常 else connect_ok=0; } /*硬件检查完成*/
/*读缓冲数据区*/ void CAN_read() interrupt 0 { uint i; for(i=0;i<=4;i++) Reg_CAN_TXB=Data_receive; Reg_CAN_CMR=0x01; INT=1; }
/*接收数据*/ void RS_FROMCAN(void) { uint i; for(i=0;i<=4;i++) Data_send=Reg_CAN_TXB; if(Reg_CAN_TXB[2]==0x01) p10=1; else p10=0; }
//延时函数
void Delay6us(unsigned char delayDSTime) //6us延时 { while(--delayDSTime); } void delay1ms(void) //1ms延时 { unsigned char i,j,k; for(i=5;i>0;i--) for(j=4;j>0;j--) for(k=23;k>0;k--); } void delay1s(void) //1s延时 { unsigned char h,i,j,k; for(h=5;h>0;h--) for(i=4;i>0;i--) for(j=116;j>0;j--) for(k=214;k>0;k--); }
//初始化函数 void Init_DS18B20(void) { uchar x=0; DQ = 1; //DQ复位 Delay6us(8); //稍做延时 DQ = 0; //单片机将DQ拉低 Delay6us(250); //精确延时 大于 480us DQ = 1; //拉高总线 Delay6us(15); x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败 Delay6us(125); }
/*读取数据的一位,满足读时隙要求*/ bit RdBit(void) { uint i; bit b; DQ=0; i++; //保持低至少1us DQ=1; i++; i++; //延时15us以上,读时隙下降沿后15us,DS18B20输出数据才有效 b=DQ; i=8; while(i>0) i--; //读时隙不低于60us return(b); } /*读取数据的第一个字节*/ uchar RdByte(void) { uchar i,j,b; b=0; for(i=1;i<=8;i++) { j=RdBit(); b=(j<<7)|(b>>1); } return(b); }
/*写数据的一个字节,满足写1和写0的实时隙要求*/ void WrByte(uchar b) { uint i; uchar j; bit btmp; for(j=1;j<=8;j++) { btmp=b&0x01; //取下一位(由低位向高位) b=b>>1; //右移 if (btmp) { /*写1*/ DQ=0; i++;i++; //延时,使得15us以内拉高 DQ=1; i=8; while(i>0) i--; //整个写1时隙不低于60us } else { /*写0*/ DQ=0; i=8; while(i>0) i--; //保持的电平在60us到120us之间 DQ=1; i++; i++; } } } /*启动温度转换*/ void convert(void) { Init_DS18B20(); //初始化DS18B20 delay1ms(); //延时1ms WrByte(0xcc); //skip rom命令 WrByte(0x44); //convert T命令 }
/*读取温度值*/ void RdTemp(void) { Init_DS18B20(); //初始化DS18B20 delay1ms(); //延时1ms WrByte(0xcc); //skip rom命令 WrByte(0xbe); //read scratchpad命令 tplsb=RdByte(); //温度值低位字节(其中低4位为二进制的"小数"部分) tpmsb=RdByte(); //温度值高位字节(其中高5位为符号位) }
/*主程序开始*/ void main() { INT=0; tpmsb=Data_receive[4]; tplsb=Data_receive[3]; SJA1000_config_normal() ; //CAN控制器初始化子程序 connect_ok=0; while(connect_ok==0) Work_test(); while(1) while(connect_ok) //CAN控制器准备好则进入主程序 { delay1ms(); //延时1ms convert(); //启动温度转换,需要750ms delay1s(); //延时1s RdTemp(); //读取温度 if(INT) RS_FROMCAN() ; //接收数据 }
} |