您的位置 首页 软件

关于LPC1758平台上I2C EEPROM 调试总结

硬件平台:PLC1758软件平台uCOS-II开发环境:IAREWARM源码如下#defineBSP_I2C2_PINS(DEF_BIT_10

硬件渠道:PLC1758

软件渠道 uCOS-II

开发环境: IAR EWARM

源码如下

#define BSP_I2C2_PINS (DEF_BIT_10|DEF_BIT_11)

static void BSP_I2C2_Init(CPU_INT32U fi2c)
{
//获取外设时钟
CPU_INT32U Fpclk = BSP_PM_PerClkFreqGet(BSP_PM_PER_NBR_I2C2);
//使能该功率模块
BSP_PM_PerClkEn(BSP_PM_PER_NBR_I2C2);
//装备脉冲捕捉管脚
BSP_GPIO_Cfg(BSP_GPIO_PORT0_FAST,//P0.10引脚
BSP_I2C2_PINS,//设置成脉冲捕捉
BSP_GPIO_OPT_FNCT_3);//引脚输入使能

//设置占空比
if(fi2c>400000)
fi2c = 400000;
I2C2SCLH = (Fpclk+1/fi2c ) / 2;//高电平占空比寄存器
I2C2SCLL = (Fpclk/fi2c) / 2; //低电平占空比寄存器
//装备成I2C主模式
I2C2CONCLR = 0x2C; //STA|SI|AA|STO;
I2C2CONSET = 0x40; //I2EN=1,使能主I2C

//设置中止源
BSP_IntVectSet((CPU_INT08U)BSP_INT_SRC_NBR_I2C2,(CPU_FNCT_VOID)I2C2_IRQ_ISR_handler );
BSP_IntPrioSet((CPU_INT08U)BSP_INT_SRC_NBR_I2C2,0x01);
//使能中止
BSP_IntEn(BSP_INT_SRC_NBR_I2C2);
//I2C2中止通道号为28

}

问题 :一个字节的变量写入与读出的的成果不一致,源码如下


INT8U I2C_WriteNByte(INT8U sla, INT8U suba_type, INT32U suba, INT8U *s, INT32U num)
{
if (num > 0) // 假如读取的个数为0,则回来过错
{ // 设置参数
if (suba_type == 1)
{ // 子地址为单字节
I2C_sla = sla; // 读器材的从地址
I2C_suba = suba; // 器材子地址
I2C_suba_num = 1; // 器材子地址为1字节
}
else if (suba_type == 2)
{ // 子地址为2字节
I2C_sla = sla; // 读器材的从地址
I2C_suba = suba; // 器材子地址
I2C_suba_num = 2; // 器材子地址为2字节
}
else if (suba_type == 3)
{ // 子地址结构为8+X
I2C_sla = sla + ((suba >> 7 )& 0x0e);// 读器材的从地址
I2C_suba = suba & 0x0ff; // 器材子地址
I2C_suba_num = 1; // 器材子地址为8+X
}

I2C_buf = s; // 数据
I2C_num = num; // 数据个数
I2C_suba_en = 2; // 有子地址,写操作
I2C_end = 0;

// 铲除STA,SI,AA标志位
I2C2CONCLR = (1 << 2)| // AA
(1 << 3)| // SI
(1 << 5); // STA

// 置位STA,发动I2C总线
I2C2CONSET = (1 << 5)| // STA
(1 << 6); // I2CEN

// 等候I2C操作完结
return( Wait_I2c_End(1000));

}
return (FALSE);
}

INT8U I2C_ReadNByte (INT8U sla, INT32U suba_type, INT32U suba, INT8U *s, INT32U num)
{

if (num > 0) // 判别num个数的合法性
{ // 参数设置
if (suba_type == 1)
{ // 子地址为单字节
I2C_sla = sla + 1; // 读器材的从地址,R=1
I2C_suba = suba; // 器材子地址
I2C_suba_num = 1; // 器材子地址为1字节
}
else if (suba_type == 2)
{ // 子地址为2字节
I2C_sla = sla + 1; // 读器材的从地址,R=1
I2C_suba = suba; // 器材子地址
I2C_suba_num = 2; // 器材子地址为2字节
}
else if (suba_type == 3)
{ // 子地址结构为8+X
I2C_sla = sla + ((suba >> 7 )& 0x0e) + 1; // 读器材的从地址,R=1
I2C_suba = suba & 0x0ff; // 器材子地址
I2C_suba_num = 1; // 器材子地址为8+x
}
I2C_buf = s; // 数据接纳缓冲区指针
I2C_num = num; // 要读取的个数
I2C_suba_en = 1; // 有子地址读
I2C_end = 0;

// 铲除STA,SI,AA标志位
I2C2CONCLR = (1 << 2)| // AA
(1 << 3)| // SI
(1 << 5); // STA

// 置位STA,发动I2C总线
I2C2CONSET = (1 << 5)| // STA
(1 << 6); // I2CEN

return( Wait_I2c_End(1000)); // 等候I2C操作完结

}
return (FALSE);

}

void I2C2_IRQ_ISR_handler(void)
{



switch (I2C2STAT & 0xF8)//0~6位是状况位
{ // 依据状况码进行相应的处理
case 0x08: // 已发送开始条件,主发送和主接纳都有,装入SLA+W或许SLA+R
if(I2C_suba_en == 1)// SLA+R // 指定子地址读
{
I2C2DAT = I2C_sla & 0xFE; // 先写入地址
}
else // SLA+W
{
I2C2DAT = I2C_sla; // 不然直接发送从机地址
}
// 清零SI位
I2C2CONCLR = (1 << 3)| // SI
(1 << 5); // STA
break;

case 0x10: // 已发送重复开始条件 // 主发送和主接纳都有
// 装入SLA+W或许SLA+R
I2C2DAT = I2C_sla; // 重起总线后,重发从地址
I2C2CONCLR = 0x28; // 清零SI,STA
break;

case 0x18:
case 0x28: // 已发送I2DAT中的数据,已接纳ACK
if (I2C_suba_en == 0)
{
if (I2C_num > 0)
{
I2C2DAT = *I2C_buf++;
I2C2CONCLR = 0x28; // 清零SI,STA
I2C_num–;
}
else // 没有数据发送了
{ // 中止总线
I2C2CONSET = (1 << 4); // STO
I2C2CONCLR = 0x28; // 清零SI,STA
I2C_end = 1; // 总线现已中止
}
}

else if(I2C_suba_en == 1) // 若是指定地址读,则重新发动总线
{
if (I2C_suba_num == 2)
{
I2C2DAT = ((I2C_suba >> 8) & 0xff);
I2C2CONCLR = 0x28; // 清零SI,STA
I2C_suba_num–;
break;
}

else if(I2C_suba_num == 1) //器材子地址为1字节
{
I2C2DAT = (I2C_suba & 0xff);
I2C2CONCLR = 0x28; // 清零SI,STA
I2C_suba_num–;
break;
}

else if (I2C_suba_num == 0)
{
I2C2CONCLR = 0x08;
I2C2CONSET = 0x20;
I2C_suba_en = 0; // 子地址己处理
break;
}
}
else if (I2C_suba_en == 2) // 指定子地址写,子地址没有指定
{ // 则发送子地址
if (I2C_suba_num > 0)
{


if (I2C_suba_num == 2)
{
I2C2DAT = ((I2C_suba >> 8) & 0xff);
I2C2CONCLR = 0x28;
I2C_suba_num–;
break;
}
else if (I2C_suba_num == 1) //器材子地址为1字节
{
I2C2DAT = (I2C_suba & 0xff);
I2C2CONCLR = 0x28;
I2C_suba_num–;
I2C_suba_en = 0;
break;
}
}
}
break;

case 0x40: // 已发送SLA+R,已接纳ACK
if (I2C_num <= 1) // 假如是最终一个字节
{
I2C2CONCLR = 1 << 2; // 下次发送非应对信号
}
else
{
I2C2CONSET = 1 << 2; // 下次发送应对信号
}
I2C2CONCLR = 0x28; // 清零SI,STA
break;

case 0x20: // 已发送SLA+W,已接纳非应对
case 0x30: // 已发送I2DAT中的数据,已接纳非应对
case 0x38: // 在SLA+R/W或数据字节中丢掉裁定

case 0x48: // 已发送SLA+R,已接纳非应对
I2C2CONCLR = 0x28;
I2C_end = 0xFF;
break;

case 0x50: // 已接纳数据字节,已回来ACK
*I2C_buf++ = I2C2DAT;
I2C_num–;
if (I2C_num == 1) // 接纳最终一个字节
{
I2C2CONCLR = 0x2C; // STA,SI,AA = 0
}
else
{
I2C2CONSET = 0x04; // AA=1
I2C2CONCLR = 0x28;
}
break;

case 0x58: // 已接纳数据字节,已回来非应对
*I2C_buf++ = I2C2DAT; // 读取最终一字节数据
I2C2CONSET = 0x10; // 完毕总线
I2C2CONCLR = 0x28;
I2C_end = 1;
break;

default:
break;
}
}

原因:指定suba_type参数不正确,假如器材的地址位宽是一字节,那么指定为1,假如地址位宽是两字节,那么指定为2。别的在读写操作时指定Wait_I2c_End(INT32 Dly)函数中的Dly值太小也不能操作成功,能够恰当放大些。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qianrushi/ruanjian/262706.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部