打印

IIC问题求助,每次程序都只鞥运行到_PA6=1;后面应答错误

[复制链接]
1054|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ztcad|  楼主 | 2013-6-9 15:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
程序如下:
//#include "main.h"
#include "HT49RA1.h"
/******************************************************************************************/
//定义宏
/******************************************************************************************/
//#define testbit(var,bitno) ((var)&(1<<(bitno)))
//#define bitset(var,bitno) ((var)|=(1<<(bitno)))
//#define bitclr(var,bitno) ((var)&=~(1<<(bitno)))                                                                                                                                  
//***************表格区****************//
#pragma vector timer_base @0x14        //时基中断
#pragma vector timer_rtc @0x18        //RTC中断
#define done _pa5        //done = pa.5
#define mode _pb4
#define rst _pb3
#define left _pb2
#define dec _pb1
#define add _pb0
//#define SDA        _pa4
#define IIC_SDA        _pa1
#define IIC_SCL        _pa3
#define WP  _pa4        //
  void        ram_clr(void);
//  void        lcd_test(void);
//  void        lcd_clear(void);
  void        lcd_test_clear(unsigned char test);
  void        show_lock_on_auto_off(void);
  void        DisplayLcd(unsigned char addr,unsigned char data1);
  void        DisplayLcd_67(unsigned char addr,unsigned char data1);
//void        showRTC(void);
//void        showRTC_temp(void);

  void        Time_pd(void);
  void        Time_buchang(void);
  void        time_tz(void);

  void         time_realy(void);
//  void         time_basejs(void);
  void        wd_set_add(void);
  void        wd_set_dec(void);
  void        wd_set_left(void);
  void        wd_set(void);

  void        set_mode_add(void);
  void        set_rst(void);
  void        set_left(void);
  void        set_dec(void);
  void        set_add(void);

  void        set_on_off_show(void);

  void        month_pd(void);
  void        day_pd(void);
  void         set_wd_show(void);
  void        display(unsigned char addr1,unsigned char s_ram);
  void        display_67(unsigned char addr1,unsigned char s_ram);
  void         clearram23(void);

  void         clearram(unsigned char addr3);
  void         displayns(void);

  unsigned char b16_10(unsigned char temp0);
  unsigned char Read_Key(void);            
  void        show_day_adjust(void);       
  void         time_setjs(void);
  void        clr_lock_on_auto_off(void);
  void        time_run_adj_show(void);
  void        time_left(void);
  void        time_dec(void);
  void        time_add(void);
//void        export_time_adj(void);
  void        export_mode_3s(void);                                                                        
  void        Time_realy(void);
  void        displayweek(unsigned char week_show);
//  void        index_set_time(void);
  void        set_week_import(void);
  void        set_week_export(void);
  void        min_hour_set_import(void);
  void        min_hour_set_export(void);

//eeprom.c
//  void WREPP(unsigned char *str,unsigned char count,unsigned char addr,unsigned char WR_RD);
  void Byte_WR(void);
  void eeprom_write(unsigned char WRITE_SJ);
  void RDEPP(unsigned char ADDR);
//  void RDEPP(unsigned char *str,unsigned char count);
  void Byte_RD(void);
  void BSTART(void);
  void BSTOP(void);
  unsigned char ACK_WR(void);
  void ACK_RD(void);
//  void I2C_busy(void);
//  void nop_nop(void);
//  void eeprom_write(void);
  void eeprom_read_preset(void);
  
  
  void delay(unsigned int t);
void delay_IIC(void);
void IIC_Init(void);
void IIC_start(void);
void IIC_stop(void);
bit IIC_Tack(void);
void IIC_single_byte_write(unsigned char Daddr,unsigned char Waddr,unsigned char Data);
unsigned char IIC_single_byte_read(unsigned char Daddr,unsigned char Waddr);
void IIC_write_byte(unsigned char Data);
unsigned char IIC_read_byte(void);
void IIC_BUSY(void);
  
/******************************************************************************************/
  unsigned char        LcdRam[18] @ 0x140;        //Lcd Ram
/******************************************************************************************/
#pragma rambank0

  unsigned char         delay_keys;
  unsigned char        bcock @ 0xFF;        //数据全部清零

  unsigned char        WRITE_SJ;                    //纬度,+为N维,-为S维
  unsigned char        READ_SJ;                    //纬度,+为N维,-为S维


  unsigned char vol_left;                //左移判断

  unsigned char index;

  unsigned char i;       
  unsigned char temp;        //纬度时间调整用
unsigned char wr_rong;

unsigned char Data3;

  unsigned char TXBUF,RXBUF,Bit_CT,Byte_CT;

  bit        bit_lock;                                //手/自动标志位
  bit        bit_on;
  bit        bit_auto;
  bit        bit_off;
  bit        bit_rtc;                        //0.5s判断标志位

//bit        bit_runyear;                        //天加1标志位

  bit bit_min;                        //动作点判断用

  bit        bit_work;                        //工作标志位
  bit        bit_set_on_off_menu;
  bit        bit_set_wd_menu;
  bit        bit_key_dec_1s;
  bit        bit_key_add_1s;
  bit        bit_mode_add;
  bit        bit_mode_flag;
  bit        bit_left_flag;
  bit        bit_mode_add_first;
  bit bit_power_on;
bit bit_lcd_on;
bit bit_key_occur;
bit bit_time_set_to_base;
bit bit_eeprom;
bit bit_eeprom_finish;
//按键宏定义
#define key_left_3s                12
#define key_rst_3s                11
#define key_dec_1s                10
#define key_add_1s                9
#define key_mode_3s                8
#define key_mode_rst        7
#define key_mode_add        6
#define key_mode                5
#define key_rst                        4
#define key_left                3
#define key_dec                        2
#define key_add                        1
#define key_no                        0


#define k_set_num                24
#define array_index                48
#define array_1_index        24

//#define SDA_OUT        0X00        //SDA SCL均为输出
//#define SDA_IN        0X10        //SDA为输入 SCL为输出
//#define EE_WR        0XA0//1010 A2A1A00
//#define EE_RD        0XA1//1010 A2A1A01
#define EE_WR        0XA6//1010 A2A1A00 A1=1;A0=1
#define EE_RD        0XA7//1010 A2A1A01 A1=1;A0=1
#define READ        0X01
#define WRITE        0X00
#pragma norambank
//#pragma norambank
/***************************************************/
//写EEPROM函数WREPP
//A1=1;A0=1;WP=写保护
/***************************************************/
//void        WREPP(unsigned char *str,unsigned char count,unsigned char addr,unsigned char WR_RD)
/*
void        main(void)
{
        _qosc = 0;        //?????
        _delay(10000);
        ram_clr();        //CLR RAM
       
        _lcdc=0x03;        //LCD?? RTC??
        for (i=0;i<18;i++)
        LcdRam = 0xf;        //lcd show test;       
        _delay(10000);
        _emi = 1;        //????
//        _tbf = 0;
//        while(sec<3)
//        {
//                _etbi = 1;        //??????
                _emi = 1;        //????
                _halt();
//        }

//        sec = 0;
        _qosc = 1;
//        lcd_clear();
        for (i=0;i<18;i++)
                LcdRam = 0;

        while(1)
        {
                _pcc=1;
                _nop();_nop();
            SCL=1;
                _nop();_nop();
            if(SDA)//如SDA为0则总线忙
                {
                        break;
                }
                else
                {
                        SDA=1;//把SDA强制拉高
                        _pcc=0;
                    _nop();
                }
                        done = 0;
//先测试写保护
                        WP = 1;
                        eeprom_write(0xaa);//地址固定写0
                        if(wr_wrong==1)
                        {
                               
                                WP = 0;        //close write protect
                _pcc=1;
                _nop();_nop();
            SCL=1;
                _nop();_nop();
            if(SDA)//如SDA为0则总线忙
                {
                        break;
                }
                else
                {
                        SDA=1;//把SDA强制拉高
                        _pcc=0;
                    _nop();
                }
                                eeprom_write(0xaa);       
                _pcc=1;
                _nop();_nop();
            SCL=1;
                _nop();_nop();
            if(SDA)//如SDA为0则总线忙
                {
                        break;
                }
                else
                {
                        SDA=1;//把SDA强制拉高
                        _pcc=0;
                    _nop();
                }                               
                                eeprom_read_preset();                       
                                if(done)
                                {
                                //        _emi = 1;        //????
                                        _halt();
                                }
                                done = 0;
                                wr_wrong = 0;               
                        }
                        else
                        {
                                done = 0;
                        }


        }
}

void        ram_clr(void)
{
        _rtcc=0x07;        //????????
        _intc0=0;
        _tmr0c=0x08;
        _tmr1c=0x08;
        done=0;                //???IO?
        _pa=0;                //初始化IO口       
        _pc=0;
        _pcc=0x01;
        _pd=0x0f;
        _intc1=0;

        _bp=0;                        //??????
        _mp0=0x60;//???????????9????????????bug;
        bcock=0x9F;
loop_ram_clr:
        _iar0=0;
        _mp0++;
        bcock--;
        if(bcock)
                goto loop_ram_clr;
               


        bit_auto = 1;
        bit_off = 1;

}
/*
void WREPP(unsigned char temppp,unsigned char addr)
{
        unsigned char i;

//        while(bit_eeprom)
//        {

                        BSTART();
//                Byte_CT=count+2;
                        i=0;
//                while(Byte_CT)
//                {
        WREPP_GOON:
                        switch(i)
                        {
                                case 0:TXBUF=EE_WR;break;
                                case 1:TXBUF=addr;break;
                                default:TXBUF=temppp;break;
                        }
                        Byte_WR();
                        while(ACK_WR()==0)
                        {
                                if(temp++>=10000)        //超时无应答则退出
                                {
                                //        wr_wrong = 1;
                                        goto WREPP_ERR;
                                }

                        }

                                if(++i>=3)
                                {
                                //        ++str;
//                                --Byte_CT;
//                                        bit_eeprom=0;
                                        BSTOP();
                                //        bit_eeprom_finish=1;        //eeprom操作完毕

                                        goto WREPP_RIGHT;
                                }
                                else
                                goto WREPP_GOON;        //未完成写操作,继续
WREPP_ERR:

                                done = 0;
                                wr_wrong = 1;                        //写操作错误
                                goto WREPP_END;
WREPP_RIGHT:
                                wr_wrong = 0;                //写操作正确
WREPP_END:
                        _nop();
                        BSTOP();               
}
/***************************************************/
//发送1字节数据子程序Byte_WR
/***************************************************/
/*
void Byte_WR(void)
{       
//        _pa=SDA_OUT;
        _pcc=0;
        Bit_CT=0x08;        //设置字节长度
        while(Bit_CT)
        {
                _nop();_nop();
                SCL=0;
                SDA=0;
                _nop();_nop();
//                if(testbit(TXBUF,7))
                if(TXBUF & 0b10000000)
                {SDA=1;}
                _nop();_nop();
                SCL=1;
                TXBUF<<=1;        //移位,准备发送下一位数据
                Bit_CT--;
        }
        _nop();
        SCL=0;
}
/***************************************************/
//读EEPROM函数RDEPP
/***************************************************/
//void RDEPP(unsigned char *str,unsigned char count)
/*
void RDEPP(unsigned char ADDR)
{

                        BSTART();
                        TXBUF=EE_WR;

                        Byte_WR();
                        while(ACK_WR()==0)
                        {
                                if(temp++>=10000)        //超时无应答则退出
                                {
                                        wr_wrong = 1;
                                        goto RDEPP_END;
                                }

                        }
                        TXBUF=ADDR;//写地址再读出
                        Byte_WR();
                        while(ACK_WR()==0)
                        {
                                if(temp++>=10000)
                                {
                                        wr_wrong = 1;
                                        goto RDEPP_END;
                                }
                        }
                        TXBUF=EE_RD;        //地址写完后接着送读指令

                        Byte_WR();
                        while(ACK_WR()==0)
                        {
                                if(temp++>=10000)        //超时无应答则退出
                                {
                                        wr_wrong = 1;
                                        goto RDEPP_END;
                                }

                        }


                Byte_RD();

                READ_SJ=RXBUF;//读出数据放READ_SJ

//                if(--count)
                        ACK_RD();
//        }

//        if(bit_eeprom)
//                bit_eeprom_finish=1;        //eeprom操作完毕
        RDEPP_END:
        _nop();
        BSTOP();       
}
/***************************************************/
//接收1字节数据子程序Byte_RD
/***************************************************/
/*
void Byte_RD(void)
{       
        SCL=0;
//        _pa=SDA_IN;
        _pcc=1;

        RXBUF=0;
        Bit_CT=0x08;        //设置字节长度
        while(Bit_CT)
        {
                _nop();_nop();
                SCL=0;
                _nop();_nop();
                RXBUF<<=1;//移位,准备接收下一位数据
                if(SDA)
//                {bitset(RXBUF,0);}
                {RXBUF |= 0b00000001;}
                _nop();_nop();
                SCL=1;
                Bit_CT--;
        }
}
/***************************************************/
//总线查询程序I2C_busy
/***************************************************/

/***************************************************/
//开始命令程序BSTART
/***************************************************/
/*
void BSTART(void)
{
        SCL=1;
        SDA=0;
//        _pa=SDA_OUT;
        _pcc=0;

}
/***************************************************/
//停止命令程序BSTOP
/***************************************************/
/*
void BSTOP(void)
{       
        SCL=0;
        SDA=0;
//    _pa=SDA_OUT;
        _pcc=0;
    _nop();_nop();
        SCL=1;
    _nop();_nop();
        SDA=1;        //发出停止命令
    _nop();_nop();
        SCL=0;
}
/***************************************************/
//应答程序ACK_WR
/***************************************************/
/*
unsigned char ACK_WR(void)
{       
        SCL=0;
//        _pa=SDA_IN;
        _pcc=1;
    _nop();_nop();
    SCL=1;
    _nop();_nop();
    if(!SDA)//如SDA为0则为有应答
        {
                SCL=0;
                return 1;
        }
        else
        {
                return 0;
        }
}
/***************************************************/
//应答程序ACK_RD
/***************************************************/
/*
void ACK_RD(void)
{       
        SCL=0;
//    _pa=SDA_OUT;
        _pcc=0;       
    SDA=0;
    _nop();_nop();
    SCL=1;
    _nop();_nop();
}
/***************************************************/
//应答程序ACK_RD
/***************************************************/
/*void nop_nop(void)
{       
        _nop();_nop();
}
/***************************************************/
//应答程序ACK_RD
/***************************************************/
/*
void eeprom_write(unsigned char WRITE_SJ)
{
//        bit_eeprom=1;        //如无中断则eeprom操作继续
//        bit_eeprom_finish=0;        //eeprom操作开始

                WREPP(WRITE_SJ,0);//地址放0

//                bit_eeprom_finish=0;

}
/***************************************************/
//应答程序ACK_RD
/***************************************************/
/*
void eeprom_read_preset(void)
{
//修复eeprom不连接时会下载错误数据的bug;
//        bit_eeprom=1;        //如无中断则eeprom操作继续
//        bit_eeprom_finish=0;        //eeprom操作开始
        READ_SJ = 0;

        RDEPP(0);

        WREPP(0xff,0);        //clearmemory
        if(wr_wrong)
        {
                done = 0;
                goto read_end;
        }
        if(READ_SJ==0xaa)                //读出结果与写入一致                                       
                done=1;
        else
                done = 0;
read_end:
        _nop();
}
*/



void main(void)                     
{

    _qosc = 0;
    _emi = 0;
IIC_Init();//初始化IIC总线。

    while(1)                     
    {
            _pa2 = 0;
            _pa0 = 0;
            _pa6 = 0;
            _pa7 = 0;
            done = 0;

                WP = 0;
                delay(5);//延时
                IIC_BUSY();
                IIC_single_byte_write(0xa6,0x02,0xaa);//xie状态

                if(wr_rong == 0)
                {
                        _pa6 = 1;
                           _delay(100);
                                IIC_BUSY();
                        Data3 = IIC_single_byte_read(0xa6,0x02);//读状态
                        if(wr_rong==0)
                        {
                                _pa0 = 1;
                        }
                        _delay(100);
                                IIC_BUSY();
                        IIC_single_byte_write(0xa6,0x02,0xff);//clear eeprom
                       
                        if(wr_rong == 0)
                        {
                                _pa7 = 1;
                                if(Data3 == 0xaa)
                                {
                                        done = 1;
                                        _halt();
                                }
                        }
                }
    }
}






//==========================功能子函数===============================
void delay(unsigned int t)
{//延时函数
    while(t){t--;};                    //延时循环计数
}
//-------------------------------------------------------------------
/********
void delay_IIC(void)   
{//IIC总线限速延时函数。
;;
}
************/
void IIC_BUSY(void)
{
        IIC_SDA = 1;
        _nop();
        IIC_SCL = 1;
        _nop();       
        IIC_SCL = 0;       
        while(IIC_SDA==0)
        {
                IIC_SDA = 1;
        }
}
//-------------------------------------------------------------------
void IIC_Init(void)
{//IIC总线初始化函数
//        _pcc = 1;
    IIC_SDA=1;//释放IIC总线的数据线。
    IIC_SCL=1;//释放IIC总线的时钟线。
  //  _pcc = 0;
}
//-------------------------------------------------------------------
void IIC_start(void)
{//IIC总线产生起始信号函数  
    IIC_SDA=1;//拉高数据线
    _nop();
     IIC_SCL=1;//拉高时钟线
      _nop();
     IIC_SDA=0;//在时钟线为高电平时,拉低数据线,产生起始信号。
      _nop();
    IIC_SCL=0;//拉低时钟线
}
//-------------------------------------------------------------------
void IIC_stop(void)
{//IIC总线产生停止信号函数
    IIC_SDA=0;//拉低数据线
     _nop();
    IIC_SCL=1;//拉高时钟线。
     _nop();
    IIC_SDA=1;//时钟时线为高电平时,拉高数据线,产生停止信号。
     _nop();
    IIC_SCL=0;//拉低时钟线。   
}
//-------------------------------------------------------------------
bit IIC_Tack(void)
{//接收应答信号函数
    bit ack;//定义一个位变量,来暂存应答状态。
    IIC_SDA=1;//释放数据总线,准备接收应答信号。
     _nop();
    IIC_SCL=1;//拉高时钟线。
     _nop();
    IIC_SCL = 0;//...................
    ack = 1;
    for(temp=255;temp>0;temp--)
    {
            if(IIC_SDA==0)
            {
                    ack = 0;
                    break;
            }
    }

     _nop();
    return ack;//返回应答信号的状态,0表示应答,1表示非应答。
}
//-------------------------------------------------------------------
void IIC_write_byte(unsigned char Data)
{//向IIC总线写入一个字节的数据函数
    unsigned char i;
     for(i=0;i<8;i++)//有8位数据
    {
        IIC_SDA=Data&0x80;//写最高位的数据
           _nop();
          IIC_SCL=1; //拉高时钟线,将数写入到设备中。
         _nop();
        IIC_SCL=0;//拉低时钟线,允许改变数据线的状态
         _nop();
        Data=Data<<1;//数据左移一位,把次高位放在最高位,为写入次高位做准备
    }
}
//-------------------------------------------------------------------
unsigned char IIC_read_byte()
{//从IIC总线读取一个字节的数据函数
    unsigned char i;
    unsigned char Data;       //定义一个缓冲寄存器。
    for(i=0;i<8;i++)//有8位数据
    {
        IIC_SCL=1;//拉高时钟线,为读取下一位数据做准备。
         _nop();
        Data=Data<<1;//将缓冲字节的数据左移一位,准备读取数据。
         _nop();
        
        if(IIC_SDA)//如果数据线为高平电平。
            Data=Data|0x1;//则给缓冲字节的最低位写1。
        IIC_SCL=0;//拉低时钟线,为读取下一位数据做准备。
         _nop();
    }
    return Data;//返回读取的一个字节数据。
}
//-------------------------------------------------------------------
void IIC_single_byte_write(unsigned char Daddr,unsigned char Waddr,unsigned char Data)
{//向任意地址写入一个字节数据函数
    IIC_start();//产生起始信号
    IIC_write_byte(Daddr);//写入设备地址(写)
    if(IIC_Tack()!=0){wr_rong=1;goto iic_write_out;}//等待设备的应答
    IIC_write_byte(Waddr);//写入要操作的单元地址。
    if(IIC_Tack()!=0){wr_rong=1;goto iic_write_out;}//等待设备的应答
    IIC_write_byte(Data);//写入数据。
    if(IIC_Tack()!=0){wr_rong=1;goto iic_write_out;}//等待设备的应答
    wr_rong = 0;
iic_write_out:
        IIC_stop();//产生停止符号。
}
//-------------------------------------------------------------------
unsigned char IIC_single_byte_read(unsigned char Daddr,unsigned char Waddr)
{//从任意地址读取一个字节数据函数
    unsigned char Data;//定义一个缓冲寄存器。

    IIC_start();//产生起始信号
    IIC_write_byte(Daddr);//写入设备地址(写)
    if(IIC_Tack()!=0){wr_rong=1;goto iic_read_out;}//等待设备的应答
    _pa2 = 1;
    IIC_write_byte(Waddr);//写入要操作的单元地址。
    if(IIC_Tack()!=0){wr_rong=1;goto iic_read_out;}//等待设备的应答
   
    IIC_start();//产生起始信号
    IIC_write_byte(Daddr+1);//写入设备地址(读)。
    if(IIC_Tack()!=0){wr_rong=1;goto iic_read_out;}//等待设备的应答
    Data=IIC_read_byte();//写入数据。
    IIC_SDA = 1;        //stop read
    IIC_stop();//产生停止符号。
    wr_rong = 0;
    //-------------------返回读取的数据--------------------
    return Data;//返回读取的一个字节数据。
iic_read_out:
    IIC_stop();//产生停止符号。
        return 0;
}

相关帖子

沙发
119746200| | 2013-6-10 19:56 | 只看该作者
看不懂啥意思

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

1

帖子

0

粉丝