用STM32或者51单片机设计一个读卡系统,对外接的I2C接口电路或者SPI接口电路进行读写操作,读写内容可以通过数码管或者其他监视器件查看,并用示波器观看通信线路波形。完成主机跟两个从机之间的I2C通信,可以用数码管等显示通信的内容,也可以用示波器监视通信线路的数据信息。
单片机源程序如下:
- #include<reg51.h>
- #include<intrins.h>
- typedef unsigned int u16;
- typedef unsigned char u8;
- sbit SDA=P1^1;
- sbit SCL=P1^0;
- void At24CO2Write(u8 add,u8 dat,u8 addr);
- u8 At24CO2Read(u8 add,u8 addr);
- u8 numer[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
- u8 display[4];
- sbit A1=P2^2;
- sbit B1=P2^3;
- sbit C1=P2^4;
- #define SHUMA P0
- sbit K1=P3^0;//保存
- sbit K2=P3^1;//读取
- sbit K3=P3^2;
- sbit K4=P3^3;
- sbit K5=P3^4;//num++
- sbit K6=P3^5;//清零
- sbit led=P2^0;
- u8 num;
- void delay(u16 i)
- {
- while(i--);
- }
- void delay10us(void)
- {
- unsigned char a,b;
- for(b=1;b>0;b--)
- for(a=2;a>0;a--);
- }
- void shumaguan(u8 word[])
- { u8 i;
- for(i=0;i<4;i++)
- {
- switch(i)
- {
- case 0:C1=0;B1=0;A1=0;break;
- case 1:C1=0;B1=0;A1=1;break;
- case 2:C1=0;B1=1;A1=0;break;
- case 3:C1=0;B1=1;A1=1;break;
- }
- SHUMA=word[i];
- delay(100);
- SHUMA=0x00;
- }
- }
- void Key(u8 dat)
- {
-
- if(K1==0)
- {
- delay(1000);
- if(K1==0)
- {
- At24CO2Write(0xa0,dat,1);
- }
- while(!K1);
- }
- if(K2==0)
- {
- delay(1000);
- if(K2==0)
- {
- num=At24CO2Read(0xa0,1);
- }
- while(!K2);
- }
- if(K3==0)
- {
- delay(1000);
- if(K3==0)
- {
- At24CO2Write(0xa2,dat,1);
- }
- while(!K3);
- }
- if(K4==0)
- {
- delay(1000);
- if(K4==0)
- {
- num=At24CO2Read(0xa2,1);
- }
- while(!K4);
- }
- if(K5==0)
- {
- delay(1000);
- if(K5==0)
- num++;
- while(!K5);
- }
- if(K6==0)
- {
- delay(1000);
- if(K6==0)
- num=0;
- while(!K6);
- }
- }
- void change()
- {
- display[0]=numer[num/1000];
- display[1]=numer[(num%1000)/100];
- display[2]=numer[(num%100)/10];
- display[3]=numer[num%10];
- }
- void main()
- {
- // SDA=1;
- // delay10us();
- // SCL=0;
- // delay10us();
- //// u8 addr = 0x66;
- // uchar addr1=0x66, addr2=0x88, dat1, dat2;
-
- // write(0xa2, addr2, 0);
- while(1)
- {
- Key(num);
- change();
- shumaguan(display);
- }
- }
- void I2cStart() //开始函数,时钟信号始终为高,当数据线由高变低时开始
- {
- SDA=1;
- delay10us();
- SCL=1;
- delay10us();
- SDA=0;
- delay10us();
- SCL=0;
- delay10us();
- }
- void I2cStop() //停止函数,时钟信号始终为高,当数据线由低变高时开结束
- {
- SDA=0;
- delay10us();
- SCL=1;
- delay10us();
- SDA=1;
- delay10us();
- }
- void I2cAck()
- {
- SDA=0;
- delay10us();
- SCL=1;
- delay10us();
- SCL=0;
- delay10us();
- }
-
- void nack()
- {
- SDA = 1; //拉高SDA,发送非应答信号
- Delay();
- SCL = 1; //拉高SCL
- Delay();
- SCL = 0; //再拉低完成非应答位,并保持住总线
- }
-
- u8 I2cSend(u8 dat)
- {
- u8 i;
- for(i=0x80; i!=0; i>>=1) //从高位到低位依次进行
- {
- if((dat&i) == 0) //该位的值依次输出到SDA上
- SDA = 0;
- else
- SDA = 1;
- delay10us();
- SCL = 1; //拉高SCL
- delay10us();
- SCL = 0; //再拉低SCL完成一个位周期
- }
- }
- u8 I2cRead()
- {
- u8 i, dat;
-
- SDA = 1; //确保主机释放SDA
- for(i=0x80; i!=0; i>>=1) //从高位到低位依次进行
- {
- delay10us();
- SCL = 1; //拉高SCL
- if(SDA == 0) //读取SDA的值
- dat &= ~i; //为0时,dat中对应位清零
- else
- dat |= i; //为1时,dat中对应位置1
- delay10us();
- SCL = 0; //再拉低SCL使从机发送出下一位
- }
- return dat;
- }
- void At24CO2Write(u8 add,u8 dat,u8 addr)
- {
- I2cStart();
- I2cSend(add);
- I2cAck();
- I2cSend(addr);
- I2cAck();
- I2cSend(dat);
- I2cAck();
- I2cStop();
- }
- u8 At24CO2Read(u8 add,u8 addr)
- {
- u8 num;
- I2cStart();
- I2cSend(add);
- I2cAck();
- I2cSend(addr);
- I2cAck();
- I2cStart();
- I2cSend(add+1);
- I2cAck();
- num=I2cRead();
- // nack();
- I2cStop();
- return num;
- }
复制代码 Keil代码与Proteus仿真下载:
实验40.rar
(98.02 KB, 下载次数: 12)
|