datounaonao 发表于 2008-1-16 13:52:32

请高手帮我分析一下用IIC通信的程序!谢谢

/*****************************************************
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_W0X64   //SD2068A写从地址
#define SLA_R 0X65    //SD2068A读从地址

//启动状态
#define START 0X08//启动总线
#define RESTART 0X10//重新启动总线

//主发送模式各种状态
#define MT_SLA_ACK0X18 //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_LOST0X38//丢失总线控制权

//主接受模式各种状态
#define MR_SLA_ACK 0X40//SLA_R已发送并收到ACK
#define MR_SLA_NACK 0X48//SLR_R已发送并收到NACK
#define MR_DATA_ACK0X50//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={0x20,0x53,0x98,0x06,0x12,0x01,0x08 };
                                             //定义时间为2008年1月12日星期六18点53分20秒
                                             //time=second,time=minute,time=hour,time=week,time=data
                                             //time=month,time=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
    elsereturn(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);
    write_time_byte(time);
    write_time_byte(time);//最高位为1表示是24小时制的,如18点,表示为10011000
    write_time_byte(time);
    write_time_byte(time);
    write_time_byte(time);
    write_time_byte(time); //依次向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=read_time_byte()&0X7F; //读出秒数据
    time=read_time_byte()&0X7F; //读出分数据
    time=read_time_byte()&0X3F; //读出时数据,要屏蔽小时的最高位,否则会因是24小时制而读出错误数据
    time=read_time_byte()&0X07; //读出星期数据
    time=read_time_byte()&0X3F; //读出日数据
    time=read_time_byte()&0X1F; //读出月数据
    time=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测试,似乎通不过,请我该怎么继续?

datounaonao 发表于 2008-1-16 13:53:39

汇编编译已经通过,我现在在用板子上一个LED在测试程序的运行!可惜...

不再为你停留 发表于 2013-8-3 10:13:49

{:smile:}{:smile:}{:smile:}

yanghuai1023 发表于 2013-8-3 14:11:12

iic搞了好久,还是不知道该怎么做,{:dizzy:}
页: [1]
查看完整版本: 请高手帮我分析一下用IIC通信的程序!谢谢