📄 24c01.c
字号:
#include <reg51.h>
#include <absacc.h>
#include <intrins.h>
//*************************************************
//将2004 年1 月25 日星期日 上午11点10分30 秒的时间写入PCF8563
//以下在PCF8563 的CLKOUT 脚输出1Hz 的方波
//读出 年、月、日、星期、时、分、秒,以38400的波特率送往串口
//打开串口调试助手或其他串口调试软件设置波特率为38400,无校验,数据位8,停止位1
//**************************************************
#define PCF8563 0x0A //器件地址
#define MAX_BYTE_NUM 10 //一次性接受或发送字节的最大数目
//内存数据定义
unsigned char SlvAdr; //被控器地址
unsigned char SubAdr; //被控器单元地址
unsigned char ByteCnt; //传送字节数存放单元
unsigned char BitCnt; //I2C 数据位计数器
unsigned char XmtDat [MAX_BYTE_NUM]; //发送数据缓冲区
unsigned char RcvDat [MAX_BYTE_NUM]; //接收数据缓冲区
//unsigned char Second, Minute, Hour, Weekday, Day, Month, Year, Century;
bit ERR=0; //错误位
//端口位定义
sbit SDA = P3^7; //模拟I2C 数据传送位
sbit SCL = P3^6; //模拟I2C 时钟控制状态标志
sbit test1 = P1^0;
sbit test2 = P1^1;
void I2CSendData ();
//void Read8563();
void I2CSTA ();
void I2CSendByte (unsigned char _24C01byte);
void I2CSTOP ();
void I2CRcvData ();
unsigned char I2CRcvByte ();
void main ()
{
// 初始化设置
//以下准备送数
//将2004 年1 月25 日星期日 上午11点10分30 秒的时间写入PCF8563
IE = 0x00;
/*
XmtDat[0] = 0x00; //启动时钟
XmtDat[1] = 0x1F; //设置报警及定时器中断,定时器中断为脉冲形式
XmtDat[2] = 0x30; //秒值(30s)
XmtDat[3] = 0x10; //分值(10min)
XmtDat[4] = 0x11; //时值(11h)
XmtDat[5] = 0x25; //日期(25号)
XmtDat[6] = 0x00; //星期(0~6代表星期日~星期六)
XmtDat[7] = 0x01; //月份(如果首字节为1代表19XX年,首字节为0代表20XX年)
XmtDat[8] = 0x04; //年份(04年,与上一字节配合,确定为2004年)
SlvAdr = PCF8563; //送被控器地址
SubAdr = 0x00; //送写入寄存器的首字节地址,从00H 开始写
*/ ByteCnt = 0x02; //写七个时间信息和2 个控制命令
/* I2CSTA(); //发送I2C 总线起始条件
I2CSendByte (0xA0); //Chip selected bits=000, Write
I2CSendByte (0xA1);
I2CSendByte (0x55);
I2CSendByte (0x56);
I2CSTOP (); //发送I2C 总线停止条件 */
/*
I2CSTA();
I2CSendByte (0xA0); //Write
I2CSendByte (0x01);
I2CSTA();
I2CSendByte (0xA1); //Read
RcvDat[0] = I2CRcvByte();
I2CSTOP();
if (RcvDat[0] == 0x55) test1 = 0;
*/
SlvAdr = 0xA0;
SubAdr = 0x01;
XmtDat [0] = 0x55;
XmtDat [1] = 0x66;
I2CSendData ();
while(1){
SlvAdr = 0xA0;
SubAdr = 0x01;
I2CRcvData ();
if (RcvDat[0] == 0x55 && RcvDat[1] == 0x66){ test2 = 1; test1 = ~test1;}
}
// if (ERR == 1) test1 = ~test1;
// I2CSendData(); //送出数据
// Read8563();
}
//*******************************************************************
//以下在PCF8563 的CLKOUT 脚输出1Hz 的方波,输出由0DH控制
//0DH 7 6 5 4 3 2 1 0
// PE - - - - - FD1 FD0
// PE=0;CLKOUT禁止输出并设成高阻抗
// PE=1;CLKOUT允许输出
// FD1 FD0 输出频率
// 0 0 32768Hz
// 0 1 1024Hz
// 1 0 32Hz
// 1 1 1Hz
//要求输出32768Hz,1024Hz,32Hz,1Hz的数据分别为80H,81H,82H和83H
//********************************************************************
//以下每隔1s左右读取时间并将时间送往串口
/*;**********************************************************
;延时1s的子程序
;**********************************************************
D1S:
PUSH ACC
PUSH PSW
SETB RS0
MOV R7,#20
D11: MOV R6,#200
D12: MOV R5,#100
DJNZ R5,$
DJNZ R6,D12
DJNZ R7,D11
POP PSW
POP ACC
RET
;**********************************************************
;向串口送数的子程序
;***********************************************************
SEND:
MOV SBUF,A
SLP:
JBC TI,NEXT ;是否送完?
AJMP SLP
NEXT: RET */
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
//I2C总线的读写子程序 ;;
//被控器地址在SlvAdr,单元地址在SubAdr中,所发送的数据字节数在ByteCnt中 ;;
//所发送的数据在XmtDat中,所接收的数据在RcvDat中 ;;
//;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
//************************************************************************************************
//发送数据程序
//名称:I2CSendData
//描述:发送ByteCnt个字节给被控器
//被控器地址在SlvAdr中,单元地址在SubAdr中
//所发送数据的字节数在ByteCnt中,发送的数据在XmtDat缓冲区中
//发送数据正常返回标志ERR=0, ERR=1表示被控器无应答或损坏
//***********************************************************************************************
void I2CSendData ()
{
unsigned char i;
// SETB RS0
I2CSTA(); //发送I2C 总线起始条件
I2CSendByte (SlvAdr); //写一个字节
// JB ERR,I2CSRN ;错误返回
I2CSendByte (SubAdr);
// JB ERR,I2CSRN
for (i = 0; i < ByteCnt; i ++)
{
I2CSendByte (XmtDat [i]);
// JB ERR,I2CSRN
}
I2CSTOP (); //发送I2C 总线停止条件
// if (ERR == 1) test1 = 0;
}
/*************************************************************************************************
;接收数据程序
;名称:I2CRcvData
;描述:从被控器接收ByteCnt个字节数据
;被控器地址在SlvAdr中,单元地址在SubAdr中
;所接收数据的字节数在ByteCnt中,接收的数据在RcvDat缓冲区中
;接收数据正常返回标志ERR=0, ERR=1表示被控器无应答或损坏
;************************************************************************************************/
void I2CRcvData()
{
unsigned char i;
// SETB RS0
I2CSTA(); //发送I2C 总线起始条件
I2CSendByte (SlvAdr); //写入器件地址
// JB ERR,I2CRRN ;错误返回
I2CSendByte (SubAdr); //写入单元地址
// JB ERR,I2CRRN
I2CSTA (); //发送I2C 总线重复起始条件
SlvAdr = SlvAdr | 0x01;
I2CSendByte (SlvAdr); //再次写入器件地址
// JB ERR,I2CRRN
for (i = 0; i < ByteCnt; i ++)
{
RcvDat [i] = I2CRcvByte ();
SDA = 0; //发送应答位
SCL = 1; //250ns后置时钟线为高通知被控器开始接收应答位
_nop_(); //保证时钟高周期大于4us
_nop_();
_nop_();
_nop_();
SCL = 0; //钳住I2C 总线以便继续接收字接数据
}
SDA = 1; //发送非应答位
SCL = 1; //250ns后置时钟线为高通知被控器开始接收非应答位
_nop_(); //保证时钟高周期大于4us
_nop_();
_nop_();
_nop_();
SCL = 0; //钳住I2C 总线以便发送停止条件
SDA = 0; //
I2CSTOP ();
}
/*******************************************************************************
; 子程序
;******************************************************************************
;名称:I2CSTA
;描述:启动I2C 总线子程序--发送I2C 总线起始条件
;------------------------------------------------------------------------------
*/
void I2CSTA ()
{
SCL = 0;
SDA = 1; //发送起始条件的数据信号
SCL = 1; //250ns后发送起始条件的时钟信号
_nop_(); //起始条件建立时间大于4.7us
_nop_();
_nop_();
_nop_();
_nop_();
SDA = 0; //发送起始信号
_nop_(); //起始条件锁定时间大于4us
_nop_();
_nop_();
_nop_();
SCL = 0; //钳住I2C 总线准备发送或接收数据
}
/*------------------------------------------------------------------------------
;名称:I2CSTOP
;描述:停止I2C 总线子程序--发送I2C 总线停止条件
;------------------------------------------------------------------------------
*/
void I2CSTOP ()
{
SDA = 0; //发送停止条件的数据信号
SCL = 1; //250ns后发送停止条件的时钟信号
_nop_(); //停止条件建立时间大于4us
_nop_();
_nop_();
_nop_();
_nop_();
SDA = 1; //发送I2C 总线停止信号
}
/*------------------------------------------------------------------------------
;名称:I2CSentByte
;描述:字节数据传送子程序--发送一个字节数据或地址给被控器
;要发送的数据在ACC中
;发送数据正常返回标志ERR=0,ERR=1表示被控器无应答或损坏.
;------------------------------------------------------------------------------
*/
void I2CSendByte (unsigned char _8563byte)
{
unsigned char i;
BitCnt = 0x08; //向VSDA线上发送1个数据字节
for ( i = BitCnt; i > 0; i --)
{
// _nop_();
SDA = (_8563byte >> (i - 1)) % 2; //发送数据位
SCL = 1; //250ns后置时钟线为高通知被控器开始接收数据位
_nop_(); //保证时钟高周期大于4us
_nop_();
_nop_();
_nop_();
SCL = 0; //钳住时钟总线准备接收下一个数据位
_nop_(); //保证时钟低周期大于4.7us
}
_nop_();
_nop_();
SDA = 1; //8位发送完后释放数据线准备收应答位
SCL = 1; //开始接收应答信号
// _nop_();
ERR = 0;
if (SDA == 1) ERR = 1;
SCL = 0;
}
/*------------------------------------------------------------------------------
;名称:I2CRcvByte
;描述:字节数据接收子程序--从被控器接收一个字节数据
;接收的字节数据在ACC中
;------------------------------------------------------------------------------*/
unsigned char I2CRcvByte ()
{
unsigned char res, i;
BitCnt = 0x08; //从VSDA线上读取1个数据字节
res = 0x00;
for (i = 0; i < BitCnt; i ++)
{
SDA = 1; //置数据线为输入方式
SCL = 1; //置时钟线为高使数据线上数据有效
res = (res << 1) | SDA; //接收数据存入res
SCL = 0; //接收结束钳住总线准备下一步接收或发送(非)应答位
_nop_(); //时钟低周期大于4.7us
}
return res;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -