📄 clockand2401rw.c
字号:
//////////////////////////////////////////////////////////////////////////////////////////////
//
// Author : ShiZheJun
// Date : 2007.10
// 编译环境 :伟福6000
// 说明:使用8051系列单片机,6M晶振,显示的数字分段从高位到低位输出到74hc164,再移位输出到数码
// 显示管,用两个数码管显示数字.
// 按键K1显示秒数,K2显示分钟,K3写数据到EEPROM 24C01,K4从24C01读出数据并显示
// 数字段码从高位到低位移出到74HC164;在移出过程中数码管必须熄灭,等全部移出后再点亮并
// 延时,24C01读写时指定地址
// Ver3
//
//////////////////////////////////////////////////////////////////////////////////////////////
#include "stdio.h"
#include "reg51.h"
#include "intrins.h"
#include "absacc.h"
#define Hi 236
#define Lo 120
#define NOP _nop_();_nop_();_nop_() /*延时使用,一个_nop_()为一个时钟周期*/
#define Rd2401 0xa1 /*读24C01控制命令*/
#define Wr2401 0xa0 /*写24C01控制命令*/
#define DispLine 0x86
#define Address 0x08 /*读写24C01存储单元的地址*/
unsigned char Seg[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char Disp; /*显示缓冲*/
unsigned char DispTemp; /*显示临时数据*/
unsigned int Deda,Sec,Min;
unsigned int KeyVal; /*按键值*/
sbit K0=P1^0;
sbit K1=P1^1;
sbit K2=P1^2;
sbit K3=P1^3;
sbit SCL=P2^0; /*IIC总线方式工作时时钟信号*/
sbit SDA=P2^1; /*IIC总线方式工作时串行数据信号*/
sbit Line0=P2^4;
sbit Bout=P3^0; /*p3.0输出段数据*/
sbit CLK=P3^1; /*p3.2输出脉冲信号,使74hc164产生移位*/
sbit P35=P3^5; /*低电平时使个位显示*/
sbit P36=P3^6; /*低电平时使十位显示*/
Timer0() interrupt 1
{
TMOD=0x01; /*工作模式1*/
TH0=Hi; /*设置10ms中断一次*/
TL0=Lo;
IE=0x82; /*允许计时器0中断*/
PT0=1; /*计时器0中断优先*/
TR0=1; /*启动计时器0*/
Deda++;
if (Deda==100) {Sec++;Deda=0;}
if (Sec==60) {Min++;Sec=0;}
if (Min==60) Min=0;
}
void InitTimer0(void) /*初始化计时器0*/
{
TMOD=0x01;
TH0=Hi;
TL0=Lo;
IE=0x82;
PT0=1;
TR0=1;
}
void Delay(unsigned int t) /*起延迟作用的子函数*/
{
while (t--);
}
void KeyPress(void) /*检测按键是否被按下*/
{
Line0=0;
if (K0==0)
Delay(500);
if (K0==0) KeyVal=0;
if (K1==0)
Delay(500);
if (K1==0) KeyVal=1;
if (K2==0)
Delay(500);
if (K2==0) KeyVal=2;
if (K3==0)
Delay(500);
if (K3==0) KeyVal=3;
}
void SendData(void) /*向74HC164移位输出显示数据*/
{
unsigned char n=8;
while (n--)
{
if (Disp&0x80) Bout=1;
else Bout=0;
CLK=0; CLK=1;
Disp=Disp<<1;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
// 以下为IIC总线方式,传输和接收数据,以及启动和停止的各个子函数
//
//////////////////////////////////////////////////////////////////////////////////////////////
void IICStart(void) /*IIC启动条件*/
{
SDA=1;
SCL=1;
NOP;
SDA=0;
NOP;
}
void IICStop(void) /*IIC停止条件*/
{
SDA=0;
SCL=1;
NOP;
SDA=1;
NOP;
}
void IICSend(unsigned char d) /*IIC发送数据子函数*/
{
unsigned int i;
for (i=0;i<8;i++)
{
SCL=0;
NOP;
if (d&0x80) SDA=1;
else SDA=0;
NOP;
SCL=1;
d=d<<1;
}
SCL=0;
}
unsigned char IICReceive(void) /*IIC接收数据子函数*/
{
unsigned int i;
unsigned char d=0;
SDA=1;
NOP;
SCL=0;
NOP;
for (i=0;i<8;i++)
{
NOP;
d=d<<1;
SCL=1;
if (SDA) d=d+1;
SCL=0;
}
return d;
}
void IICAck(void) /*IIC发出应答信号*/
{
SDA=0;
NOP;
SCL=1;
NOP;
SCL=0;
}
void IICNoAck(void) /*IIC发出无应答信号*/
{
SDA=1;
NOP;
SCL=1;
NOP;
SCL=0;
}
void Change(void) /*根据按键显示不同的内容*/
{
if (KeyVal==0) /*显示秒数*/
{
Disp=Seg[Sec%10];
SendData();
P35=0;
Delay(407);
P35=1;
Disp=Seg[Sec/10];
SendData();
P36=0;
Delay(408);
P36=1;
}
if (KeyVal==1) /*显示分钟*/
{
Disp=Seg[Min%10];
SendData();
P35=0;
Delay(409);
P35=1;
Disp=Seg[Min/10];
SendData();
P36=0;
Delay(410);
P36=1;
}
if (KeyVal==2) /*向24C01发送数据*/
{
IICStart();
IICSend(Wr2401);
SDA=0;
NOP;
SCL=1;
NOP;
SCL=0;
IICSend(Address); /*发送数据地址*/
SDA=0;
NOP;
SCL=1;
NOP;
SCL=0;
IICSend(DispLine);
IICAck();
IICStop();
KeyVal=0;
}
if (KeyVal==3) /*接收24C01的数据,接收前要先输入写的命令,再重新初始化*/
{
IICStart();
IICSend(Wr2401);
IICAck();
IICSend(Address); /*发送数据地址*/
IICAck();
IICStart();
IICSend(Rd2401);
IICAck();
DispTemp=IICReceive();
IICNoAck();
IICStop();
KeyVal=4;
}
if (KeyVal==4) /*显示从24C01接收到的数据*/
{
Disp=DispTemp;
SendData();
P35=0;
Delay(405);
P35=1;
Disp=DispTemp;
SendData();
P36=0;
Delay(406);
P36=1;
}
}
void main(void)
{
InitTimer0( ); /*初始化计时器0*/
while ( 1 )
{
KeyPress(); /*按键检测*/
Change();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -