国产毛片a精品毛-国产毛片黄片-国产毛片久久国产-国产毛片久久精品-青娱乐极品在线-青娱乐精品

電子工程網(wǎng)

標(biāo)題: PIC24F之EEPROM讀寫中斷事件處理函數(shù)要點(diǎn)及說明 [打印本頁(yè)]

作者: hotpower    時(shí)間: 2009-4-2 22:57
標(biāo)題: PIC24F之EEPROM讀寫中斷事件處理函數(shù)要點(diǎn)及說明
/*-------------------------------------------------------------------------------------------------
                        PIC24F之EEPROM讀寫中斷事件處理函數(shù)要點(diǎn)及說明
注意: 這是一個(gè)通用的I2C/SMBUS通訊中斷處理程序
對(duì)于EEPROM來講,從機(jī)后面需要跟EEPROM需要讀寫的地址(I2CRegs.RWAddr)
對(duì)于SMBUS來說,從機(jī)后面需要跟SMBUS需要的命令(I2CRegs.RWAddr改為I2CRegs.CMD即可)
由于PIC24F的I2C不太標(biāo)準(zhǔn),I2C1STAT被搞得很倒塌!!一點(diǎn)都沒I2C的"大家閨秀"的樣子~~~
不過它的STOP還能激活中斷確實(shí)比LPCARM/AVR好一點(diǎn)點(diǎn)~~~

為什么I2C收發(fā)都用中斷呢???
這主要是為了高低速靈活變化的總線通訊所做,主要是SMBUS總線的通信.
菜農(nóng)在LPCARM/AVR上用此程序模板可謂不怕數(shù)據(jù)被干擾~~~

如果為I2cExit()也配上鉤子函數(shù),那么任何錯(cuò)誤都在手掌中~~~

這個(gè)PIC程序雖沒SMBUS的PEC校驗(yàn)部分,但"異步"還是完美的.
當(dāng)然也要注意對(duì)寫保護(hù)硬件管腳的控制時(shí)機(jī)的把握,原則是關(guān)保護(hù)的時(shí)間最短就更好~~~

菜農(nóng)本來PIC24F菜鳥已“畢業(yè)”,但還是“忍痛”發(fā)表出來~~~

主要看到人們編寫MCU程序太死板~~~特別是I2C程序.網(wǎng)上收發(fā)全中斷的很少,可以說幾乎沒有.

隨貼附老外倒塌的非中斷I2C狀態(tài)機(jī)讀寫程序i2cEmem.c~~~可以比較經(jīng)典和非典的差異在何處~~~

菜農(nóng)近期將整理出LPCARM和AVR的I2C/SMBUS/TWI/USI收發(fā)全中斷實(shí)戰(zhàn)例程供大家“游玩”~~~

如果精通DELPHI程序的人一定會(huì)為“事件驅(qū)動(dòng)”機(jī)制而癡迷~~~為什么不在MCU上"聲東擊西"呢???

"有事件才處理"---這才是編程的硬道理~~~輪循的“癡迷等待”最終還是“單相思”~~~

本程序附實(shí)戰(zhàn)結(jié)果圖.(因?yàn)椴宿r(nóng)的程序從來不空談社會(huì)主義~~~)

原本是在"雞蛋節(jié)"獻(xiàn)給大家,由于"憶苦思甜"沒發(fā)~~~就算是“臭蛋節(jié)”的禮物吧~~~

菜農(nóng) HotPower@126.com   2007.12.25 "雞蛋節(jié)"于大雁塔菜地
--------------------------------------------------------------------------------------------------*/
#include "i2c.h"

_PERSISTENT volatile I2CREGS I2CRegs;
_PERSISTENT volatile I2CBITS I2CBits;

void I2cInit(void)
{
unsigned int i;
    TRIS_WP   = PORTOUTMODE;//定義WP為輸出IO
    TRIS_SCL1 = PORTOUTMODE;//定義SCL為輸出IO
    TRIS_SDA1 = PORTINPUTMODE;//定義SDA為輸出入IO
    ODC_SCL1 = 1;//OC輸出
    ODC_SDA1 = 1;//OC輸出
    WP = 1;//寫保護(hù)
    I2CRegs.MaxCount = 0x200;//8KByte
    I2CRegs.I2CAddr = 0xa0;//器件地址
    I2CRegs.RWAddr = 0;//EEPROM讀寫地址
    I2CRegs.TxCount = 0;//發(fā)送數(shù)據(jù)字節(jié)個(gè)數(shù)
    I2CRegs.RxCount = 0;//接收數(shù)據(jù)字節(jié)個(gè)數(shù)
    for (i = 0; i < 16; i ++)
    {
        I2CRegs.TxBuffer = 0;//發(fā)送緩沖區(qū)清零
    }
    for (i = 0; i < 256; i ++)
    {
        I2CRegs.RxBuffer = 0;//接收緩沖區(qū)清零
    }

    I2C1CON = 0;
//    I2C1CONbits.A10M = 0;//7位地址模式
    I2C1CONbits.SCLREL = 1;
    I2C1MSK = 0;
    I2C1STAT = 0;
    _MI2C1IF = 0;
    _SI2C1IF = 0;
    I2C1BRG = (FCY / (2 * I2CBAUD)) - 1;//波特率計(jì)算
/*------------------------------------------------------------------------
    定義I2C串口2中斷優(yōu)先級(jí)位1111)
-------------------------------------------------------------------------*/
    IPC4bits.MI2C1P0 = 1;
    IPC4bits.MI2C1P1 = 1;
    IPC4bits.MI2C1P2 = 1;

    I2C1CONbits.I2CEN = 1;//允許I2C功能
    _MI2C1IE = 1;//允許主設(shè)備中斷

//    I2cStop();
}

/*------------------------------------------------------------------
    EEPROM讀塊函數(shù)(只能在回調(diào)函數(shù)I2CReadCallBack中得到讀出的數(shù)據(jù))
-------------------------------------------------------------------*/
void I2CReadBuffers(unsigned int E2RomAddr, unsigned int ReadSize)
{
    if (ReadSize && (ReadSize <= 256))
    {
        I2CRegs.TxCount = 0;
        I2CRegs.RxCount = ReadSize;
        I2CRegs.RWAddr = E2RomAddr;
        I2CRegs.I2CAddr |= 1;//0xa1
        I2cStart();
    }
}

void I2CReadByte(unsigned int E2RomAddr)
{
    I2CRegs.TxCount = 0;
    I2CRegs.RxCount = 1;
    I2CRegs.RWAddr = E2RomAddr;
    I2CRegs.I2CAddr |= 1;//0xa1
    I2cStart();
}

/*------------------------------------------------------------------
    EEPROM寫塊函數(shù)
-------------------------------------------------------------------*/
void I2CWriteBuffers(unsigned int E2RomAddr, unsigned int WriteSize)
{
    if (WriteSize && (WriteSize <= 16))
    {
        I2CRegs.TxCount = WriteSize;
        I2CRegs.RxCount = 0;
        I2CRegs.RWAddr = E2RomAddr;
        I2CRegs.I2CAddr &= 0xfe;//0xa0
        I2cStart();
    }
}

void I2CWriteByte(unsigned int E2RomAddr, unsigned char cData)
{
    I2CRegs.TxBuffer[0] = cData;
    I2CRegs.TxCount = 1;
    I2CRegs.RxCount = 0;
    I2CRegs.RWAddr = E2RomAddr;
    I2CRegs.I2CAddr &= 0xfe;//0xa0
    I2cStart();
}

/*------------------------------------------------------------------
    用戶讀回調(diào)函數(shù)
-------------------------------------------------------------------*/
void I2CReadCallBack(void)
{
    if ((I2CRegs.RWAddr + I2CRegs.RxCount) <= I2CRegs.MaxCount)
    {
//        I2CRegs.RWAddr += I2CRegs.RxCount;
//        I2CReadBuffers(I2CRegs.RWAddr, I2CRegs.RxCount);//繼續(xù)讀
    }
}

/*------------------------------------------------------------------
    用戶寫回調(diào)函數(shù)
-------------------------------------------------------------------*/
void I2CWriteCallBack(void)
{
    if ((I2CRegs.RWAddr + I2CRegs.TxCount) <= I2CRegs.MaxCount)
    {
//        I2CRegs.RWAddr += I2CRegs.TxCount;
//        I2CWriteBuffers(I2CRegs.RWAddr, I2CRegs.TxCount);//繼續(xù)寫
    }
}


