当前位置:文档之家› MCS-51微机接口大作业

MCS-51微机接口大作业

《微机接口技术》大作业作业要求:设计一外部设备监控系统,采用CPU为51系列单片机,用C51或ASM51编写软件,给出SCH原理图和软件清单(要求有功能注释),系统要求如下:①系统带有电子时钟,2路模拟量和8路数字量的检测;②4个按键,分别为设置、+、-、->可以可以完成相应的设置过程(包括时间设置和外部监控值的上下限设置);③采用I2C 8583时钟芯片(可以查相关资料);④8个8段LED显示(可以采用SPI总线芯片7219)以辅助完成设置,显示内容:时-分-秒;⑤8个按键分别可以模拟外部8个故障点;⑥2路电位器可以模拟外部模拟信号;⑦EEPROM(I2C总线芯片24c256)保存最近100个外部故障数据(包含故障点和故障时间);⑧RS485上位机接口。

系统软件完成的功能:①上电时电子钟方式显示当前时间;②设置按键进入设置状态,可以重新设置新时间值和外部监控值的上下限,结果写入8583。

设置完成后电子钟方式显示当前时间;③实时监测外部8个数字故障点和模拟数字,一旦故障记录其故障数据、故障发生时间和恢复时间;④上位机传来命令字0xaa向上位机发送所保存的外部故障数据,发送完成后清除保存数据。

(自定义通讯协议)。

一、元器件选择芯片名称型号接口类型线数其它AD转换芯片TLC1549 SPI 3 2块共阴极数码管显示驱动器MAX7219 SPI 3时钟芯片PCF8583 I2C 2EPROM 24WC256 I2C 2串口RS485 MAX487E 3二、MCS-51单片机引脚连接单片机I/O 引脚外部器件连接及功用器件名称引脚代号功用P0^0 SW1 按钮1,模拟外部故障点1P0^1 SW2 按钮2,模拟外部故障点2P0^2 SW3 按钮3,模拟外部故障点3P0^3 SW4 按钮4,模拟外部故障点4P0^4 SW5 按钮5,模拟外部故障点5P0^5 SW6 按钮6,模拟外部故障点6P0^6 SW7 按钮7,模拟外部故障点7P0^7 SW8 按钮8,模拟外部故障点8P1^0 MAX7219 DIN 数码管显示串行数据输入端P1^1 MAX7219 LOAD 数码管显示数据锁存端P1^2 MAX7219 CLK 数码管显示时钟输入端P1^3 --- --- ---P1^4 SPI/TLC1549 CS 模拟SPI片选信号P1^5 SP I/TLC1549 DA TA OUT 模拟SPI数据传送位P1^6 SP I/TLC1549 CLK 模拟SPI时钟控制位P1^7 --- --- ---P2^0 --- --- ---P2^1 SW9 按钮9,系统参数“设置”键P2^2 SW10 按钮10,系统参数增加“+”键P2^3 SW11 按钮11,系统参数减小“-”键P2^4 SW12 按钮12,系统参数项目选择“->”键P2^5 --- --- ---P2^6 MAX487E DE 485串口通信P2^7 MAX487E RE 485串口通信P3^0/RXD MAX487E RXD 485串口通信P3^1/TXD MAX487E TXD 485串口通信P3^2/INT0 PCF8583 INTP3^3/INT1 --- --- ---P3^4/T0 --- --- ---P3^5/T1 --- --- ---P3^6/WR I2C总线SCL 模拟I2C时钟控制位P3^7/RD I2C总线SDA 模拟I2C数据传送位1.I2C器件接线图2.功能按键设置接线图3.AD转换器件接线图4.数码管显示驱动接线图5.485串口接线电路6.单片机复位与外部时钟电路四、软件程序清单1.延时程序:void delay(void);2.启动I2C总线:void I_start(void);3.停止I2C总线:void I_stop(void);4.初始化I2C总线:void I_int(void);5.提供时钟信号,并返回时钟为高电平时SDA的状态:bit I_clock(void);6.向SDA发送一个字节,并检验应答信号:bit I_send(uchar I_data);7.从SDA上读取8位数据信号,并作为一个数据信号返回:byte I_receive(void);8.发送应答信号:void I_ack(void);9.毫秒级延时程序:void delay_ms(int n);10.向8583时钟芯片内指定地址写入数据,并检验应答信号,成功则返回TRUE,否则返回FAULSE:bit Write_8583(uchar Address,uchar data1);11.从8583时钟芯片指定地址读出数据,如成功读取,则发送应答信号,并返回TRUE,否则返回FAULSE:uchar Read_8583(uchar Address);12.初始化8583时钟芯片,预输入时间:void init_8583(void);13.向7219指定地址写入数据:void Write_7219(uchar Address,uchar Data);14.MAX7219初始化:void init_7219(void);15.设置时间和监控值:void set(void);16.向24c256写入器件地址和一个指定的字节地址:bit E_address(uchar Address1,uchar Address2);17.从24c256内地址0开始读出BLOCKSIZE个字节的数据:bit E_read(void);18.向24c256写入数据:bit E_write(uchar data1);19.故障点产生故障时写入24c256:void failure(void);20.将模拟量通过TLC1549转换成数字量:uint TLC1549(void);21.初始化:void init(void);22.接受主机指令:bit Recv_Data(uchar *type);23.发送单字节数据:void Send(uchar m);24.发送数据:void Send_Data(uchar type,uchar len,uchar *buf);25.主函数:void main(void)。

五、主要子函数源程序1.函数变量及端口定义#define HIGH 1#define LOW 0#define TRUE 1#define FAULSE 0#define byte unsigned int#define uchar unsigned char#define uint unsigned int#define WRITE 0xA0 //8583写#define READ 0xA1 //8583读#define WRITE1 0xA2 //7219写#define READ1 0xA3 //7219读#define BLOCKSIZE 700#define ACTIVE 0x11 //4种帧的定义#define GETDATA 0xaa#define READY 0x33#define SENDDATA 0x44#define RECFRMMAXLEN 16 //接受帧的最大长度,超过此值认为帧超长错误#define STATUSMAXLEN 700 //设备状态信息最大长度extern xdata uchar StatusBuf[STATUSMAXLEN]; //设备状态信息缓冲区extern xdata byte EEPROM[BLOCKSIZE];extern xdata byte address1_256=0x00; //24c256的写入地址extern xdata byte address2_256=0x00;extern xdata uchar run=0; //run为设置状态extern xdata uchar time; //从8583读取的时间值bit key_flg=0; //key_flg=0无按键,key_flg=1有按键bit transfer_flg=0; //transfer_flg=0无移位键按下,transfer_flg=1有移位键按下extern xdata byte keyvalue; //keyvalue值代表按键extern xdata byte number[]={0x02,0x03,0x04}; //存放时间的8583内部地址extern xdata byte tran=0; //记录移位键extern xdata byte max=0x40; //max为外部监控值的上限extern xdata byte min=0x10; //min为外部监控值的下限uchar DevNo; //设备号sbit set_time=P2^1; //时间设置键接口sbit add_time=P2^2;sbit minus_time=P2^3;sbit transfer_time=P2^4;sbit SCL=P3^7; //I2C总线sbit SDA=P3^6;sbit DIN=P1^0; //SPI总线sbit CLK=P1^2;sbit LOAD=P1^1;sbit CS_AD1549 =P1^4; //AD转换SPI总线sbit CLK_AD_DA =P1^6;sbit DIO_AD_DA =P1^5;sbit DE=P2^6; //驱动器使能,1有效sbit RE=P2^7; //接收器使能,0有效sbit failure1=P0^0; //外部故障点接口sbit failure2=P0^1;sbit failure3=P0^2;sbit failure4=P0^3;sbit failure5=P0^4;sbit failure6=P0^5;sbit failure7=P0^6;sbit failure8=P0^7;2.向SDA发送一个字节,并检验应答信号bit I_send(uchar I_data){register int i;for(i=0;i<8;i++){SDA=(bit)(I_data&0x80);I_data=I_data<<1;I_clock();}SDA=HIGH;return(~I_clock());}3.从SDA上读取8位数据信号,并作为一个数据信号返回byte I_receive(void){register int i;uchar I_data=0;for(i=0;i<8;i++){I_data=I_data<<1;if(I_clock());I_data=I_data&1;}return(I_data);}4.向8583时钟芯片内指定地址写入数据,并检验应答信号,成功则返回TRUE,否则返回FAULSEbit Write_8583(uchar Address,uchar data1){I_start();if(I_send(WRITE)&&I_send(Address)&&I_send(data1)){I_stop();delay();return(TRUE);}else return(FAULSE);}5.从8583时钟芯片指定地址读出数据,如成功读取,则发送应答信号,并返回TRUE,否则返回FAULSEuchar Read_8583(uchar Address){uchar data_8583;I_start();if(I_send(WRITE)&I_send(Address)&I_send(READ)){data_8583=I_receive();I_ack();I_stop();delay();return(data_8583);}}6.向7219指定地址写入数据void Write_7219(uchar Address,uchar Data){uchar i;LOAD = 1;for(i=0;i<8;i++) //传送8位地址{CLK = 0;DIN = (bit)(Address&0x80);Address = Address << 1;CLK = 1;}for(i=0;i<8;i++) //传送8位数据{CLK = 0;DIN = (bit)(Data&0x80);Data = Data << 1;CLK = 1;}LOAD = 0;}7.设置时间和监控值void set(void){char time1;char time2;if(!set_time){delay_ms(5);if(!set_time){keyvalue=0; //设置键按下时,keyvalue为0key_flg=1;}}if(!add_time){delay_ms(5);if(!add_time){keyvalue=1; //加1键按下时,keyvalue为1key_flg=1;}}if(!minus_time){delay_ms(5);if(!minus_time){keyvalue=2; //减1键按下时,keyvalue为2key_flg=1;}}if(!transfer_time){delay_ms(5);if(!transfer_time){keyvalue=3; //移位键按下时,keyvalue位3key_flg=1;}}if(key_flg){key_flg=0;{run=run+1;if((run-1)==4)run=1;if((run-1)==0) //进入时间设置状态{Write_8583(0x00,0x00);}if((run-1)==3) //跳出设置状态{Write_8583(0x00,0x80);}if((run-1)==1) //进入监控最大值设置状态{init_7219();Write_7219(0x01,max);}if((run-1)==2) //进入监控最小值设置状态{init_7219();Write_7219(0x01,min);}}if(keyvalue==1) //若按下加1键{if((run-1)==0&&transfer_flg){transfer_flg=0;if((tran-1)==2){time1=time&0x0f;time2=time&0xf0;time2=time2>>4;time1=time1+0x01;if(time1>0x09){time1=0x00;time2=time2+0x01;}time2=time2<<4;time=time1&time2;if(time>0x24)time=0x00;}if(tran-1<2){time1=time&0x0f; //time1放低位time2=time&0xf0; //time2放高位time2=time2>>4;if(time1>0x09){time1=0x00;time2=time2+0x01;}time2=time2<<4;time=time1&time2;time2=time2>>4;if(time>0x59)time=0x00;}Write_8583(number[tran-1],time);if((tran-1)==0){Write_7219(0x08,time1);Write_7219(0x07,time2);}if((tran-1)==1){Write_7219(0x05,time1);Write_7219(0x04,time2);}if((tran-1)==2){Write_7219(0x02,time1);Write_7219(0x01,time2);}}if((run-1)==1){max=max+0x01;Write_7219(0x01,max);}if((run-1)==2){min=min+0x01;Write_7219(0x01,min);}}if(keyvalue==2) //若按下减1键{if((run-1)==0&&transfer_flg){transfer_flg=0;if((tran-1)==2){time1=time&0x0f;time2=time&0xf0;time2=time2>>4;{time1=0x03;time2=0x02;}else{if(time1==0x00){time1=0x09;time2=time2-0x01;}else{time1=time1-0x01;}}time2=time2<<4;time=time1&time2;time2=time2>>4;}if(tran-1<2){time1=time&0x0f;time2=time&0xf0;time2=time2>>4;if(time1==0x00&&time2==0x00){time1=0x09;time2=0x05;}else{if(time1==0x00){time1=0x09;time2=time2-0x01;}else{time1=time1-0x01;}}time2=time2<<4;time=time1&time2;time2=time2>>4;}Write_8583(number[tran-1],time);if((tran-1)==0){}if((tran-1)==1){Write_7219(0x05,time1);Write_7219(0x04,time2);}if((tran-1)==2){Write_7219(0x02,time1);Write_7219(0x01,time2);}}if((run-1)==1){max=max-0x01;Write_7219(0x01,max);}if((run-1)==2){min=min-0x01;Write_7219(0x01,min);}}if(keyvalue==3) //若按下移位键{if((run-1)==0){transfer_flg=1;time=Read_8583(number[tran]);tran++;if(tran>2)tran=0;if(tran-1==0) //只显示秒位{Write_7219(0x01,0x0f);Write_7219(0x02,0x0f);Write_7219(0x04,0x0f);Write_7219(0x05,0x0f);}if(tran-1==1) //只显示分位{Write_7219(0x01,0x0f);Write_7219(0x02,0x0f);Write_7219(0x07,0x0f);Write_7219(0x08,0x0f);}if(tran-1==0) //只显示时位{Write_7219(0x04,0x0f);Write_7219(0x05,0x0f);}}}}}8.故障点产生故障时,写入24c256void failure(void){uchar key;register uchar i=0;bit port=1;uchar s1,m1,h1,s2,m2,h2;key=P0;if(key!=0xff){delay_ms(5);if(key!=0xff){s1=Read_8583(0x02);m1=Read_8583(0x03);h1=Read_8583(0x04);while(port){port=(bit)(key&0x80);key=key<<1;i++;}while(1){if(key==0xff){s2=Read_8583(0x02);m2=Read_8583(0x03);h2=Read_8583(0x04);break;}}E_write(i);E_write(s1);E_write(m1);E_write(h1);E_write(s2);E_write(m2);E_write(h2);}}}9.将模拟量通过TLC1549转换成数字量uint TLC1549(void){uchar n;uint ad_value=0; //初始化CS_AD1549 = 1;CLK_AD_DA = 0;DIO_AD_DA = 1;CS_AD1549 = 0;for(n=0;n<8;n++) //输出数据{CLK_AD_DA = 1;ad_value=ad_value|(uint)DIO_AD_DA;ad_value=ad_value<<1;CLK_AD_DA = 0;; ;}CS_AD1549 = 1;delay();return (ad_value);}10.接受主机指令bit Recv_Data(uchar *type){uchar tmp,rCount,i;uchar r_buf[RECFRMMAXLEN]; //保存接受到得帧uchar Flag_RecvOver; //一帧接受结束标志uchar Flag_StartRec; //一帧开始接收标志uchar CheckSum; //校验和uchar DataLen; //数据字节长度变量 /*禁止发送,允许接收*/DE=0;RE=0;/*接收一帧数据*/rCount=0;Flag_RecvOver=0;Flag_StartRec=0;while(!Flag_RecvOver){RI=0;while(!RI);tmp=SBUF;RI=0;/*判断是否收到字符“$”*/if((!Flag_StartRec)&&(tmp==0x24)){Flag_StartRec=1;}if(Flag_StartRec){r_buf[rCount]=tmp;rCount++;/*判断是否收到字符“*”*/if(tmp==0x2A)Flag_RecvOver=1;}if(rCount==RECFRMMAXLEN)return (0);}/*校验和字节*/CheckSum=0;DataLen=r_buf[3];for(i=0;i++;i<3+DataLen){CheckSum=CheckSum+r_buf[i+1];}/*判断帧是否错误*/if(rCount<6)return 0;if(r_buf[1]!=DevNo)return 0;if(r_buf[rCount-2]!=CheckSum)return 0;*type=r_buf[2];return 1;}11.发送数据void Send_Data(uchar type,uchar len,uchar *buf){uchar i,tmp;uchar CheckSum=0;/*允许发送,禁止接收*/DE=1;RE=1;/*发送帧起始字节*/tmp=0x24;Send(tmp);Send(DevNo); //发送设备号CheckSum=CheckSum+DevNo;Send(type); //发送类型字节CheckSum=CheckSum+type;Send(len); //发送数据长度字节CheckSum=CheckSum+len;/*发送数据*/for (i=0;i<len;i++){Send(*buf);CheckSum=CheckSum+ *buf;buf++;}Send(CheckSum); //发送校验和字节/*发送帧结束字节*/tmp=0x2A;Send(tmp);}12.主函数void main(void){uchar s1,m1,h1;uchar simu;uchar s2,m2,h2,s3,m3,h3;uchar s1h,s1l,m1h,m1l,h1h,h1l;uchar type;uchar key;key=P0;init_8583();init_7219();init();while(1){s1=Read_8583(0x02);m1=Read_8583(0x03);h1=Read_8583(0x04);h1h=h1&0x10;h1h=h1h>>4;Write_7219(0x01,h1h);h1l=h1&0x01;Write_7219(0x02,h1l);m1h=m1&0x10;m1h=m1h>>4;Write_7219(0x04,m1h);m1l=m1&0x01;Write_7219(0x05,m1l);s1h=s1&0x10;s1h=s1h>>4;Write_7219(0x07,s1h);s1l=s1&0x01;Write_7219(0x08,s1l);set(); //设置程序failure(); //故障点程序simu=TLC1549(); //模数转换程序if(simu<min||simu>max) //模拟量故障程序{s2=Read_8583(0x02);m2=Read_8583(0x03);h2=Read_8583(0x04);while(1){if(key==0xff){s3=Read_8583(0x02);m3=Read_8583(0x03);h3=Read_8583(0x04);break;}}E_write(0x09);E_write(s2);E_write(m2);E_write(h2);E_write(s3);E_write(m3);E_write(h3);}if(Recv_Data(&type)!=0) //写入上位机{switch (type){case ACTIVE:Send_Data(READY,0,StatusBuf);break;case GETDATA:E_read();Send_Data(SENDDATA,strlen(StatusBuf),StatusBuf);break;default:break;}}}}。

相关主题