搜索
bottom↓
回复: 3

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

[复制链接]

出0入0汤圆

发表于 2008-1-16 13:52:32 | 显示全部楼层 |阅读模式
/*****************************************************
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, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2008-1-16 13:53:39 | 显示全部楼层
汇编编译已经通过,我现在在用板子上一个LED在测试程序的运行!可惜...

出0入0汤圆

发表于 2013-8-3 10:13:49 | 显示全部楼层

出0入0汤圆

发表于 2013-8-3 14:11:12 | 显示全部楼层
iic搞了好久,还是不知道该怎么做,
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 23:40

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表