/*------------------------------------------------------------------
    EEPROM讀寫啟動(dòng)函數(shù)
-------------------------------------------------------------------*/
void I2cStart(void)
{
/*------------------------------------------------------------------------
//本程序在狀態(tài)I2C_MT_ADDRL_ACK下進(jìn)行瞬間打開,也可在此打開,不過安全不好
    if (I2CRegs.TxCount)//需要寫入字節(jié)
    {
        WP = 0;//不寫保護(hù)
    }
    else
    {
        WP = 1;//寫保護(hù)
    }
--------------------------------------------------------------------------*/
    I2C1STATbits.IWCOL = 0;
    I2CBits.BusyFlag = 1;
    I2CRegs.State = I2C_START;//主機(jī)準(zhǔn)備發(fā)送啟始位
    I2CRegs.Count = 0;//發(fā)送數(shù)據(jù)個(gè)數(shù)
    I2CBits.I2CFlag = 0;
    I2C1CONbits.SEN = 1;//發(fā)送Start信號(hào)
}

/*------------------------------------------------------------------
    EEPROM讀再啟動(dòng)函數(shù)
-------------------------------------------------------------------*/
void I2cReStart(void)
{
    I2C1STATbits.IWCOL = 0;
    I2CBits.BusyFlag = 1;
    I2CRegs.State = I2C_REP_START;//主機(jī)準(zhǔn)備發(fā)送重新啟始位
    I2CRegs.Count = 0;//發(fā)送數(shù)據(jù)個(gè)數(shù)
    I2C1CONbits.RSEN = 1;//發(fā)送ReStart信號(hào)
    I2C1CONbits.ACKEN = 0;
}

/*------------------------------------------------------------------
    EEPROM讀寫正確停止函數(shù)
-------------------------------------------------------------------*/
void I2cStop(void)
{
    I2C1STATbits.IWCOL = 0;
    I2CBits.BusyFlag = 0;
    I2CRegs.State = I2C_SUCCEEDED;//通訊成功
    I2C1CONbits.PEN = 1;//發(fā)送Stop信號(hào)
    WP = 1;//寫保護(hù)
}


/*------------------------------------------------------------------
    EEPROM讀寫錯(cuò)誤退出函數(shù)
-------------------------------------------------------------------*/
void I2cExit(void)
{
    I2C1STATbits.IWCOL = 0;
    I2CBits.BusyFlag = 0;
    I2CRegs.State = I2C_FAILED;
    I2C1CONbits.PEN = 1;//發(fā)送Stop信號(hào)
    WP = 1;//寫保護(hù)
}

/*------------------------------------------------------------------
     EEPROM讀寫中斷事件處理函數(shù)(說明見文件頭部)
-------------------------------------------------------------------*/
void I2CExec(void)
{
    if (I2C1STATbits.S)//收到Start過信號(hào)
    {
        switch (I2CRegs.State)
        {
            case I2C_START://收到Start信號(hào)
                I2C1TRN = I2CRegs.I2CAddr & 0xfe;//發(fā)送器件寫地址(通知從機(jī)只能聽)
                I2CRegs.State = I2C_MT_SLA_ACK;//下次應(yīng)該接收器件寫地址應(yīng)答信號(hào)
                break;
            case I2C_MT_SLA_ACK://收到器件寫地址應(yīng)答信號(hào)
                if (!I2C1STATbits.ACKSTAT)//收到Ack信號(hào)
                {
                    if (I2CRegs.MaxCount > 0x100)//EEPROM容量超過256個(gè)字節(jié),EEPROM地址需要兩次發(fā)送
                    {
                        I2C1TRN = I2CRegs.RWAddr >> 8;//發(fā)送EEPROM寫高8位地址
                        I2CRegs.State = I2C_MT_ADDRH_ACK;//下次應(yīng)該接收EEPROM寫高8位地址應(yīng)答信號(hào)
                    }
                    else//小容量只需一次發(fā)送!!!
                    {
                        I2C1TRN = I2CRegs.RWAddr;//發(fā)送EEPROM寫低8位地址
                        I2CRegs.State = I2C_MT_ADDRL_ACK;//下次應(yīng)該接收EEPROM寫低8位地址應(yīng)答信號(hào)
                        I2CRegs.Count = 0;//清空發(fā)送緩沖計(jì)數(shù)器
                    }
                }   
                else//收到NAck信號(hào)
                {
                    I2cExit();//錯(cuò)誤的ACK信號(hào)   
                }   
                break;
            case I2C_MT_ADDRH_ACK://收到EEPROM寫高8位地址應(yīng)答信號(hào)
                if (!I2C1STATbits.ACKSTAT)//收到Ack信號(hào)
                {
                    I2C1TRN = I2CRegs.RWAddr & 0xff;//發(fā)送EEPROM寫低8位地址
                    I2CRegs.State = I2C_MT_ADDRL_ACK;//下次應(yīng)該接收EEPROM寫低8位地址應(yīng)答信號(hào)
                    I2CRegs.Count = 0;//清空發(fā)送緩沖計(jì)數(shù)器
                }   
                else//收到NAck信號(hào)
                {
                    I2cExit();//錯(cuò)誤的ACK信號(hào)   
                }   
                break;
            case I2C_MT_ADDRL_ACK://收到EEPROM寫高低8位地址應(yīng)答信號(hào)
                if (I2CRegs.TxCount)//寫保護(hù)只在寫入期間不保護(hù),增加了對(duì)誤寫入的安全防護(hù)能力!!!
                {
                     WP = 0;//不寫保護(hù)
                }
            case I2C_MT_DATA_ACK://收到應(yīng)答信號(hào)
                if (!I2C1STATbits.ACKSTAT)//收到Ack信號(hào)
                {
                    if (I2CRegs.Count < I2CRegs.TxCount)//緩沖區(qū)未空
                    {
                        I2C1TRN = I2CRegs.TxBuffer[I2CRegs.Count ++];//繼續(xù)發(fā)送數(shù)據(jù)   
                    }
                    else if (I2CRegs.Count == I2CRegs.TxCount)//緩沖區(qū)已空
                    {
                        if (I2CRegs.I2CAddr & 1)//應(yīng)該開始接收數(shù)據(jù)
                        {
                            I2cReStart();//發(fā)送重復(fù)位命令
                        }
                        else//只寫退出
                        {
                            I2cStop();//正常發(fā)送結(jié)束
                        }
                    }
                    else//干擾出錯(cuò)
                    {
                        I2cExit();//錯(cuò)誤
                    }
                }   
                else//收到NAck信號(hào)(可能被寫保護(hù))
                {
                    I2cExit();//錯(cuò)誤的ACK信號(hào)   
                }   
                break;
            case I2C_REP_START://收到ReStart信號(hào)
                I2C1TRN = I2CRegs.I2CAddr | I2C_READ;//發(fā)送器件讀地址(通知從機(jī)可以說話)
                I2CRegs.State = I2C_MR_SLA_ACK;//下次應(yīng)該接收器件寫讀地址應(yīng)答信號(hào)
                break;
            case I2C_MR_SLA_ACK://收到器件讀地址應(yīng)答信號(hào)
                if (!I2C1STATbits.ACKSTAT)//收到Ack信號(hào)
                {
                    I2C1CONbits.RCEN = 1;//開始接收數(shù)據(jù)
                    I2CRegs.State = I2C_MR_DATA;//下次應(yīng)該收接收數(shù)據(jù)
                }   
                else//收到NAck信號(hào)
                {
                    I2cExit();//錯(cuò)誤的ACK信號(hào)   
                }   
                break;
            case I2C_MR_DATA://收到接收數(shù)據(jù)
                if (I2CRegs.Count < I2CRegs.RxCount)
                {
//                    I2C1STATbits.I2COV = 0;
                    I2CRegs.RxBuffer[I2CRegs.Count ++] = I2C1RCV;
                    if (I2CRegs.Count < I2CRegs.RxCount)
                    {
                         I2C1CONbits.ACKDT = 0;//應(yīng)答子機(jī)
                        I2CRegs.State = I2C_MR_DATA_EN;//下次應(yīng)該收到器件允許繼續(xù)讀信號(hào)
                    }
                    else
                    {
                        I2C1CONbits.ACKDT = 1;//非應(yīng)答子機(jī)   
                        I2CRegs.State = I2C_MR_DATA_STOP;//下次應(yīng)該收到退出信號(hào)
                    }
                     I2C1CONbits.ACKEN = 1;//向從機(jī)發(fā)送(非)應(yīng)答信號(hào)
                }
                else//正確的狀態(tài)已分支到I2C_MR_DATA_STOP
                {
                    I2cExit();//錯(cuò)誤
                }
                break;
            case I2C_MR_DATA_EN://收到器件允許繼續(xù)讀信號(hào)
                I2C1CONbits.RCEN = 1;//開始接收數(shù)據(jù)
                I2CRegs.State = I2C_MR_DATA;//下次應(yīng)該繼續(xù)接收數(shù)據(jù)
                break;
            case I2C_MR_DATA_STOP://收到器件退出信號(hào)
                I2cStop();//正常接收結(jié)束
                break;
            default://其他不可預(yù)料的錯(cuò)誤
                I2cExit();//錯(cuò)誤
        }
    }
    else if (I2C1STATbits.P)//收到Stop信號(hào)
    {
        if (I2CRegs.State == I2C_SUCCEEDED)//成功,回調(diào)
        {
            if (I2CRegs.I2CAddr & 1)//讀
            {
                I2CBits.ReadFlag = 1;//激活用戶讀回調(diào)函數(shù)I2CReadCallBack()
            }
            else//寫
            {
                I2CBits.WriteFlag = 1;//激活用戶寫回調(diào)函數(shù)I2CWriteCallBack()
            }
        }
    }
    else//無法確認(rèn)的復(fù)雜錯(cuò)誤
    {
        I2cExit();//錯(cuò)誤出錯(cuò)退出
    }
}

作者: hotpower    時(shí)間: 2009-4-2 22:57
對(duì)應(yīng)的I2C.H

#include "main.h"

#ifndef __I2C_H
#define __I2C_H

#define I2CBAUD 800000//800KHz  本程序是讀寫鐵電的,故速度很高               

//下面的是I2C的標(biāo)準(zhǔn)狀態(tài)表,因?yàn)镻IC的不標(biāo)準(zhǔn),故湊合著用和補(bǔ)充了加注解的部分~~~
enum enum_I2CState
{
/* Master */
    I2C_START =                    0x08,//啟動(dòng)
    I2C_REP_START=                0x10,//重啟動(dòng)
/* Master Transmitter */
    I2C_MT_SLA_ACK=                0x18,//主發(fā)模式下得到從機(jī)地址應(yīng)答信號(hào)
    I2C_MT_SLA_NACK=            0x20,

    I2C_MT_DATA_ACK=            0x28,//主發(fā)模式下得到從機(jī)數(shù)據(jù)應(yīng)答信號(hào)
    I2C_MT_DATA_NACK=            0x30,



    I2C_MT_ARB_LOST=            0x38,
/* Master Receiver */
    I2C_MR_ARB_LOST=            0x38,
    I2C_MR_SLA_ACK=                0x40,//主收模式下得到從機(jī)地址應(yīng)答信號(hào)
    I2C_MR_SLA_NACK=            0x48,
    I2C_MR_DATA_ACK=            0x50,
    I2C_MR_DATA_NACK=            0x58,

/* Slave Transmitter */
    I2C_ST_SLA_ACK=                0xA8,
    I2C_ST_ARB_LOST_SLA_ACK=    0xB0,
    I2C_ST_DATA_ACK=            0xB8,
    I2C_ST_DATA_NACK=            0xC0,
    I2C_ST_LAST_DATA=            0xC8,
/* Slave Receiver */
    I2C_SR_SLA_ACK=                0x60,
    I2C_SR_ARB_LOST_SLA_ACK=    0x68,
    I2C_SR_GCALL_ACK=            0x70,
    I2C_SR_ARB_LOST_GCALL_ACK=  0x78,
    I2C_SR_DATA_ACK=            0x80,
    I2C_SR_DATA_NACK=            0x88,
    I2C_SR_GCALL_DATA_ACK=        0x90,
    I2C_SR_GCALL_DATA_NACK=        0x98,
    I2C_SR_STOP=                0xA0,
/* Misc */
    I2C_NO_INFO=                0xF8,

    I2C_MT_ADDRH_ACK=            0x3a,//主發(fā)模式下得到從機(jī)高位EEPROM地址應(yīng)答信號(hào)
    I2C_MT_ADDRL_ACK=            0x3b,//主發(fā)模式下得到從機(jī)高低位EEPROM地址應(yīng)答信號(hào)
    I2C_MR_DATA=                0x5a,//主收模式下接收數(shù)據(jù)
    I2C_MR_DATA_EN=                0x5b,//主收模式下使能接收數(shù)據(jù)功能
    I2C_MR_DATA_STOP=            0x5c,//主收模式下接收數(shù)據(jù)完成

    I2C_FAILED=                    0xcc,//讀寫操作失敗
    I2C_SUCCEEDED=              0x00,//讀寫操作成功
    I2C_RWBIT=                    0,//
    I2C_READ=                    1,//
    I2C_WRITE=                    0//
};


#define TRIS_SCL1 _TRISG2 //SCL方向控制
#define TRIS_SDA1 _TRISG3 //SDA方向控制
#define ODC_SCL1 _ODG2 //SCL開漏控制
#define ODC_SDA1 _ODG3 //SDA開漏控制

/*-----------------------------------------
        寫保護(hù)管腳定義,需要硬件的支持
------------------------------------------*/
#define TRIS_WP   _TRISD0 //WP方向控制
#define WP _LATD0//寫保護(hù)

typedef struct tagI2CBITS
{
    union
    {
        unsigned char I2CFlag;
        struct
        {
            unsigned char  BusyFlag:   1;//忙標(biāo)志
            unsigned char  ReadFlag:   1;//讀回調(diào)標(biāo)志
            unsigned char  WriteFlag:  1;//寫回調(diào)標(biāo)志
        };
    };
}I2CBITS;

extern volatile I2CBITS I2CBits;

typedef struct tagI2CREGS
{
    unsigned char State;//運(yùn)行狀態(tài)編碼
    unsigned char I2CAddr;//器件地址0xa1,0xa0
    unsigned int RWAddr;//器件讀寫地址(自動(dòng)根據(jù)MaxCount判斷長(zhǎng)短地址)
    unsigned int Count;//運(yùn)行計(jì)數(shù)器
    unsigned int TxCount;//發(fā)送(寫)個(gè)數(shù)
    unsigned int RxCount;//接收(讀)個(gè)數(shù)
    unsigned int MaxCount;//器件最大容量
    unsigned char TxBuffer[16];//發(fā)送緩沖區(qū)
    unsigned char RxBuffer[256];//接收緩沖區(qū)
}I2CREGS;

extern volatile I2CREGS I2CRegs;


void I2cInit(void);
void I2CReadBuffers(unsigned int, unsigned int);
void I2CReadByte(unsigned int);
void I2CWriteBuffers(unsigned int, unsigned int);
void I2CWriteByte(unsigned int, unsigned char);
void I2CReadCallBack(void);
void I2CWriteCallBack(void);
void I2cStart(void);
void I2cReStart(void);
void I2cStop(void);
void I2CExec(void);

#endif//__I2C_H
作者: hotpower    時(shí)間: 2009-4-2 22:58
老外的i2cEmem.c

/**********************************************************************
* ?2005 Microchip Technology Inc.
*
* FileName:        i2cEmem.c
* Dependencies:    Header (.h) files if applicable, see below
* Processor:       dsPIC33Fxxxx/PIC24Hxxxx
* Compiler:        MPLAB?C30 v3.00 or higher
* Tested On:       dsPIC33FJ256GP710
*
* SOFTWARE LICENSE AGREEMENT:
* Microchip Technology Incorporated ("Microchip") retains all ownership and
* intellectual property rights in the code accompanying this message and in all
* derivatives hereto.  You may use this code, and any derivatives created by
* any person or entity by or on your behalf, exclusively with Microchip's
* proprietary products.  Your acceptance and/or use of this code constitutes
* agreement to the terms and conditions of this notice.
*
* CODE ACCOMPANYING THIS MESSAGE IS SUPPLIED BY MICROCHIP "AS IS".  NO
* WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
* TO, IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE APPLY TO THIS CODE, ITS INTERACTION WITH MICROCHIP'S
* PRODUCTS, COMBINATION WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.
*
* YOU ACKNOWLEDGE AND AGREE THAT, IN NO EVENT, SHALL MICROCHIP BE LIABLE, WHETHER
* IN CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE OR BREACH OF STATUTORY DUTY),
* STRICT LIABILITY, INDEMNITY, CONTRIBUTION, OR OTHERWISE, FOR ANY INDIRECT, SPECIAL,
* PUNITIVE, EXEMPLARY, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, FOR COST OR EXPENSE OF
* ANY KIND WHATSOEVER RELATED TO THE CODE, HOWSOEVER CAUSED, EVEN IF MICROCHIP HAS BEEN
* ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE.  TO THE FULLEST EXTENT
* ALLOWABLE BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO
* THIS CODE, SHALL NOT EXCEED THE PRICE YOU PAID DIRECTLY TO MICROCHIP SPECIFICALLY TO
* HAVE THIS CODE DEVELOPED.
*
* You agree that you are solely responsible for testing the code and
* determining its suitability.  Microchip has no obligation to modify, test,
* certify, or support the code.
*
* REVISION HISTORY:
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Author            Date      Comments on this revision
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Settu D.          07/09/06       First release of source file
*
**********************************************************************/
#if defined(__dsPIC33F__)
#include "p33Fxxxx.h"
#elif defined(__PIC24H__)
#include "p24Hxxxx.h"
#endif

#include "i2cEmem.h"

unsigned int jDone;


/*=============================================================================
I2C Master Interrupt Service Routine
=============================================================================*/
void __attribute__((interrupt, no_auto_psv)) _MI2C1Interrupt(void)
{
        jDone=1;
        IFS1bits.MI2C1IF = 0;        //Clear the DMA0 Interrupt Flag;

}

/*=============================================================================
I2C Slave Interrupt Service Routine
=============================================================================*/
void __attribute__((interrupt, no_auto_psv)) _SI2C1Interrupt(void)
{
   
        IFS1bits.SI2C1IF = 0;        //Clear the DMA0 Interrupt Flag
}



/*=============================================================================
I2C Peripheral Initialisation
=============================================================================*/   
void I2CEMEMinit(I2CEMEM_DRV *i2cMem)
{   
    i2cMem->cmd=0;
    i2cMem->oData=0;

// Configre SCA/SDA pin as open-drain
    ODCGbits.ODCG2=1;
    ODCGbits.ODCG3=1;


    I2C1CONbits.A10M=0;
    I2C1CONbits.SCLREL=1;
    I2C1BRG=300;

    I2C1ADD=0;
    I2C1MSK=0;

    I2C1CONbits.I2CEN=1;
    IEC1bits.MI2C1IE = 1;
      IFS1bits.MI2C1IF = 0;


}

/*=============================================================================
I2C Serial EEPROM, STATE-MACHINE BASED DRIVER
=============================================================================*/                                                            
void I2CEMEMdrv(I2CEMEM_DRV *i2cMem)
{

static int state="0", cntr="0", rtrycntr="0";

    switch(state)
    {
    case 0:
        if( (i2cMem->cmd == I2C_WRITE)  || (i2cMem->cmd == I2C_READ)  )
            state=1;   
         
        break;

    /*==================================*/        
    /* Control/Address Phase            */
    /*==================================*/
    case 1:
        // Start Condition
        I2C1CONbits.SEN=1;        
        state=state+1;
        break;


    case 2:
        // Start Byte with device select id
        if(jDone==1)    {
            jDone=0;
              state=state+1;
              I2C1TRN=(0x00A0)|(((i2cMem->oData->csel)&0x7)<<1);
        }
        break;

    case 3:         
           // Send address byte 1, if ack is received. Else Retry
        if(jDone==1)    {
            jDone=0;
      
            if(I2C1STATbits.ACKSTAT==1) {        // Ack Not received, Retry

                if(rtrycntr < MAX_RETRY)
                    state=18;
                else
                    state=16;                    // Flag error and exit

            } else {

                rtrycntr=0;

                #if ADDRWIDTH==TWO_BYTE
                I2C1TRN=((i2cMem->oData->addr)&0xFF00)>>8;
                   state=state+1;
                #endif
               
                #if ADDRWIDTH==ONE_BYTE
                I2C1TRN=((i2cMem->oData->addr));
                state=state+2;
                #endif

            }
        }
        break;
   
   
    case 4:
        // Send address byte 2, if ack is received. Else Flag error and exit
          if(jDone==1)    {
            jDone=0;

            if(I2C1STATbits.ACKSTAT==1) {        // Ack Not received, Flag error and exit
                state=16;

            } else {

                #if ADDRWIDTH==TWO_BYTE
                I2C1TRN=((i2cMem->oData->addr)&0x00FF);
                #endif
                state=state+1;
            }
        }
        break;
   

    case 5:
        // Read or Write
          if(jDone==1)    {
            jDone=0;

            if(I2C1STATbits.ACKSTAT==1) {        // Ack Not received, Flag error and exit
                state=16;

            } else {

                if(i2cMem->cmd == I2C_WRITE)
                    state=state+1;   

                if(i2cMem->cmd == I2C_READ)
                    state=8;
            }

        }
        break;

    /*==================================*/        
    /* Write Data Phase                    */
    /*==================================*/

    case 6:
        // Send data
        I2C1TRN=*(i2cMem->oData->buff + cntr);
        state=state+1;
        cntr=cntr+1;
        break;   

    case 7:  
        // Look for end of data or no Ack
          if(jDone==1)    {
            jDone=0;
            state=state-1;

            if(I2C1STATbits.ACKSTAT==1) {        // Ack Not received, Flag error and exit
                state=16;
            } else {

                if(cntr== i2cMem->oData->n)
                    state=14;                   // Close the Frame
                }
        }
        break;

    /*==================================*/        
    /* Read Data Phase                    */
    /*==================================*/
    case 8:
        // Repeat Start
         I2C1CONbits.RSEN=1;        
        state=state+1;
        break;

    case 9:
        // Re-send control byte with W/R=R
        if(jDone==1)    {
            jDone=0;
              state=state+1;
              I2C1TRN=(0x00A1)|(((i2cMem->oData->csel)&0x7)<<1);
        }
        break;

    case 10:   
        // Check, if control byte went ok
        if(jDone==1)    {
            jDone=0;
              state=state+1;

            if(I2C1STATbits.ACKSTAT==1)         // Ack Not received, Flag error and exit
                state=16;
   
        }
        break;

    case 11:
          // Receive Enable
         I2C1CONbits.RCEN=1;   
        state++;
        break;

    case 12:  
        // Receive data
        if(jDone==1)    {
            jDone=0;
            state=state+1;

            *(i2cMem->oData->buff+cntr)=I2C1RCV;
            cntr++;

            if(cntr== i2cMem->oData->n) {
                I2C1CONbits.ACKDT=1;        // No ACK        
            } else {
                I2C1CONbits.ACKDT=0;        // ACK
            }

            I2C1CONbits.ACKEN=1;   

        }
        break;

    case 13:
        if(jDone==1)    {
            jDone=0;
              if(cntr== i2cMem->oData->n)
                state=state+1;
               else
                state=state-2;
         }         
         break;
         
    /*==================================*/        
    /* Stop Sequence                    */
    /*==================================*/
    case 14:
          I2C1CONbits.PEN=1;   
        state++;
        break;
           
    case 15:
         if(jDone==1)    {
            jDone=0;
            state=0;
            cntr=0;
            i2cMem->cmd=0;
        }
          break;

    /*==================================*/        
    /* Set Error                         */
    /*==================================*/
    case 16:
           I2C1CONbits.PEN=1;   
          state++;
        break;
   
    case 17:
         if(jDone==1)    {
            jDone=0;
            state=0;
            rtrycntr=0;
            cntr=0;
            i2cMem->cmd=0xFFFF;
        }
          break;

    /*==================================*/        
    /* Retry                             */
    /*==================================*/
    case 18:
           I2C1CONbits.PEN=1;   
          state++;
        rtrycntr++;
        break;

    case 19:
         if(jDone==1)    {
            jDone=0;
            state=0;
            cntr=0;
        }
          break;


     }     

}




歡迎光臨 電子工程網(wǎng) (http://m.qingdxww.cn/) Powered by Discuz! X3.4
主站蜘蛛池模板: 日日噜噜夜夜狠狠tv视频免费 | 我去色| 国产三级农村妇女做受 | 成人手机在线视频 | 老鸭窝欧美一级一区二区 | 成人国产一区 | 久99久视频 | 亚洲专区在线播放 | 欧美日韩视频一区二区在线观看 | 最新国语自产精品视频在 | 国产馆在线观看免费的 | 亚洲高清在线看 | 麻豆日记 | 国产亚洲福利一区二区免费看 | 亚洲一区视频在线播放 | 一级有奶水毛片免费看 | 一道本高清香蕉网 | 日日噜噜夜夜狠狠视频无 | 日本高清在线观看视频www | 国产精品亚洲精品影院 | 大香线蕉免费观看视频75 | www.日日| 日韩成人免费在线视频 | 综合五月婷婷 | 深夜福利国产精品亚洲尤物 | 国产久视频 | 裙底盗摄国产精品 | 日韩一区二区三区四区五区 | 91成人午夜精品福利院在线观看 | 天堂一区二区三区在线观看 | 在线免费色视频 | 香蕉久人久人青草青草 | 毛片黄在线看免费 | 亚洲免费成人网 | 国内精品一区二区在线观看 | 亚洲国产精品91 | 国产免费一区二区在线看 | 欧美xxxxx九色视频免费观看 | 日本强不卡在线观看 | 久久香蕉国产线看观看式 | 末成年娇小性色xxxxx |