|
/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.3 Evaluation
Automatic Program Generator
?Copyright 1998-2007 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project : twi_sd2068
Version :
Date : 2008-1-11
Author : Freeware, for evaluation and non-commercial use only
Company :
Comments:
Chip type : ATmega8
Program type : Application
Clock frequency : 3.686400 MHz
Memory model : Small
External SRAM size : 0
Data Stack size : 256
*****************************************************/
#include <mega8.h>
// I2C Bus functions
#asm
.equ __i2c_port=0x15 ;PORTC
.equ __sda_bit=4
.equ __scl_bit=5
#endasm
#include <i2c.h>
#include <DELAY.H>
#define uchar unsigned char
#define uint unsigned int
#define false 0
#define right 1
//定义TWCR里各位
#define TWINT 7
#define TWEA 6
#define TWSTA 5
#define TWSTO 4
#define TWWC 3
#define TWEN 2
#define TWIE 0
//SD2068A 7位器件地址为0110010, 第8位为0表示写,为1表示读.定义SLA_W,SLA_R如下
#define SLA_W 0X64 //SD2068A写从地址
#define SLA_R 0X65 //SD2068A读从地址
//启动状态
#define START 0X08 //启动总线
#define RESTART 0X10 //重新启动总线
//主发送模式各种状态
#define MT_SLA_ACK 0X18 //SLA_W已发送并收到ACK
#define MT_SLA_NACK 0X20 //SLA_W已发送并收到NACK
#define MT_DATA_ACK 0X28 //DATA已发送并收到ACK
#define MT-DATA_NACK 0X30 //DATA已经发送并收到NACK
#define MT_LOST 0X38 //丢失总线控制权
//主接受模式各种状态
#define MR_SLA_ACK 0X40 //SLA_R已发送并收到ACK
#define MR_SLA_NACK 0X48 //SLR_R已发送并收到NACK
#define MR_DATA_ACK 0X50 //DATA已经发送并收到ACK
#define MR_DATA_NACK 0X58 //DATA已经发送并收到NACK
#define MR_LOST 0X38 //丢失总线控制权
//定义IIC接口行为
#define start() TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN); //发送开始信号
#define stop() TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN) //发送停止信号
#define waitack() {while(!(TWCR&(1<<TWINT)));} //等待发送完成,即将TWINT置位
#define checkack() TWSR&0XF8 //检查状态寄存器的状态时,应将预分频位清0
#define sendbyte(x) {TWDR=(x);TWCR=(1<<TWINT)|(1<<TWEN);} //往时间片寄存器写一个字节数据
#define revnckbyte() TWCR=(1<<TWINT)|(1<<TWEN) // 从时间片寄存器读一个字节数据,不返回应答
#define revackbyte() TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWEA) //从时间片寄存器读一个字节数据,并返回应答
uchar time[7]={0x20,0x53,0x98,0x06,0x12,0x01,0x08 };
//定义时间为2008年1月12日星期六18点53分20秒
//time[0]=second,time[1]=minute,time[2]=hour,time[3]=week,time[4]=data
//time[5]=month,time[6]=year
//IIC初始化
void IICinit(void){
TWCR=0X00; //disable iic
TWBR=0X010; //set 波特率
TWSR=0X00; //set 预分频位
TWCR=0X44; //enable iic
}
//写入字节数据
uchar write_time_byte(uchar a){
sendbyte(a); //将a写入时间片相应的寄存器
waitack(); //等待写完成
switch(a){
case SLA_W: if(checkack()!=MT_SLA_ACK) return false;//如果写入的是SLA_W(SD2068A写从地址),判断是否写成功
else return right;
break;
case SLA_R: if(checkack()!=MR_SLA_ACK) return false; //如果写入的是SLA_R(SD2068A读从地址),判断是否写成功
else return right;
default: if(checkack()!=MT_DATA_ACK) return false; //如果写入的是时间片寄存器地址或是数据,判断是否写成功
else return right;
break;
}
}
//读出字节数据
uchar read_time_byte(){
revackbyte(); //从时间片相应的寄存器读出一字节数据
waitack(); //等待读完成
if(checkack()!=MR_DATA_ACK) return false; //检查TWSR的状态,判断是否读成功,成功则返回TWDR
else return(TWDR);
}
//写SD2068A允许函数,置WRTC1,WRTC2,WRTC3为1,使时间片处于写允许状态
void write_allow(void){
start(); //发送开始信号
waitack(); //等待发送完成,即等TWINT置位
if(checkack()!=START) // return false; //检查开始信号是否发送成功
write_time_byte(SLA_W); //发送SD2068A的写器件地址
write_time_byte(0X10); //WRTC1所在的寄存器地址
write_time_byte(0X80); //发送要写的寄存器地址10H,置WRTC1为1
start(); //再次发送开始信号
waitack(); //等待发送完成,即等TWINT置位
if(checkack()!=RESTART) //return false; //检查重新开始信号是否发送成功
write_time_byte(SLA_W); //发送SD2068A的写器件地址
write_time_byte(0X0F); //WRTC2,WRTC3所在的寄存器地址
write_time_byte(0X84); //发送要写的寄存器地址0FH,置WRTC2,WRTC3为1
stop(); //发送停止信号
}
//写SD2068A禁止函数,置WRTC1,WRTC2,WRTC3为0,使时间片处于写禁止状态
void write_ban(void){
start(); //发送开始信号
waitack(); //等待发送完成,即等TWINT置位
if(checkack()!=START) // return false; //检查开始信号是否发送成功
write_time_byte(SLA_W); //发送SD2068A的写器件地址
write_time_byte(0X0F); //WRTC2,WRTC3所在的寄存器地址
write_time_byte(0X00); //将WRTC2和WRTC3位置0,然后地址加1变为0X10,这是WRTC1所在的寄存器地址
write_time_byte(0X00); //将WRTC1位置0,此时WRTC1,WRTC2,WRTC3均为0,此时SD2068A处于写禁止状态
stop(); //发送停止信号
}
// 写时间片函数
uchar write_timer(){
write_allow(); //置SD2068A处于写允许状态
start(); //发送开始信号
waitack(); //等待发送完成,即等TWINT置位
if(checkack()!=START) return false; //检查开始信号是否发送成功
write_time_byte(SLA_W); //发送SD2068A的7位器件地址0110010和一位写命令0,即0x64(SLA_W)
write_time_byte(0X00); //SD2068A进入写状态后,在发一个一个字节数据,高三位是传输模式,写状态时为"000",低5位为其内部地址(00H-1FH)
//此时从00H开始写起
write_time_byte(time[0]);
write_time_byte(time[1]);
write_time_byte(time[2]); //最高位为1表示是24小时制的,如18点,表示为10011000
write_time_byte(time[3]);
write_time_byte(time[4]);
write_time_byte(time[5]);
write_time_byte(time[6]); //依次向00H到06H对应的秒,分,时,星期,日,月,年相应的寄存器写数据
stop();//结束写数据过程
write_ban(); //置SD2068A处于写禁止状态
}
//读时间片函数
uchar read_timer(){
start(); //发送开始信号
waitack(); //等待发送完成,即等TWINT置位
if(checkack()!=START) return false; //检查开始信号是否发送成功
write_time_byte(SLA_W);
write_time_byte(0X00);
start(); //重新发送开始信号,以改变两线接口数据传输方向
waitack(); //等待发送完成,即等TWINT置位
if(checkack()!=RESTART) return false; //检查重新开始信号是否发送成功
write_time_byte(SLA_R); //发7位器件地址0110010和一位读命令1,即0x64(SLA_R)
time[0]=read_time_byte()&0X7F; //读出秒数据
time[1]=read_time_byte()&0X7F; //读出分数据
time[2]=read_time_byte()&0X3F; //读出时数据,要屏蔽小时的最高位,否则会因是24小时制而读出错误数据
time[3]=read_time_byte()&0X07; //读出星期数据
time[4]=read_time_byte()&0X3F; //读出日数据
time[5]=read_time_byte()&0X1F; //读出月数据
time[6]=read_time_byte()&0XFF; //读出年数据
stop(); //结束信号
}
void main(void)
{
PORTC=0x08;
DDRC=0x08;
MCUCR=0x00;
TIMSK=0x00;
ACSR=0x80;
SFIOR=0x00;
IICinit();
write_timer();
while (1)
{
read_timer();
delay_ms(1000);
};
}
为什么在write_time_byte里,判断TWSP状态的时候,我用LED测试,似乎通不过,请我该怎么继续? |
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|