打印
[菜农群课笔记]

【第三期】I2C的操作.查询,中断.各种操作!

[复制链接]
3057|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
kyzb001|  楼主 | 2011-12-7 12:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
I2c, ST, se, ck, AC
本帖最后由 kyzb001 于 2011-12-7 14:22 编辑
void DrcI2C_WriteByte(uint32_t address,uint8_t data )
{
uint32_t i;
SystemCoreClock = DrvSYS_GetHCLKFreq();
//Open I2C1 and set clock = 50Kbps
if(DrvI2C_Open(I2C_PORT1, 50000))
printf("Open i2c1 fail.\n");

//send i2c start state
DrvI2C_Ctrl(I2C_PORT1, 1, 0, 0, 0); //设置开始
while (I2C1->I2CON.SI == 0); //等待...

I2C1->I2CDAT = 0xA0; //发送器件地址
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1,0 ); //clr si flag
while( I2C1->I2CON.SI == 0 ); //poll si flag

I2C1->I2CDAT = (address>>8)&0XFF; //send address high
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //clr si and set ack
while( I2C1->I2CON.SI == 0 ); //poll si flag
//send address low
I2C1->I2CDAT = address&0XFF;
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //clr si and set ack
while( I2C1->I2CON.SI == 0 ); //poll si flag
//send data
I2C1->I2CDAT = data; //write data to
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //clr si and set ack
while( I2C1->I2CON.SI == 0 ); //poll si flag
//send i2c stop
DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0); //send stop
while( I2C1->I2CON.STO);
//while( I2C1->CON.SI == 0 );
for(i=0;i<60;i++);
DrvI2C_Close(I2C_PORT1);

for(i=0;i<6000;i++);
for(i=0;i<6000;i++);
}

void DrcI2C_WriteData(uint32_t address,uint8_t *pBuffer ,uint32_t u32Num)
{
uint32_t i;
SystemCoreClock = DrvSYS_GetHCLKFreq();

if(DrvI2C_Open(I2C_PORT1, 50000)) //Open I2C1 and set clock = 50Kbps
printf("Open i2c1 fail.\n");

//send i2c start
DrvI2C_Ctrl(I2C_PORT1, 1, 0, 0, 0); //set start
while (I2C1->I2CON.SI == 0); //poll si flag
//send writer command
I2C1->I2CDAT = address; //send writer command
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1,0 ); //clr si flag
while( I2C1->I2CON.SI == 0 ); //poll si flag

while(u32Num--)
{
//send data
I2C1->I2CDAT = *pBuffer; //write data to
pBuffer++;
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //clr si and set ack
while( I2C1->I2CON.SI == 0 ); //poll si flag

}

//send i2c stop
DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0); //send stop
while( I2C1->I2CON.STO);
//while( I2C1->CON.SI == 0 );
for(i=0;i<60;i++);
DrvI2C_Close(I2C_PORT1);

for(i=0;i<6000;i++);
for(i=0;i<6000;i++);
}

uint8_t DrcI2C_ReadByte(uint32_t address)
{
uint8_t TEMP;
//Open I2C1 and set clock = 50Kbps
SystemCoreClock = DrvSYS_GetHCLKFreq();
DrvI2C_Open(I2C_PORT1, 50000);
//send i2c start
DrvI2C_Ctrl(I2C_PORT1, 1, 0, 1, 0); //set start
while (I2C1->I2CON.SI == 0); //poll si flag

//send writer command
I2C1->I2CDAT = 0XA0;
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0); //clr si
while( I2C1->I2CON.SI == 0 ); //poll si flag

//send address high
I2C1->I2CDAT = (address>>8)&0XFF;
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //clr si and set ack
while( I2C1->I2CON.SI == 0 ); //poll si flag

//send address low
I2C1->I2CDAT = address&0XFF;
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0); //clr si and set ack
while( I2C1->I2CON.SI == 0 ); //poll si flag

//send start flag
DrvI2C_Ctrl(I2C_PORT1, 1, 0, 1, 0); //clr si and send start
while( I2C1->I2CON.SI == 0 ); //poll si flag

//send read command
I2C1->I2CDAT = 0XA1;
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //clr si
while( I2C1->I2CON.SI == 0 ); //poll si flag

//resive data
I2C1->I2CDAT = 0XFF;
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0); //clr si
while( I2C1->I2CON.SI == 0 ); //poll si flag
TEMP= I2C1->I2CDAT;
//send i2c stop
DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0); //clr si and set stop
while( I2C1->I2CON.STO);
DrvI2C_Close(I2C_PORT1);

return TEMP;
}

#include "DrvI2C_Int.h"

volatile I2C_HOT_T I2C1s;



void I2C1_INT_HANDLE (uint32_t status)
{
switch(status & 0xf8)
{
case I2C_START: //主机收到自己发送的开始信号
{
if(I2C1s.State == I2C_START)
{ //本次中断应该接收TW_START信号
I2C1->I2CDAT = I2C1s.u8SetAddress & 0xfe; //发送子机地址(写)
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0); //STA位必须清除,否则死机 清除中断标志
I2C1s.State = I2C_MT_SLA_ACK; //Status下次I2C_MT_SLA_ACK
}
else
I2C_Exit(); //通讯失败
break;
}

case I2C_REP_START: //主机收到自己发送的重新开始信号
{
if (I2C1s.State == I2C_REP_START)
{ //本次中断应该接收TW_RESTART信号
I2C1->I2CDAT = I2C1s.u8SetAddress; //发送子机地址(读)
I2C1s.State = I2C_MR_SLA_ACK; //Status下次I2C_MR_SLA_ACK
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1); //STA位必须清除,否则死机 清除中断标志
}
else
I2C_Exit(); //通讯失败
break;
}

case I2C_MT_SLA_ACK:
{ //主发机接收到从机的地址应答信号后发送命令
if(I2C1s.State == I2C_MT_SLA_ACK)
{ //本次中断应该接收TW_MT_SLA_ACK信号
I2C1s.State = I2C_MT_DATA_ACK; //Status下次应该收TW_MT_DATA_ACK
I2C1->I2CDAT = I2C1s.SubComm; //发送子机命令
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1);
}
else
I2C_Exit(); //通讯失败
break;
}

case I2C_MR_SLA_ACK:
{ //主收机接收到从机的地址应答信号
if ((I2C1s.State == I2C_MR_SLA_ACK) && I2C1s.u32SubCount)
{ //本次中断应该接收TW_MR_SLA_ACK信号
I2C1s.State = I2C_MR_DATA_ACK; //Status下次应该收TW_MR_DATA_ACK
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1);
}
else
I2C_Exit(); //通讯失败
break;
}
case I2C_MT_DATA_ACK:
{ //主收机接收到从机的数据应答信号
if ((I2C1s.State == I2C_MT_DATA_ACK) && (I2C1s.u32Count < I2C1s.u32MasterCount))
{ //本次中断应该接收TW_MT_DATA_ACK信号
I2C1->I2CDAT= I2C1s.u32TxBuffer[I2C1s.u32Count ++]; //发送子机数据
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1);
}
else
{
if ((I2C1s.State == I2C_MT_DATA_ACK) &&
(I2C1s.u32Count == I2C1s.u32MasterCount) &&
(I2C1s.u8SetAddress & 0x01))
{ //本次中断应该接收TW_MT_DATA_ACK信号
I2C_REStart();//
}
else
I2C_Stop(); //通讯成功
}
break;
}
case I2C_MR_DATA_ACK:
{
if ((I2C1s.State == I2C_MR_DATA_ACK) && (I2C1s.u32Count < I2C1s.u32SubCount))
{
I2C1s.u32TxBuffer[I2C1s.u32Count ++] = I2C1->I2CDAT;//接收子机数据
if (I2C1s.u32Count < I2C1s.u32SubCount)
{
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 1);
}
else
{
DrvI2C_Ctrl(I2C_PORT1, 0, 0, 1, 0);
I2C1s.State = I2C_MR_DATA_NACK; //下次进入I2C_MR_DATA_NACK,接收数据准备完成
}
}
else
I2C_Exit(); //通讯失败
break;
}
case I2C_MR_DATA_NACK: //数据接收结束
{
if((I2C1s.State == I2C_MR_DATA_NACK) && (I2C1s.u32Count == I2C1s.u32SubCount))
{
I2C_Stop(); //通讯成功
}
else
I2C_Exit(); //通讯失败
break;
}

default:
I2C_Exit(); //通讯失败
}
}

void Init_I2C(void)
{
/* Set I2C I/O */
DrvGPIO_InitFunction(E_FUNC_I2C1);
I2C1s.u8SetAddress = 0xA0;
}

void I2C_Start(void)
{
I2C1s.Busy = TRUE;
I2C1s.State = I2C_START; //主机准备发送启始位
I2C1s.u32Count = 0; //发送数据个数
//SystickCount = 0; //清除节拍计数器

/* Open I2C1, and set clock = 50Kbps */
DrvI2C_Open(I2C_PORT1,50000);

/* Enable I2C1 interrupt and set corresponding NVIC bit */
DrvI2C_EnableInt(I2C_PORT1);

/* Install I2C1 call back function for slave */
DrvI2C_InstallCallback(I2C_PORT1, I2CFUNC, I2C1_INT_HANDLE);

DrvI2C_Ctrl(I2C_PORT1, 1, 0, 0, 0);

DrvSYS_Delay(8000);
}

void I2C_REStart(void)
{
I2C1s.Busy = TRUE;
I2C1s.State = I2C_REP_START; //主机准备发送启始位
I2C1s.u32Count = 0; //发送数据个数
DrvI2C_Ctrl(I2C_PORT1, 1, 0, 1, 0);
}


void I2C_Stop(void)
{
I2C1s.Busy= FALSE;
I2C1s.State = I2C_BUS_OK; //通讯成功
DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0);
}

void I2C_Exit(void)
{
I2C1s.Busy = FALSE;
I2C1s.State = I2C_BUS_ERROR; //通讯失败
DrvI2C_Ctrl(I2C_PORT1, 0, 1, 1, 0);

printf("I2C talk is fail.\n");
}


unsigned char I2C_ReadByte(unsigned int Address, unsigned char *Data)
{
I2C1s.u8SetAddress |= 0x01;
I2C1s.u32MasterCount = 0; //发送0个数据(只读)
//本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
I2C1s.SubComm = Address; //读出地址
I2C1s.u32SubCount = 1; //接收1个数据
I2C_Start(); //启动I2C模块
if (I2C1s.State == I2C_BUS_OK) //通讯成功
{
Data[0] = I2C1s.u32TxBuffer[0]; //从接收缓冲区取出一个字节
}
return I2C1s.State; //(读出数据在RxBuffer[0]~RxBuffer[15])
}
//本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
unsigned char I2C_ReadBuffer(unsigned int Address, unsigned char *Data, unsigned int Cnt)
{
int i;
I2C1s.u8SetAddress |= 0x01;
I2C1s.u32MasterCount = 0; //发送0个数据(只读)

I2C1s.SubComm = Address; //读出地址
I2C1s.u32SubCount = (Cnt <= sizeof(I2C1s.u32TxBuffer)) ? Cnt : sizeof(I2C1s.u32TxBuffer);//接收Cnt个数据
I2C_Start(); //启动I2C模块
if (I2C1s.State == I2C_BUS_OK)
{ //通讯成功
for (i = 0; i < I2C1s.u32SubCount; i ++)
Data[i] = I2C1s.u32TxBuffer[i]; //从接收缓冲区取出Cnt个字节
}
return I2C1s.State; //(读出数据在RxBuffer[0]~RxBuffer[15])
}
//本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
unsigned char I2C_WriteByte(unsigned int Address, unsigned char Data)
{
I2C1s.u8SetAddress &=0xfe;
I2C1s.u32MasterCount = 1; //发送1个数据

I2C1s.SubComm = Address; //写入地址
I2C1s.u32TxBuffer[0] = Data; //写入1个数据到发送缓冲区
I2C1s.u32SubCount = 0; //接收0个数据
I2C_Start(); //启动I2C模块
DrvSYS_Delay(100);
return I2C1s.State;
}



//本程序为通用I2C,故发送器件后一般为命令,对EEPROM来说,命令实际是EEPROM地址
unsigned char I2C_WriteBuffer(unsigned int Address, unsigned char *Data, unsigned int Cnt)
{
int i;
I2C1s.u8SetAddress &= 0xfe; //发送Cnt个数据
I2C1s.u32MasterCount =Cnt ;


I2C1s.SubComm = Address; //写入地址

for (i = 0; i < Cnt; i ++)
{
I2C1s.u32TxBuffer[i] = Data[i]; //写入Cnt个数据到发送缓冲区
}
I2C1s.u32SubCount = 0; //接收0个数据
I2C_Start(); //启动I2C模块
DrvSYS_Delay(100);
return I2C1s.State;
}





其实我是复制黏贴的 - -~
废话不多说了,遇到一个变态的I2C器件...折腾了2天..显示出来了!!
贴上代码!
现在网速度很垃圾~ 贴不上去!   网速好了 在补!!!

相关帖子

沙发
Ryanhsiung| | 2011-12-7 12:57 | 只看该作者
还好了,你遇到的我肯定遇到过,我遇到你不一定遇到!

    呵呵

使用特权

评论回复
板凳
kyzb001|  楼主 | 2011-12-7 13:26 | 只看该作者
本帖最后由 kyzb001 于 2011-12-7 13:29 编辑
还好了,你遇到的我肯定遇到过,我遇到你不一定遇到!

    呵呵
Ryanhsiung 发表于 2011-12-7 12:57


不会把, 这么肯定。
我去年7月份就接触M0了!
功能除了USB 其他的都玩过了.....

使用特权

评论回复
地板
kyzb001|  楼主 | 2011-12-7 13:30 | 只看该作者
当时用的是140....

使用特权

评论回复
5
kyzb001|  楼主 | 2011-12-7 15:28 | 只看该作者
做为查询方式...新塘的那个DrvI2C_Ctrl 这个函数写的很蛋疼~
中断方式DrvI2C_Ctrl这个函数 会使操作方便一点!
不说那个方式好~  最好用的就是最好的!!!

使用特权

评论回复
6
mcs8098| | 2011-12-20 11:13 | 只看该作者
:lol

使用特权

评论回复
7
Ryanhsiung| | 2011-12-22 08:46 | 只看该作者
不会把, 这么肯定。
我去年7月份就接触M0了!
功能除了USB 其他的都玩过了.....
kyzb001 发表于 2011-12-7 13:26


我指的是I2C的设备

使用特权

评论回复
8
kyzb001|  楼主 | 2011-12-22 09:06 | 只看该作者
呵呵~ 设备就那么肯定拉!:)
7# Ryanhsiung

使用特权

评论回复
9
qhongzhang| | 2011-12-29 15:12 | 只看该作者
先谢谢。用查询还,还是中断好呢?

使用特权

评论回复
10
Ryanhsiung| | 2012-1-8 12:43 | 只看该作者
先谢谢。用查询还,还是中断好呢?
qhongzhang 发表于 2011-12-29 15:12

正常当然是中断好了,占用系统时间少。

使用特权

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

本版积分规则

个人签名:Is this my life

15

主题

624

帖子

1

粉丝