51单片机AT24C02写读流水灯实例+Proteus仿真
51单片机AT24C02写读流水灯实例+Proteus仿真
- Proteus仿真

这个流水灯的状态是通过读取AT24C02地址中的数值来改变的。(有点废AT24C02)
程序代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
| #include <reg52.h> // 包含51单片机寄存器定义的头文件 #include <intrins.h> //包含\_nop\_()函数定义的头文件 #define OP\_READ 0xa1 // 器件地址以及读取操作,0xa1即为1010 0001B #define OP\_WRITE 0xa0 // 器件地址以及写入操作,0xa1即为1010 0000B #define uchar unsigned char uchar code table[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
sbit SDA=P1^0; //将串行数据总线SDA位定义在为P1.0引脚 sbit SCL=P1^1; //将串行时钟总线SDA位定义在为P1.1引脚 /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 函数功能:延时1ms \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/ void delay1ms()//@11.0592MHz { unsigned char i, j; \_nop\_(); \_nop\_(); \_nop\_(); i = 11; j = 190; do { while (--j); } while (--i); } /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 函数功能:延时若干毫秒 入口参数:n \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/ void delaynms(unsigned char n) { unsigned char i; for(i=0;i<n;i++) delay1ms(); } /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 函数功能:开始数据传送 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/ void start() // 开始位 { SDA = 1; //SDA初始化为高电平“1” SCL = 1; //开始数据传送时,要求SCL为高电平“1” \_nop\_(); //等待一个机器周期 \_nop\_(); //等待一个机器周期 \_nop\_(); //等待一个机器周期 \_nop\_(); //等待一个机器周期 SDA = 0; //SDA的下降沿被认为是开始信号 \_nop\_(); //等待一个机器周期 \_nop\_(); //等待一个机器周期 \_nop\_(); //等待一个机器周期 \_nop\_(); //等待一个机器周期 SCL = 0; //SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传递) } /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 函数功能:结束数据传送 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/ void stop() // 停止位 { SDA = 0; //SDA初始化为低电平“0” \_n SCL = 1; //结束数据传送时,要求SCL为高电平“1” \_nop\_(); //等待一个机器周期 \_nop\_(); //等待一个机器周期 \_nop\_(); //等待一个机器周期 \_nop\_(); //等待一个机器周期 SDA = 1; //SDA的上升沿被认为是结束信号 \_nop\_(); //等待一个机器周期 \_nop\_(); //等待一个机器周期 \_nop\_(); //等待一个机器周期 \_nop\_(); //等待一个机器周期 SDA=0; SCL=0; } /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 函数功能:从AT24Cxx读取数据 出口参数:x \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/ unsigned char ReadData() // 从AT24Cxx移入数据到MCU { unsigned char i; unsigned char x; //储存从AT24Cxx中读出的数据 for(i = 0; i < 8; i++) { SCL = 1; //SCL置为高电平 x<<=1; //将x中的各二进位向左移一位 x|=(unsigned char)SDA; //将SDA上的数据通过按位“或“运算存入x中 SCL = 0; //在SCL的下降沿读出数据 } return(x); //将读取的数据返回 } /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 函数功能:向AT24Cxx的当前地址写入数据 入口参数:y (储存待写入的数据) \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/ //在调用此数据写入函数前需首先调用开始函数start(),所以SCL=0 bit WriteCurrent(unsigned char y) { unsigned char i; bit ack_bit; //储存应答位 for(i = 0; i < 8; i++) // 循环移入8个位 { SDA = (bit)(y&0x80); //通过按位“与”运算将最高位数据送到S //因为传送时高位在前,低位在后 \_nop\_(); //等待一个机器周期 SCL = 1; //在SCL的上升沿将数据写入AT24Cxx \_nop\_(); //等待一个机器周期 \_nop\_(); //等待一个机器周期 SCL = 0; //将SCL重新置为低电平,以在SCL线形成传送数据所需的8个脉冲 y <<= 1; //将y中的各二进位向左移一位 } SDA = 1; // 发送设备(主机)应在时钟脉冲的高电平期间(SCL=1)释放SDA线, //以让SDA线转由接收设备(AT24Cxx)控制 \_nop\_(); //等待一个机器周期 \_nop\_(); //等待一个机器周期 SCL = 1; //根据上述规定,SCL应为高电平 \_nop\_(); //等待一个机器周期 \_nop\_(); //等待一个机器周期 \_nop\_(); //等待一个机器周期 \_nop\_(); //等待一个机器周期 ack_bit = SDA; //接受设备(AT24Cxx)向SDA送低电平,表示已经接收到一个字节 //若送高电平,表示没有接收到,传送异常 SCL = 0; //SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传递) return ack_bit; // 返回AT24Cxx应答位 } /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 函数功能:向AT24Cxx中的指定地址写入数据 入口参数:add (储存指定的地址);dat(储存待写入的数据) \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/ void WriteSet(unsigned char add, unsigned char dat) // 在指定地址addr处写入数据WriteCurrent { start(); //开始数据传递 WriteCurrent(OP_WRITE); //选择要操作的AT24Cxx芯片,并告知要对其写入数据 WriteCurrent(add); //写入指定地址 WriteCurrent(dat); //向当前地址(上面指定的地址)写入数据 stop(); //停止数据传递 delaynms(4); //1个字节的写入周期为1ms, 最好延时1ms以上 } /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 函数功能:从AT24Cxx中的当前地址读取数据 出口参数:x (储存读出的数据) \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/ unsigned char ReadCurrent() { unsigned char x; start(); //开始数据传递 WriteCurrent(OP_READ); //选择要操作的AT24Cxx芯片,并告知要读其数据 x=ReadData(); //将读取的数据存入x stop(); //停止数据传递 return x; //返回读取的数据 } /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 函数功能:从AT24Cxx中的指定地址读取数据 入口参数:set\_addr 出口参数:x \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/ unsigned char ReadSet(unsigned char set_addr) // 在指定地址读取 { start(); //开始数据传递 WriteCurrent(OP_WRITE); //选择要操作的AT24Cxx芯片,并告知要对其写入数据 WriteCurrent(set_addr); //写入指定地址 return(ReadCurrent()); //从指定地址读出数据并返回 } /\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\* 函数功能:主函数 \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/ void main(void) { unsigned char i,j=0; SDA = 1; // SDA=1,SCL=1,使主从设备处于空闲状态 SCL = 1; for(i=0;i<8;i++){ WriteSet(0x50+i,table[i]); //在指定地址“0x50”开始写入数据 } while(1) { P2=ReadSet(0x50+j); //从指定地址“0x50中读取数据并送P2口显示 j++; j %=8; delaynms(1000); } }
|
程序源码和仿真资源
1 2 3
| 链接:https://pan.baidu.com/s/1obHP0HZHdKVY\_tK\_q6Yx1A 提取码:5cyy
|
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!