[51单片机] EEPROM 24c02 [I2C代码封装-保存实现流水灯]
这里把EEPROM 24c02封装起来,今后可以直接调用,其连线方式为:SDA-P2.1;SCL-P2.0;WP-VCC
>_<:i2c.c
1 /*----------------------------------------------- 2 名称:IIC协议 3 内容:函数是采用软件延时的方法产生SCL脉冲,固对高晶振频率要作 一定的修改....(本例是1us机器 4 周期,即晶振频率要小于12MHZ) 5 ------------------------------------------------*/ 6 #include "i2c.h" 7 #define _Nop() _nop_() //定义空指令 8 bit ack; //应答标志位 9 sbit SDA=P2^1; 10 sbit SCL=P2^0; 11 /*------------------------------------------------ 12 uS延时函数,含有输入参数 unsigned char t,无返回值 13 unsigned char 是定义无符号字符变量,其值的范围是 14 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时 15 长度如下 T=tx2+5 uS 16 ------------------------------------------------*/ 17 void DelayUs2x(unsigned char t) 18 { 19 while(--t); 20 } 21 /*------------------------------------------------ 22 mS延时函数,含有输入参数 unsigned char t,无返回值 23 unsigned char 是定义无符号字符变量,其值的范围是 24 0~255 这里使用晶振12M,精确延时请使用汇编 25 ------------------------------------------------*/ 26 void DelayMs(unsigned char t) 27 { 28 while(t--) 29 { 30 //大致延时1mS 31 DelayUs2x(245); 32 DelayUs2x(245); 33 } 34 } 35 /*------------------------------------------------ 36 启动总线 37 ------------------------------------------------*/ 38 void Start_I2c() 39 { 40 SDA=1; //发送起始条件的数据信号 41 _Nop(); 42 SCL=1; 43 _Nop(); //起始条件建立时间大于4.7us,延时 44 _Nop(); 45 _Nop(); 46 _Nop(); 47 _Nop(); 48 SDA=0; //发送起始信号 49 _Nop(); //起始条件锁定时间大于4μ 50 _Nop(); 51 _Nop(); 52 _Nop(); 53 _Nop(); 54 SCL=0; //钳住I2C总线,准备发送或接收数据 55 _Nop(); 56 _Nop(); 57 } 58 /*------------------------------------------------ 59 结束总线 60 ------------------------------------------------*/ 61 void Stop_I2c() 62 { 63 SDA=0; //发送结束条件的数据信号 64 _Nop(); //发送结束条件的时钟信号 65 SCL=1; //结束条件建立时间大于4μ 66 _Nop(); 67 _Nop(); 68 _Nop(); 69 _Nop(); 70 _Nop(); 71 SDA=1; //发送I2C总线结束信号 72 _Nop(); 73 _Nop(); 74 _Nop(); 75 _Nop(); 76 } 77 /*---------------------------------------------------------------- 78 字节数据传送函数 79 函数原型: void SendByte(unsigned char c); 80 功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对 81 此状态位进行操作.(不应答或非应答都使ack=0 假) 82 发送数据正常,ack=1; ack=0表示被控器无应答或损坏。 83 ------------------------------------------------------------------*/ 84 void SendByte(unsigned char c) 85 { 86 unsigned char BitCnt; 87 for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位 88 { 89 if((c<<BitCnt)&0x80)SDA=1; //判断发送位 90 else SDA=0; 91 _Nop(); 92 SCL=1; //置时钟线为高,通知被控器开始接收数据位 93 _Nop(); 94 _Nop(); //保证时钟高电平周期大于4μ 95 _Nop(); 96 _Nop(); 97 _Nop(); 98 SCL=0; 99 } 100 _Nop(); 101 _Nop(); 102 SDA=1; //8位发送完后释放数据线,准备接收应答位 103 _Nop(); 104 _Nop(); 105 SCL=1; 106 _Nop(); 107 _Nop(); 108 _Nop(); 109 if(SDA==1)ack=0; 110 else ack=1; //判断是否接收到应答信号 111 SCL=0; 112 _Nop(); 113 _Nop(); 114 } 115 /*---------------------------------------------------------------- 116 字节数据传送函数 117 函数原型: unsigned char RcvByte(); 118 功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号), 119 发完后请用应答函数。 120 ------------------------------------------------------------------*/ 121 unsigned char RcvByte() 122 { 123 unsigned char retc; 124 unsigned char BitCnt; 125 126 retc=0; 127 SDA=1; //置数据线为输入方式 128 for(BitCnt=0;BitCnt<8;BitCnt++) 129 { 130 _Nop(); 131 SCL=0; //置时钟线为低,准备接收数据位 132 _Nop(); 133 _Nop(); //时钟低电平周期大于4.7us 134 _Nop(); 135 _Nop(); 136 _Nop(); 137 SCL=1; //置时钟线为高使数据线上数据有效 138 _Nop(); 139 _Nop(); 140 retc=retc<<1; 141 if(SDA==1)retc=retc+1; //读数据位,接收的数据位放入retc中 142 _Nop(); 143 _Nop(); 144 } 145 SCL=0; 146 _Nop(); 147 _Nop(); 148 return(retc); 149 } 150 /*---------------------------------------------------------------- 151 应答子函数 152 原型: void Ack_I2c(void); 153 ----------------------------------------------------------------*/ 154 void Ack_I2c(void) 155 { 156 SDA=0; 157 _Nop(); 158 _Nop(); 159 _Nop(); 160 SCL=1; 161 _Nop(); 162 _Nop(); //时钟低电平周期大于4μ 163 _Nop(); 164 _Nop(); 165 _Nop(); 166 SCL=0; //清时钟线,钳住I2C总线以便继续接收 167 _Nop(); 168 _Nop(); 169 } 170 /*---------------------------------------------------------------- 171 非应答子函数 172 原型: void NoAck_I2c(void); 173 ----------------------------------------------------------------*/ 174 void NoAck_I2c(void) 175 { 176 SDA=1; 177 _Nop(); 178 _Nop(); 179 _Nop(); 180 SCL=1; 181 _Nop(); 182 _Nop(); //时钟低电平周期大于4μ 183 _Nop(); 184 _Nop(); 185 _Nop(); 186 SCL=0; //清时钟线,钳住I2C总线以便继续接收 187 _Nop(); 188 _Nop(); 189 } 190 /*---------------------------------------------------------------- 191 向无子地址器件发送字节数据函数 192 函数原型: bit ISendByte(unsigned char sla,ucahr c); 193 功能: 从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla. 194 如果返回1表示操作成功,否则操作有误。 195 注意: 使用前必须已结束总线。 196 ----------------------------------------------------------------*/ 197 /*bit ISendByte(unsigned char sla,unsigned char c) 198 { 199 Start_I2c(); //启动总线 200 SendByte(sla); //发送器件地址 201 if(ack==0)return(0); 202 SendByte(c); //发送数据 203 if(ack==0)return(0); 204 Stop_I2c(); //结束总线 205 return(1); 206 } 207 */ 208 /*---------------------------------------------------------------- 209 向有子地址器件发送多字节数据函数 210 函数原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no); 211 功能: 从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件 212 地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。 213 如果返回1表示操作成功,否则操作有误。 214 注意: 使用前必须已结束总线。 215 ----------------------------------------------------------------*/ 216 bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no) 217 { 218 unsigned char i; 219 for(i=0;i<no;i++) 220 { 221 Start_I2c(); //启动总线 222 SendByte(sla); //发送器件地址 223 if(ack==0)return(0); 224 SendByte(suba); //发送器件子地址 225 if(ack==0)return(0); 226 227 SendByte(*s); //发送数据 228 229 if(ack==0)return(0); 230 Stop_I2c(); //结束总线 231 DelayMs(2); //必须延时等待芯片内部自动处理数据完毕 232 s++; 233 suba++; 234 } 235 return(1); 236 } 237 238 /*---------------------------------------------------------------- 239 向无子地址器件读字节数据函数 240 函数原型: bit IRcvByte(unsigned char sla,ucahr *c); 241 功能: 从启动总线到发送地址,读数据,结束总线的全过程,从器件地 242 址sla,返回值在c. 243 如果返回1表示操作成功,否则操作有误。 244 注意: 使用前必须已结束总线。 245 ----------------------------------------------------------------*/ 246 /*bit IRcvByte(unsigned char sla,unsigned char *c) 247 { 248 Start_I2c(); //启动总线 249 SendByte(sla+1); //发送器件地址 250 if(ack==0)return(0); 251 *c=RcvByte(); //读取数据 252 NoAck_I2c(); //发送非就答位 253 Stop_I2c(); //结束总线 254 return(1); 255 } 256 */ 257 /*---------------------------------------------------------------- 258 向有子地址器件读取多字节数据函数 259 函数原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no); 260 功能: 从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件 261 地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。 262 如果返回1表示操作成功,否则操作有误。 263 注意: 使用前必须已结束总线。 264 ----------------------------------------------------------------*/ 265 bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no) 266 { 267 unsigned char i; 268 269 Start_I2c(); //启动总线 270 SendByte(sla); //发送器件地址 271 if(ack==0)return(0); 272 SendByte(suba); //发送器件子地址 273 if(ack==0)return(0); 274 275 Start_I2c(); 276 SendByte(sla+1); 277 if(ack==0)return(0); 278 279 for(i=0;i<no-1;i++) 280 { 281 *s=RcvByte(); //发送数据 282 Ack_I2c(); //发送就答位 283 s++; 284 } 285 *s=RcvByte(); 286 NoAck_I2c(); //发送非应位 287 Stop_I2c(); //结束总线 288 return(1); 289 }
>_<:i2c.h
1 /*----------------------------------------------- 2 名称:IIC协议 头文件 3 ------------------------------------------------*/ 4 #ifndef __I2C_H__ 5 #define __I2C_H__ 6 #include <reg52.h> //头文件的包含 7 #include <intrins.h> 8 #define _Nop() _nop_() //定义空指令 9 /*----------------------------------------------- 10 uS延时函数,含有输入参数 unsigned char t,无返回值 11 unsigned char 是定义无符号字符变量,其值的范围是 12 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时 13 长度如下 T=tx2+5 uS 14 ------------------------------------------------*/ 15 void DelayUs2x(unsigned char t); 16 /*------------------------------------------------ 17 mS延时函数,含有输入参数 unsigned char t,无返回值 18 unsigned char 是定义无符号字符变量,其值的范围是 19 0~255 这里使用晶振12M,精确延时请使用汇编 20 ------------------------------------------------*/ 21 void DelayMs(unsigned char t); 22 /*------------------------------------------------ 23 启动总线 24 ------------------------------------------------*/ 25 void Start_I2c(); 26 /*------------------------------------------------ 27 结束总线 28 ------------------------------------------------*/ 29 void Stop_I2c(); 30 /*---------------------------------------------------------------- 31 字节数据传送函数 32 函数原型: void SendByte(unsigned char c); 33 功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对 34 此状态位进行操作.(不应答或非应答都使ack=0 假) 35 发送数据正常,ack=1; ack=0表示被控器无应答或损坏。 36 ------------------------------------------------------------------*/ 37 void SendByte(unsigned char c); 38 /*---------------------------------------------------------------- 39 字节数据传送函数 40 函数原型: unsigned char RcvByte(); 41 功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号), 42 发完后请用应答函数。 43 ------------------------------------------------------------------*/ 44 unsigned char RcvByte(); 45 /*---------------------------------------------------------------- 46 应答子函数 47 原型: void Ack_I2c(void); 48 ----------------------------------------------------------------*/ 49 void Ack_I2c(void); 50 /*---------------------------------------------------------------- 51 非应答子函数 52 原型: void NoAck_I2c(void); 53 ----------------------------------------------------------------*/ 54 void NoAck_I2c(void); 55 /*---------------------------------------------------------------- 56 向无子地址器件发送字节数据函数 57 函数原型: bit ISendByte(unsigned char sla,ucahr c); 58 功能: 从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla. 59 如果返回1表示操作成功,否则操作有误。 60 注意: 使用前必须已结束总线。 61 ----------------------------------------------------------------*/ 62 bit ISendByte(unsigned char sla,unsigned char c); 63 64 /*---------------------------------------------------------------- 65 向有子地址器件发送多字节数据函数 66 函数原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no); 67 功能: 从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件 68 地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。 69 如果返回1表示操作成功,否则操作有误。 70 注意: 使用前必须已结束总线。 71 ----------------------------------------------------------------*/ 72 bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no); 73 /*---------------------------------------------------------------- 74 向无子地址器件读字节数据函数 75 函数原型: bit IRcvByte(unsigned char sla,ucahr *c); 76 功能: 从启动总线到发送地址,读数据,结束总线的全过程,从器件地 77 址sla,返回值在c. 78 如果返回1表示操作成功,否则操作有误。 79 注意: 使用前必须已结束总线。 80 ----------------------------------------------------------------*/ 81 bit IRcvByte(unsigned char sla,unsigned char *c); 82 /*---------------------------------------------------------------- 83 向有子地址器件读取多字节数据函数 84 函数原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no); 85 功能: 从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件 86 地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。 87 如果返回1表示操作成功,否则操作有误。 88 注意: 使用前必须已结束总线。 89 ----------------------------------------------------------------*/ 90 bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no); 91 #endif
>_<:下面是main函数中如何调用封装好的函数来实现流水灯的效果的:
>_<:流水灯8个的连线这里用的是P1
1 /*----------------------------------------------- 2 名称:IIC协议 24c02存储花样灯程序 3 内容:将表格内容写入24c02,然后批量删除这些数据, 4 并从24c02中读取数据并显示 5 ------------------------------------------------*/ 6 #include <reg52.h> 7 #include "i2c.h" 8 /*------------------------------------------------ 9 花样灯表格 10 ------------------------------------------------*/ 11 unsigned char dat[]={0x7f,0xbf,0xdf,0xef, 12 0xf7,0xfb,0xfd,0xfe, 13 0xff,0xff,0x00,0x00, 14 0x55,0x55,0xaa,0xaa 15 };//ram允许情况可以无限添加 16 /*------------------------------------------------ 17 主函数 18 ------------------------------------------------*/ 19 main() 20 { 21 //bit flag; 22 unsigned char i; 23 ISendStr(0xae,80,dat,16); //写入24c02 24 DelayMs(1); //写入后必须延时等待24c02内部 25 //烧录数据处理完毕方可继续其他操作 26 for(i=0;i<16;i++) //清除数据 27 dat[i]=0; 28 IRcvStr(0xae,80,dat,16); //从24c02读出数据 29 while(1) 30 { 31 for(i=0;i<16;i++) //查表 32 { 33 DelayMs(200); 34 P1=dat[i]; 35 } 36 } 37 }