?? i2c.c
字號:
/*
* FILE: i2c.c
* 用于主機發送/接收
*/
#include <stdio.h>
#include "s3c24xx.h"
#include "i2c.h"
void Delay(int time);
#define WRDATA (1)
#define RDDATA (2)
typedef struct tI2C {
unsigned char *pData; /* 數據緩沖區 */
volatile int DataCount; /* 等待傳輸的數據長度 */
volatile int Status; /* 狀態 */
volatile int Mode; /* 模式:讀/寫 */
volatile int Pt; /* pData中待傳輸數據的位置 */
}tS3C24xx_I2C, *ptS3C24xx_I2C;
static tS3C24xx_I2C g_tS3C24xx_I2C;
/*
* I2C初始化
*/
void i2c_init(void)
{
GPEUP |= 0xc000; // 禁止內部上拉
GPECON |= 0xa0000000; // 選擇引腳功能:GPE15:IICSDA, GPE14:IICSCL
INTMSK &= ~(BIT_IIC);
/* bit[7] = 1, 使能ACK
* bit[6] = 0, IICCLK = PCLK/16
* bit[5] = 1, 使能中斷
* bit[3:0] = 0xf, Tx clock = IICCLK/16
* PCLK = 50MHz, IICCLK = 3.125MHz, Tx Clock = 0.195MHz
*/
IICCON = (1<<7) | (0<<6) | (1<<5) | (0xf); // 0xaf
IICADD = 0x10; // S3C24xx slave address = [7:1]
IICSTAT = 0x10; // I2C串行輸出使能(Rx/Tx)
}
/*
* 主機發送
* slvAddr : 從機地址,buf : 數據存放的緩沖區,len : 數據長度
*/
void i2c_write(unsigned int slvAddr, unsigned char *buf, int len)
{
g_tS3C24xx_I2C.Mode = WRDATA; // 寫操作
g_tS3C24xx_I2C.Pt = 0; // 索引值初始為0
g_tS3C24xx_I2C.pData = buf; // 保存緩沖區地址
g_tS3C24xx_I2C.DataCount = len; // 傳輸長度
IICDS = slvAddr;
IICSTAT = 0xf0; // 主機發送,啟動
/* 等待直至數據傳輸完畢 */
while (g_tS3C24xx_I2C.DataCount != -1);
}
/*
* 主機接收
* slvAddr : 從機地址,buf : 數據存放的緩沖區,len : 數據長度
*/
void i2c_read(unsigned int slvAddr, unsigned char *buf, int len)
{
g_tS3C24xx_I2C.Mode = RDDATA; // 讀操作
g_tS3C24xx_I2C.Pt = -1; // 索引值初始化為-1,表示第1個中斷時不接收數據(地址中斷)
g_tS3C24xx_I2C.pData = buf; // 保存緩沖區地址
g_tS3C24xx_I2C.DataCount = len; // 傳輸長度
IICDS = slvAddr;
IICSTAT = 0xb0; // 主機接收,啟動
/* 等待直至數據傳輸完畢 */
while (g_tS3C24xx_I2C.DataCount != -1);
}
/*
* I2C中斷服務程序
* 根據剩余的數據長度選擇繼續傳輸或者結束
*/
void I2CIntHandle(void)
{
unsigned int iicSt,i;
// 清中斷
SRCPND = BIT_IIC;
INTPND = BIT_IIC;
iicSt = IICSTAT;
if(iicSt & 0x8){ printf("Bus arbitration failed\n\r"); }
switch (g_tS3C24xx_I2C.Mode)
{
case WRDATA:
{
if((g_tS3C24xx_I2C.DataCount--) == 0)
{
// 下面兩行用來恢復I2C操作,發出P信號
IICSTAT = 0xd0;
IICCON = 0xaf;
Delay(10000); // 等待一段時間以便P信號已經發出
break;
}
IICDS = g_tS3C24xx_I2C.pData[g_tS3C24xx_I2C.Pt++];
// 將數據寫入IICDS后,需要一段時間才能出現在SDA線上
for (i = 0; i < 10; i++);
IICCON = 0xaf; // 恢復I2C傳輸
break;
}
case RDDATA:
{
if (g_tS3C24xx_I2C.Pt == -1)
{
// 這次中斷是發送I2C設備地址后發生的,沒有數據
// 只接收一個數據時,不要發出ACK信號
g_tS3C24xx_I2C.Pt = 0;
if(g_tS3C24xx_I2C.DataCount == 1)
IICCON = 0x2f; // 恢復I2C傳輸,開始接收數據,接收到數據時不發出ACK
else
IICCON = 0xaf; // 恢復I2C傳輸,開始接收數據
break;
}
if ((g_tS3C24xx_I2C.DataCount--) == 0)
{
g_tS3C24xx_I2C.pData[g_tS3C24xx_I2C.Pt++] = IICDS;
// 下面兩行恢復I2C操作,發出P信號
IICSTAT = 0x90;
IICCON = 0xaf;
Delay(10000); // 等待一段時間以便P信號已經發出
break;
}
g_tS3C24xx_I2C.pData[g_tS3C24xx_I2C.Pt++] = IICDS;
// 接收最后一個數據時,不要發出ACK信號
if(g_tS3C24xx_I2C.DataCount == 0)
IICCON = 0x2f; // 恢復I2C傳輸,接收到下一數據時無ACK
else
IICCON = 0xaf; // 恢復I2C傳輸,接收到下一數據時發出ACK
break;
}
default:
break;
}
}
/*
* 延時函數
*/
void Delay(int time)
{
for (; time > 0; time--);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -