前段时间写的,一个简单的iic时钟,采用的软件模拟的iic总线。单片机是atmega168,8m晶振。中文手册见附件。代码如下:
#include <iom168pv.h>
#include <macros.h>
#include "MyHeader.h"
#include "RTC.h"
//---------------------------------------------------------
//
// IIC起始
//
//---------------------------------------------------------
void IIC_Start(void)
{
RTC_SCL_OUT();
RTC_SDA_OUT();
RTC_SDA_1();
RTC_SCL_H();
N_NOP(80);
RTC_SDA_0();
N_NOP(80);
RTC_SCL_L();
N_NOP(80);
}
//---------------------------------------------------------
//
// IIC结束
//
//---------------------------------------------------------
void IIC_Stop(void)
{
RTC_SDA_OUT();
RTC_SDA_0();
RTC_SCL_H();
N_NOP(80);
RTC_SDA_1();
N_NOP(80);
}
//---------------------------------------------------------
//
// 发出一个ACK
//
//---------------------------------------------------------
void IIC_SentACK(void)
{
RTC_SDA_OUT();
RTC_SDA_1();
RTC_SCL_L();
N_NOP(80);
RTC_SDA_0();
N_NOP(80);
RTC_SCL_H();
N_NOP(80);
N_NOP(80);
RTC_SCL_L();
N_NOP(80);
}
//---------------------------------------------------------
//
// 等待一个ACK
//
//---------------------------------------------------------
unsigned char IIC_GetAck(void)
{
unsigned char ReturnFlag="NOT";
RTC_SDA_IN();
RTC_SCL_L();
N_NOP(80);
RTC_SCL_H();
N_NOP(80);
if ( RTC_SDA()==0x00 )
{
ReturnFlag = YES;
}
else
{
ReturnFlag = NOT;
IIC_Stop();
return ReturnFlag;
}
N_NOP(80);
RTC_SCL_L();
N_NOP(80);
return ReturnFlag;
}
//---------------------------------------------------------
//
// 写入一个字节
//
//---------------------------------------------------------
void IIC_WriteByte(unsigned char Data)
{
unsigned char i;
unsigned char Shift = 0x80;
RTC_SDA_OUT();
for ( i="0";i<8;i++ )
{
RTC_SCL_L();
N_NOP(80);
if ( (Data&Shift)!=0x00 )
{
RTC_SDA_1();
}
else
{
RTC_SDA_0();
}
Shift >>= 1;
N_NOP(80);
RTC_SCL_H();
N_NOP(80);
N_NOP(80);
RTC_SCL_L();
N_NOP(80);
}
}
//---------------------------------------------------------
//
// 移出一个字节
//
//---------------------------------------------------------
unsigned char IIC_ReadByte(void)
{
unsigned char i;
unsigned char Shift = 0x80;
unsigned char Data = 0x00;
RTC_SDA_IN();
for ( i="0";i<8;i++ )
{
RTC_SCL_L();
N_NOP(80);
N_NOP(80);
RTC_SCL_H();
N_NOP(80);
if ( RTC_SDA()!=0x00 )
{
Data |= Shift;
}
else
{
}
Shift >>= 1;
N_NOP(80);
RTC_SCL_L();
N_NOP(80);
}
return Data;
}
//---------------------------------------------------------
//
// 写入RTC寄存器
//
//---------------------------------------------------------
void Write_RTC_Reg(unsigned char Address,unsigned char Data)
{
IIC_Start();
IIC_WriteByte(RTC_WRITE_ADDR);
if ( IIC_GetAck()==YES )
{
}
else
{
}
IIC_WriteByte(Address);
if ( IIC_GetAck()==YES )
{
}
else
{
}
IIC_WriteByte(Data);
if ( IIC_GetAck()==YES )
{
}
else
{
}
IIC_Stop();
}
//---------------------------------------------------------
//
// 读出RTC寄存器
//
//---------------------------------------------------------
unsigned char Read_RTC_Reg(unsigned char Address)
{
unsigned char Data;
IIC_Start();
IIC_WriteByte(RTC_WRITE_ADDR);
if ( IIC_GetAck()==YES )
{
}
else
{
}
IIC_WriteByte(Address);
if ( IIC_GetAck()==YES )
{
}
else
{
}
IIC_Start();
IIC_WriteByte(RTC_READ_ADDR);
if ( IIC_GetAck()==YES )
{
}
else
{
}
Data = IIC_ReadByte();
IIC_Stop();
return Data;
}
//---------------------------------------------------------
//
// RTC初始化
//
//---------------------------------------------------------
void RTC_Init(void)
{
unsigned char i;
Write_RTC_Reg(0x07,0x91); //允许外部32768Hz的时钟
Write_RTC_Reg(0x08,0xca); //频率输出为1HZ
}
//---------------------------------------------------------
//
// 写入时间:秒分时日月年
//
//---------------------------------------------------------
void RTC_SET_Timer(unsigned char *pointer)
{
unsigned char i;
for ( i="0";i<7;i++ )
{
Write_RTC_Reg(0x00+i,*(pointer+i));
}
}
//---------------------------------------------------------
//
// 得到时间:秒分时日月年
//
//---------------------------------------------------------
void RTC_GET_Timer(unsigned char *pointer)
{
unsigned char i;
for ( i="0";i<7;i++ )
{
*(pointer+i) = Read_RTC_Reg(0x00+i);
}
}
//---------------------------------------------------------
//
// 不精确短延时
//
//---------------------------------------------------------
void N_NOP(unsigned char times)
{
unsigned char i;
for ( i="0";i<times;i++ )
{
NOP();
}
}
头文件RTC.h如下
#ifndef _RTC_H_
#define _RTC_H_
//根据需要改变相应的IO口
#define RTC_SCL_OUT() SET(DDRC,5)
#define RTC_SCL_L() CLR(PORTC,5)
#define RTC_SCL_H() SET(PORTC,5)
#define RTC_SDA_OUT() SET(DDRC,4)
#define RTC_SDA_IN() CLR(DDRC,4)
#define RTC_SDA_0() CLR(PORTC,4)
#define RTC_SDA_1() SET(PORTC,4)
#define RTC_SDA() (PINC&BIT(4))
#define RTC_WRITE_ADDR 0xde
#define RTC_READ_ADDR 0xdf
void IIC_Start(void);
void IIC_Stop(void);
void IIC_SentACK(void);
unsigned char IIC_GetAck(void);
void IIC_WriteByte(unsigned char Data);
unsigned char IIC_ReadByte(void);
void Write_RTC_Reg(unsigned char Address,unsigned char Data);
unsigned char Read_RTC_Reg(unsigned char Address);
void RTC_Init(void);
void RTC_SET_Timer(unsigned char *pointer);
void RTC_GET_Timer(unsigned char *pointer);
void N_NOP(unsigned char times);
#endif
用户1407682 2009-4-27 11:45