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