?? i2c.c
字號:
#include "..\header files\includes.H"
#include "I2C.h"
#ifndef FALSE
#define FALSE 0
#endif
//static OS_EVENT *I2cMbox;
INT8U COMMAND; // 在SMBus中斷服務程序中用于保存從地址 + R/W 位。
INT8U IIC_dat; // 保持SMBus要發送的數據字節或剛收到的數據
INT8U BYTE_NUMBER; // 在中用于檢查發送的是什么數據
// 高地址字節、低地址字節或數據字節
INT8U HIGH_ADD, LOW_ADD; // EEPROM存儲器地址的高、低字節
INT8U SM_BUSY; // 該位在發送或接收開始時被置1,
// 操作結束后由中斷服務程序清0
INT8U I2cInit(void) reentrant
{
SFRPAGE=SMB0_PAGE;
SMB0CN = 0x44; // 允許SMBus在應答周期發送ACK
SMB0CR=0xD6; //SMBUS 波特率設置:100KHz
EIE1|= 0x02; //開啟SMBUS中斷
/*
I2cMbox = OSMboxCreate((void *)0); //消息郵箱用于中斷向任務傳遞操作結果
if (I2cMbox ==(void *)0 )
return FALSE;
*/
return FALSE;
}
/***********************************************************************
// SMBus 字節寫函數-----------------------------------------------------
// 向給定存儲器地址寫一個字節
//
// out_byte = 待寫數據
// byte_address = 待寫存儲器地址(2字節)
// chip_select = 待寫EEPROM芯片的器件地址
*************************************************************************/
void SM_Send (INT8U chip_select, INT16U byte_address,INT8U len, INT8U out_byte) reentrant
{
while (SM_BUSY); // 等待SMBus空閑
SM_BUSY = 1; // 占用SMBus(設置為忙)
SFRPAGE=SMB0_PAGE;
SMB0CN = 0x44; // SMBus允許,應答周期發ACK
COMMAND = (chip_select | WRITE); // 片選 + WRITE
if(len) //2個字節
{
BYTE_NUMBER = 2; // 2地址字節
HIGH_ADD = ((byte_address >> 8) & 0x00FF); // 高8位地址
LOW_ADD = (byte_address & 0x00FF); // 低8位地址
}
else
{
BYTE_NUMBER = 1; // 1地址字節
HIGH_ADD =(INT8U)byte_address; // 高8位地址
LOW_ADD = (INT8U)byte_address ; // 低8位地址
}
IIC_dat = out_byte; // 待寫數據
SFRPAGE=SMB0_PAGE;
STA = 1; // 啟動傳輸過程
}
/***********************************************************************
// SMBus隨機讀函數-----------------------------------------------------
// 從給定存儲器地址讀一個字節
//
// byte_address = 要讀取的存儲器地址
// chip_select = 待讀EEPROM的器件地址
************************************************************************/
char SM_Receive (char chip_select, INT16U byte_address,INT8U len) reentrant
{
while (SM_BUSY); // 等待總線空閑
SM_BUSY = 1; //占用SMBus(設置為忙)
SFRPAGE=SMB0_PAGE;
SMB0CN = 0x44; // 允許SMBus,應答周期發ACK
COMMAND = (chip_select | READ); // 片選 + READ
if(len)//2個字節
{
BYTE_NUMBER = 2; // 2地址字節
HIGH_ADD = ((byte_address >> 8) & 0x00FF); // 高8位地址
LOW_ADD = (byte_address & 0x00FF); // 低8位地址
}
else
{
BYTE_NUMBER = 1; // 1地址字節
HIGH_ADD =(INT8U)byte_address; // 高8位地址
LOW_ADD = (INT8U)byte_address ; // 低8位地址
}
SFRPAGE=SMB0_PAGE;
STA = 1; // 啟動傳輸過程
while (SM_BUSY); // 等待傳輸結束
return IIC_dat;
}
//--------------------------------------------------------------------
// 中斷服務程序
//--------------------------------------------------------------------
// SMBus中斷服務程序
void IIC_isr(void) reentrant
{
OS_ENTER_CRITICAL();
SFRPAGE=SMB0_PAGE;
switch (SMB0STA)
{ // SMBus狀態碼(SMB0STA寄存器)
// 主發送器/接收器:起始條件已發送
// 在該狀態發送的COMMAND字的R/W位總是為0(W),
// 因為對于讀和寫操作來說都必須先寫存儲器地址。
case SMB_START:
SMB0DAT = (COMMAND & 0xFE); // 裝入要訪問的從器件的地址
STA = 0; // 手動清除START位
break;
//主發送器/接收器:重復起始條件已發送。
// 該狀態只應在讀操作期間出現,在存儲器地址已發送并得到確認之后
case SMB_RP_START:
SMB0DAT = COMMAND; // COMMAND中應保持從地址 + R.
STA = 0;
break;
// 主發送器:從地址 + WRITE已發送,收到ACK。
case SMB_MTADDACK:
SMB0DAT = HIGH_ADD; // 裝入待寫存儲器地址的高字節
break;
// 主發送器:從地址 + WRITE已發送,收到NACK。
// 從器件不應答,發送STOP + START重試
case SMB_MTADDNACK:
STO = 1;
STA = 1;
break;
// 主發送器:數據字節已發送,收到ACK。
// 該狀態在寫和讀操作中都要用到。BYTE_NUMBER看存儲器地址狀態 – 如果
// 只發送了HIGH_ADD,則裝入LOW_ADD。如果LOW_ADD已發送,檢查COMMAND
// 中的R/W 值以決定下一狀態。
case SMB_MTDBACK:
switch (BYTE_NUMBER)
{
case 2: // 如果BYTE_NUMBER=2,
SMB0DAT = LOW_ADD; // 只發送了HIGH_ADD。
BYTE_NUMBER--; // 減1,為下一輪作準備
break;
case 1: // 如果BYTE_NUMBER=1,LOW_ADD已發送。
if (COMMAND & 0x01) // 如果R/W=READ,發送重復起始條件
STA = 1;
else
{
SMB0DAT = IIC_dat; // 如果R/W=WRITE,裝入待寫字節
BYTE_NUMBER--;
}
break;
default: // 如果BYTE_NUMBER=0,傳輸結束
STO = 1;
//OSMboxPost(I2cMbox, (void *)I2C_WRITE_END);
SM_BUSY = 0; // 釋放SMBus
}
break;
// 主發送器:數據字節已發送,收到NACK。
// 從器件不應答,發送STOP + START重試
case SMB_MTDBNACK:
STO = 1;
STA = 1;
break;
// 主發送器:競爭失敗
// 不應出現。如果出現,重新開始傳輸過程
case SMB_MTARBLOST:
STO = 1;
STA = 1;
break;
// 主接收器:從地址 + READ 已發送。收到ACK。
// 設置為在下一次傳輸后發送NACK,因為那將是最后一個字節(唯一)。
case SMB_MRADDACK:
AA = 0; // 在應答周期NACK。
break;
// 主接收器:從地址 + READ 已發送。收到NACK。
// 從器件不應答,發送重復起始條件重試
case SMB_MRADDNACK:
STA = 1;
break;
// 收到數據字節。ACK已發送。
// 該狀態不應出現,因為AA已在前一狀態被清0。如果出現,發送停止條件。
case SMB_MRDBACK:
STO = 1;
//OSMboxPost(I2cMbox, (void *)I2C_ACK_ERR);
SM_BUSY = 0;
break;
// 收到數據字節。NACK已發送。
// 讀操作已完成。讀數據寄存器后發送停止條件。
case SMB_MRDBNACK:
IIC_dat = SMB0DAT;
STO = 1;
//OSMboxPost(I2cMbox, (void *)I2C_READ_END);
SM_BUSY = 0; // 釋放SMBus
break;
// 在本應用中,所有其它狀態碼沒有意義。通信復位。
default:
STO = 1; // 通信復位。
SM_BUSY = 0;
//OSMboxPost(I2cMbox, (void *)I2C_NOT_GET_BUS);
break;
}
SI=0; // 清除中斷標志
OS_EXIT_CRITICAL();
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -