打印
[DSP编程]

DSP28335 I2C 程序

[复制链接]
10398|27
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
pandabin|  楼主 | 2014-4-17 22:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
I2C程序调了好几天了,还没有调通,存在的问题是:一直收不到应答信号。如下,由IntSource==I2C_ARDY_ISRC引起中断,然后就进入:
if(I2caRegs.I2CSTR.bit.NACK == 1)
      {
         I2caRegs.I2CMDR.bit.STP = 1;
         I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;
         Count3++;
      }

Count3一直在自加,而没执行CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_RESTART;
包括写数据时也受不应答信号。什么原因引起的呢了,外设器件有问题吗??

// Interrupt source = Register Access Ready
   // This interrupt is used to determine when the RTC address setup portion of the
   // read data communication is complete. Since no stop bit is commanded, this flag
   // tells us when the message has been sent instead of the SCD flag. If a NACK is
   // received, clear the NACK bit and command a stop. Otherwise, move on to the read
   // data portion of the communication.
   else if(IntSource == I2C_ARDY_ISRC)
   {
      if(I2caRegs.I2CSTR.bit.NACK == 1)
      {
         I2caRegs.I2CMDR.bit.STP = 1;
         I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT;
         Count3++;
      }
      else if(CurrentMsgPtr->MsgStatus == I2C_MSGSTAT_SEND_NOSTOP_BUSY)
      {
         CurrentMsgPtr->MsgStatus = I2C_MSGSTAT_RESTART;
         Count4++;
      }
   }  // end of register access ready

相关帖子

沙发
zhangmangui| | 2014-4-17 23:46 | 只看该作者
板凳
pandabin|  楼主 | 2014-4-20 16:38 | 只看该作者
又查看了两天代码,还是没能解决。将程序附上,请最近在玩28335 i2c的高手指点一下。 boot to RAM ,外设i2c器件MAX44009。写数据时,收不到应答信号。

I2C2.rar

130.61 KB

使用特权

评论回复
地板
pandabin|  楼主 | 2014-4-20 16:40 | 只看该作者

使用特权

评论回复
5
pandabin|  楼主 | 2014-4-26 00:22 | 只看该作者
结贴了!调试了好久,最终锁定是外设I2C模块出了问题。不过这个调试过程,还是让自己对I2C有了更多的了解和熟悉。
自己认为需要注意的两点,当然也是在论坛内学到的知识。
1:I2caRegs.I2CSAR = (msg->SlaveAddress)>>1; 查看datasheet理解此语句
2:SDA数据线会先移出I2caRegs.I2CSAR 寄存器中的值,以选定从器件。而读写控制位是I2C模块根据 I2caRegs.I2CMDR.all = 0x2C20;(或I2caRegs.I2CMDR.all = 0x2620;)自动添加的,不需要在程序中手动添加。
(这两点某前辈在论坛内提到,对自己有了点拨,在此谢过!)

使用特权

评论回复
6
raoxianbin| | 2014-4-27 20:41 | 只看该作者
pandabin 发表于 2014-4-26 00:22
结贴了!调试了好久,最终锁定是外设I2C模块出了问题。不过这个调试过程,还是让自己对I2C有了更多的了解和 ...

请问楼主,第一条语句为什么要右移一位呢

使用特权

评论回复
7
pandabin|  楼主 | 2014-4-27 21:27 | 只看该作者
raoxianbin 发表于 2014-4-27 20:41
请问楼主,第一条语句为什么要右移一位呢

在7位地址模式时,I2CSAR 寄存器中[6:0]位放从地址码,八位数里,高七位为地址为,最后一位为读写控制位,我要将读写控制位给移出

使用特权

评论回复
8
LENA989| | 2014-7-8 00:56 | 只看该作者

使用特权

评论回复
9
1831249703| | 2015-4-17 17:06 | 只看该作者
pandabin 发表于 2014-4-26 00:22
结贴了!调试了好久,最终锁定是外设I2C模块出了问题。不过这个调试过程,还是让自己对I2C有了更多的了解和 ...

可以把您调通的资料给我一份吗

使用特权

评论回复
10
海中水| | 2015-4-17 17:20 | 只看该作者
仔细的参考一下I2C通信协议就知道了。

使用特权

评论回复
11
1831249703| | 2015-4-18 13:06 | 只看该作者
海中水 发表于 2015-4-17 17:20
仔细的参考一下I2C通信协议就知道了。

我查看了,但是我感觉例程给的我看不怎么懂,麻烦您给一份你调通的吗

使用特权

评论回复
12
海中水| | 2015-4-18 14:38 | 只看该作者
1831249703 发表于 2015-4-18 13:06
我查看了,但是我感觉例程给的我看不怎么懂,麻烦您给一份你调通的吗

好的我周一帮你看看,看看能不能帮你调通一下。

使用特权

评论回复
13
悦待伊人| | 2015-4-18 22:34 | 只看该作者
多谢

使用特权

评论回复
14
1831249703| | 2015-4-20 12:37 | 只看该作者
海中水 发表于 2015-4-18 14:38
好的我周一帮你看看,看看能不能帮你调通一下。

最近这两天有波形了,但是波形对应的不对,我只发一帧,从开始到停止应该有八个周期的scl,但是有九个,我把我的程序传给你,麻烦您看看吧,看看哪里不对,我的目的就是循环发送一帧数据,从地址为0x90

使用特权

评论回复
15
1831249703| | 2015-4-20 12:37 | 只看该作者
海中水 发表于 2015-4-18 14:38
好的我周一帮你看看,看看能不能帮你调通一下。



#include "DSP28x_Project.h"     // Device Headerfile and Examples Include File

// Note: I2C Macros used in this example can be found in the
// DSP2833x_I2C_defines.h file

// Prototype statements for functions found within this file.
void   I2CA_Init(void);
void I2CA_WriteData(Uint16 data);//写数据

#define I2C_SLAVE_ADDR        0x91//从地址
#define I2C_NUMBYTES          4//传输字节数
#define I2C_EEPROM_HIGH_ADDR  0x00//高位地址
#define I2C_EEPROM_LOW_ADDR   0x30//低位地址

void main(void)
{
   
   Uint16 i;


// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the DSP2833x_SysCtrl.c file.
   InitSysCtrl();


// Step 2. Initalize GPIO:
// This example function is found in the DSP2833x_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
// InitGpio();
// Setup only the GP I/O only for I2C functionality
   InitI2CGpio();

// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
   DINT;

// Initialize PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the DSP2833x_PieCtrl.c file.
   InitPieCtrl();

// Disable CPU interrupts and clear all CPU interrupt flags:
   IER = 0x0000;
   IFR = 0x0000;

// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example.  This is useful for debug purposes.
// The shell ISR routines are found in DSP2833x_DefaultIsr.c.
// This function is found in DSP2833x_PieVect.c.
   InitPieVectTable();

// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
   EALLOW;        // This is needed to write to EALLOW protected registers
  // PieVectTable.I2CINT1A = &i2c_int1a_isr;
   EDIS;   // This is needed to disable write to EALLOW protected registers

// Step 4. Initialize all the Device Peripherals:
// This function is found in DSP2833x_InitPeripherals.c
// InitPeripherals(); // Not required for this example
   I2CA_Init();



// Enable interrupts required for this example

// Enable I2C interrupt 1 in the PIE: Group 8 interrupt 1
   PieCtrlRegs.PIEIER8.bit.INTx1 = 1;

// Enable CPU INT8 which is connected to PIE group 8
//   IER |= M_INT8;
   EINT;   
         I2CA_WriteData(0x0000);     
}   // end of main

void I2CA_Init(void)
{
   // Initialize I2C
   I2caRegs.I2CMDR.bit.IRS = 0;
   //I2caRegs.I2CSAR = 0x0090;                // Slave address - EEPROM control code

   #if (CPU_FRQ_150MHZ)             // Default - For 150MHz SYSCLKOUT
        I2caRegs.I2CPSC.all = 14;   // Prescaler - need 7-12 Mhz on module clk (150/15 = 10MHz)
   #endif
   #if (CPU_FRQ_100MHZ)             // For 100 MHz SYSCLKOUT
     I2caRegs.I2CPSC.all = 9;            // Prescaler - need 7-12 Mhz on module clk (100/10 = 10MHz)
   #endif

   I2caRegs.I2CCLKL = 10;                        // NOTE: must be non zero
   I2caRegs.I2CCLKH = 5;                        // NOTE: must be non zero
   I2caRegs.I2CIER.all = 0x24;                // Enable SCD & ARDY interrupts

   I2caRegs.I2CMDR.all = 0x0020;        // Take I2C out of reset

                                                                           // Stop I2C when suspended

//   I2caRegs.I2CSTR.bit.ARDY=1;
//   I2caRegs.I2CFFTX.all = 0x6000;        // Enable FIFO mode and TXFIFO
//   I2caRegs.I2CFFRX.all = 0x2040;        // Enable RXFIFO, clear RXFFINT,


}


void I2CA_WriteData(Uint16 data)
{
  char Busy_flag;
   Busy_flag = I2caRegs.I2CSTR.bit.BB;//判断总线是否忙
   if(!Busy_flag)
   {   

            I2caRegs.I2CSAR = 0x90;
              I2caRegs.I2CCNT = 1;                    
        I2caRegs.I2CDXR = data;
      
      while(I2caRegs.I2CSTR.bit.XRDY==0)
       I2caRegs.I2CMDR.all = 0x6E20;     
      //  while(I2caRegs.I2CSTR.bit.XRDY==1)
      //    I2caRegs.I2CDXR = data;
         
             if(I2caRegs.I2CSTR.bit.SCD==0)
                        for(;;);
              if(I2caRegs.I2CSTR.bit.SCD==1)
            I2CA_WriteData(0x00);
}


}

使用特权

评论回复
16
海中水| | 2015-4-20 12:43 | 只看该作者
1831249703 发表于 2015-4-20 12:37
最近这两天有波形了,但是波形对应的不对,我只发一帧,从开始到停止应该有八个周期的scl,但是有九个, ...

不是吧!你仔细看看I2C的通信协议,应该是有9个时钟信号的。最后一个是应答信号。前几天没有调通是什么原因呢?在这里分享一下吧!

使用特权

评论回复
17
1831249703| | 2015-4-20 12:58 | 只看该作者
海中水 发表于 2015-4-20 12:43
不是吧!你仔细看看I2C的通信协议,应该是有9个时钟信号的。最后一个是应答信号。前几天没有调通是什么原 ...

但是数据位对应不上呢,无论发送寄存器被赋值为多少,sda都不变,你帮我看看程序哪里错了吧,先谢谢了

使用特权

评论回复
18
1831249703| | 2015-4-20 14:14 | 只看该作者
海中水 发表于 2015-4-20 12:43
不是吧!你仔细看看I2C的通信协议,应该是有9个时钟信号的。最后一个是应答信号。前几天没有调通是什么原 ...

还有两个疑问:例程中为何在发送时,先往I2CDXR发送两字节地址,再接着发送四字节数据后才配置I2CMDR。个人理解是否应一个一个的发数据,因为发送寄存器是只有一个的,一次写那么多,怎么发呢

使用特权

评论回复
19
海中水| | 2015-4-20 18:16 | 只看该作者
1831249703 发表于 2015-4-20 14:14
还有两个疑问:例程中为何在发送时,先往I2CDXR发送两字节地址,再接着发送四字节数据后才配置I2CMDR。个 ...

你仔细查看一下它的发送格式,这上面没有发送两个字节的地址。
I2caRegs.I2CSAR = 0x90;这个只是说要发送的目的地址,这个寄存器里面只有0~9位是有用的。
I2caRegs.I2CCNT=1;这个指定了发送的字节数。
I2caRegs.I2CDXR=data; 这个是要发送的数据,虽然说数据是16位的,但是真正有效的位是低八位,高八位无效。
while(I2caRegs.I2CSTR.bit.XRDY == 0)I2caRegs.I2CMDR.all = 0x6E20;这个操作时等待发送就绪。
这些在数据手册中都有的。你可以仔细查看一下。

使用特权

评论回复
20
1831249703| | 2015-4-20 19:30 | 只看该作者
海中水 发表于 2015-4-20 18:16
你仔细查看一下它的发送格式,这上面没有发送两个字节的地址。
I2caRegs.I2CSAR = 0x90;这个只是说要发送 ...

这些位的设置我知道,版主不好意思,让你看的是我写的,不是例程,下边的是例程就是例程中在发送时,先往I2CDXR发送两字节地址,再接着发送四字节数据后才配置I2CMDR。个人理解是否应一个一个的发数据,在每一帧发送数据的时候找好对应的标志位,因为发送寄存器是只有一个的,一次写那么多,怎么发呢?下边的为例程
Uint16 I2CA_WriteData(struct I2CMSG *msg)
{
   Uint16 i;

   // Wait until the STP bit is cleared from any previous master communication.
   // Clearing of this bit by the module is delayed until after the SCD bit is
   // set. If this bit is not checked prior to initiating a new message, the
   // I2C could get confused.
   if (I2caRegs.I2CMDR.bit.STP == 1)
   {
      return I2C_STP_NOT_READY_ERROR;
   }

   // Setup slave address
   I2caRegs.I2CSAR = msg->SlaveAddress;

   // Check if bus busy
   if (I2caRegs.I2CSTR.bit.BB == 1)
   {
      return I2C_BUS_BUSY_ERROR;
   }

   // Setup number of bytes to send
   // MsgBuffer + Address
   I2caRegs.I2CCNT = msg->NumOfBytes+2;

   // Setup data to send
   I2caRegs.I2CDXR = msg->MemoryHighAddr;
   I2caRegs.I2CDXR = msg->MemoryLowAddr;
// for (i=0; i<msg->NumOfBytes-2; i++)
   for (i=0; i<msg->NumOfBytes; i++)

   {
      I2caRegs.I2CDXR = *(msg->MsgBuffer+i);
   }

   // Send start as master transmitter
   I2caRegs.I2CMDR.all = 0x6E20;

   return I2C_SUCCESS;
}

使用特权

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

本版积分规则

4

主题

14

帖子

1

粉丝