📄 s3530a.c
字号:
#include <c8051f.h>
#include <S3530A.h> // SFR declarations
#include "INTRINS.H"
//------------------------------------------------------------------------------------
// Global CONSTANTS
//------------------------------------------------------------------------------------
union
{
unsigned char ClockString[7];
struct RealClock
{
unsigned char Year,Month,Day,Week,Hour,Minute,Second;
} RT;
} RealTime;
char COMMAND; // Holds the slave address + R/W bit for use in the SMBus ISR.
unsigned char *I2CDataBuff;
char BYTE_NUMBER; // Used by ISR to check what data has just been
// sent - High address byte, Low byte, or data byte
unsigned char HIGH_ADD, LOW_ADD; // High & Low byte for EEPROM memory address
bit SM_BUSY; // This bit is set when a send or receive
// is started. It is cleared by the
CDateTime g_objDateTime; // ISR when the operation is finished.
//------------------------------------------------------------------------------------
// Function PROTOTYPES
//------------------------------------------------------------------------------------
void SMBus_ISR (void);
//------------------------------------------------------------------------------------
// MAIN Routine
//------------------------------------------------------------------------------------
//
// Main routine configures the crossbar and SMBus, and tests
// the SMBus interface between the three EEPROMs
void ResetRealClock(void)
{
while (SM_BUSY); // Wait for SMBus to be free.
SM_BUSY = 1; // Occupy SMBus (set to busy)
SMB0CN = 0x44; // SMBus enabled, ACK on acknowledge cycle
BYTE_NUMBER = 0; // 2 address bytes.
COMMAND = (CLOCK3530_ADDRESS_RESET | READ); // Chip select + READ
STA = 1; // Start transfer
while (SM_BUSY); // Wait for transfer to finish
}
//======================写S-3530A内部实时数据寄存器程序=====================
//功能:将设定年、月、日、星期、时、分、秒数据写入S-3530A |
//入口:发送数据放在年、月、日、星期、时、分、秒各寄存器 |
//出口:NONE |
//==========================================================================
void SetRealClock(void)
{
while (SM_BUSY); // Wait for SMBus to be free.
SM_BUSY = 1; // Occupy SMBus (set to busy)
SMB0CN = 0x44; // SMBus enabled, ACK on acknowledge cycle
BYTE_NUMBER = 7; // 2 address bytes.
COMMAND = (CLOCK3530_ADDRESS_DATEHOUR | WRITE); // Chip select + WRITE
I2CDataBuff = &RealTime.ClockString[0]; // Data to be writen
STA = 1; // Start transfer
}
//==================读S-3530A实时数据寄存器子程序===========================
//功能:从S-3530A读入当前时间数据 |
//入口:NONE |
//出口:接收数据放在年、月、日、星期、时、分、秒各寄存器 |
//==========================================================================
void GetRealClock(void)
{
while (SM_BUSY); // Wait for SMBus to be free.
SM_BUSY = 1; // Occupy SMBus (set to busy)
SMB0CN = 0x44; // SMBus enabled, ACK on acknowledge cycle
BYTE_NUMBER = 7; // 2 address bytes.
COMMAND = (CLOCK3530_ADDRESS_DATEHOUR | READ); // Chip select + READ
I2CDataBuff = &RealTime.ClockString[0]; // Data to be writen
STA = 1; // Start transfer
while (SM_BUSY); // Wait for transfer to finish
}
//============================写状态寄存器程序==============================
//功能:读/写S-3530A状态寄存器,对S-3530A进行设置 |
//入口:NONE 出口:NONE |
//==========================================================================
unsigned char GetRealClockStatus(void)
{
unsigned char result;
while (SM_BUSY); // Wait for SMBus to be free.
SM_BUSY = 1; // Occupy SMBus (set to busy)
SMB0CN = 0x44; // SMBus enabled, ACK on acknowledge cycle
BYTE_NUMBER = 1;
COMMAND = (CLOCK3530_ADDRESS_STATUS | READ);
I2CDataBuff = &result;
STA = 1; // Start transfer
while (SM_BUSY); // Wait for transfer to finish
return result;
}
void SetRealClockStatus(unsigned char status)
{
while (SM_BUSY); // Wait for SMBus to be free.
SM_BUSY = 1; // Occupy SMBus (set to busy)
SMB0CN = 0x44; // SMBus enabled, ACK on acknowledge cycle
BYTE_NUMBER = 1;
COMMAND = (CLOCK3530_ADDRESS_STATUS | WRITE);
I2CDataBuff = &status;
STA = 1; // Start transfer
}
unsigned char revolve(unsigned char val)
{
char i;
unsigned char val1=0;
for (i=0;i<8;i++)
{
if (val&0x1)
val1++;
val1=_crol_(val1,1);
val=_cror_(val,1);
}
val1=_cror_(val1,1);
return val1;
}
//id Delay1ms(unsigned char T);
void SET_S3530A(CDateTime g_objDateTime )
{
unsigned char var ;
P0MDOUT |= 0x1D;
P1MDOUT |= 0x01;
SMB0CN = 0x44; // Enable SMBus with ACKs on acknowledge cycle
SMB0CR = -80; // SMBus clock rate = 100kHz.
EIE1 |= 2; // SMBus interrupt enable
EA = 1; // Global interrupt enable
SM_BUSY = 0; // Free SMBus for first transfer.
var = GetRealClockStatus();
ResetRealClock();
var = GetRealClockStatus();
SetRealClockStatus(0xc2);
var = GetRealClockStatus();
RealTime.RT.Year=g_objDateTime.year;
RealTime.RT.Month=g_objDateTime.month;
RealTime.RT.Day=g_objDateTime.day;
// RealTime.RT.Week=0x00;
RealTime.RT.Hour=g_objDateTime.hour;
RealTime.RT.Minute=g_objDateTime.minute;
RealTime.RT.Second=g_objDateTime.second;
SetRealClock();
}
/*
void TestI2C (void)
{
char year,month,day,week,hour,minute,second ;
Delay1ms(100);
Delay1ms(100);
Delay1ms(100);
Delay1ms(100);
Delay1ms(100);
Delay1ms(100);
Delay1ms(100);
Delay1ms(100);
Delay1ms(100);
GetRealClock();
year=RealTime.RT.Year;
month=RealTime.RT.Month;
day=RealTime.RT.Day;
week=RealTime.RT.Week;
hour=RealTime.RT.Hour&0x1f;
minute=RealTime.RT.Minute;
second=RealTime.RT.Second;
}
*/
CDateTime GetRealTime(void)
{
CDateTime Time ;
GetRealClock();
Time.year=RealTime.RT.Year;
Time.month=RealTime.RT.Month;
Time.day=RealTime.RT.Day;
// week=RealTime.RT.Week;
Time.hour=RealTime.RT.Hour&0x1f;
Time.minute=RealTime.RT.Minute;
Time.second=RealTime.RT.Second;
return Time ;
}
//------------------------------------------------------------------------------------
// Interrupt Service Routine
//------------------------------------------------------------------------------------
void SMBUS_ISR (void) interrupt 7
{
switch (SMB0STA)
{ // SMBus 状态码SMB0STA 寄存器
// 主发送器/接收器起始条件已发送
case SMB_START:
SMB0DAT = COMMAND ; // 装入要访问的从器件的地址
STA = 0; // 手动清除START 位
break;
//主发送器/接收器重复起始条件已发送
// 该状态只应在读操作期间出现在存储器地址已发送并得到确认之后 ?
case SMB_RP_START:
SMB0DAT = COMMAND; // COMMAND 中应保持从地址 + R.
STA = 0;
break;
// 主发送器从地址 + WRITE 已发送收到ACK
case SMB_MTADDACK:
// 主发送器数据字节已发送收到ACK
case SMB_MTDBACK:
if (BYTE_NUMBER)
{
SMB0DAT = revolve(*I2CDataBuff); // If R/W=WRITE, load byte to write.
I2CDataBuff++;
BYTE_NUMBER--;
}
else
{
STO = 1; SM_BUSY = 0; // Free SMBus
}
break;
// 主发送器从地址 + WRITE 已发送收到NACK
// 从器件不应答发送STOP + START 重试
case SMB_MTADDNACK:
STO = 1; STA = 1;
break;
// 主发送器数据字节已发送收到NACK
// 从器件不应答发送STOP + START 重试
case SMB_MTDBNACK:
STO = 1; STA = 1;
break;
// 主发送器竞争失败
// 不应出现如果出现重新开始传输过程
case SMB_MTARBLOST:
STO = 1; STA = 1;
break;
// 主接收器从地址 + READ 已发送,收到ACK
case SMB_MRADDACK:
AA = 1; // 在应答周期ACK
if (!BYTE_NUMBER)
{
STO = 1; SM_BUSY = 0; // 释放SMBus
}
break;
// 主接收器从地址 + READ 已发送收到NACK
// 从器件不应答发送重复起始条件重试
case SMB_MRADDNACK:
STA = 1;
break;
// 收到数据字节ACK 已发送
// 该状态不应出现因为AA 已在前一状态被清0 如果出现发送停止条件
case SMB_MRDBACK:
if (BYTE_NUMBER)
{
*I2CDataBuff=revolve(SMB0DAT);
I2CDataBuff++;
BYTE_NUMBER--;
}
if (!BYTE_NUMBER) AA= 0;
break;
// 收到数据字节NACK 已发送
// 读操作已完成读数据寄存器后发送停止条件
case SMB_MRDBNACK:
STO = 1;
SM_BUSY = 0; // 释放SMBus
break;
// 在本应用中所有其它状态码没有意义通信复位
default:
STO = 1; // 通信复位
SM_BUSY = 0;
break;
}
SI=0; // 清除中断标志
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -