[求助] 关于I2C从机通讯的问题

lifeissweet66   2012-9-13 14:26 楼主
各位大神,求助啊,我没玩过I2C,这是我东拼西凑些的I2C从机代码,主要是完成和主机的通讯用的。但是先在问题出来了,代码运行时,主机向0xA0发送一个数据,
从机能进中断( I2C2_EV_IRQHandler)函数,在switch (I2C_Event)这一句时,I2C各个寄存器函数如下:
图片看不到.............算了,手打

I2C2_CR1            0x00000401
I2C2_CR2            0x00000624   
I2C2_OAR1          0x000040A0
I2C2_OAR2          0
I2C2_DR              0
I2C2_SR1            0x00000110
I2C2_SR2            0
I2C2_CCR           0x0000801E
I2C2_TRISE         0x0000000B

[ 本帖最后由 lifeissweet66 于 2012-9-13 14:47 编辑 ]

回复评论 (10)

为什么发的图片看不到?
点赞  2012-9-13 14:41
谢谢,我还是手工吧,下面的是mian.c文件

[ 本帖最后由 lifeissweet66 于 2012-9-13 15:01 编辑 ]
点赞  2012-9-13 14:42

回复 4楼 lifeissweet66 的帖子

图片不能复制,先下载再上传试试!
点赞  2012-9-13 14:50
#include "includes.h"


/* Private typedef -----------------------------------------------------------*/
typedef enum
{
        FAILED = 0,
        PASSED = !FAILED
}TestStatus;
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
extern void RCC_Configuration(void);
extern void GPIO_Configuration(void);
extern void delay_ms(u16 nms);
extern void delay_init(u8 SYSCLK);
extern void NVIC_Configuration(void);
extern void LED_On(LED_STATE led_status);
void  I2C_Comm_Init(u32 I2C_Speed, u16 I2C_Addr);
/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program
  * @param  None
  * @retval : None
  */
int main(void)
{
          /********************初始化函数*********************************/
          RCC_Configuration();
          GPIO_Configuration();
        I2C_Comm_Init(400000,0xa0);

          delay_init(72);
          while(1)
    {
                LED_On(LED1);
              delay_ms(500);
                LED_On(LED2);
              delay_ms(500);
              LED_On(LED3);
              delay_ms(500);
                LED_On(LED4);
              delay_ms(500);
    }
}


void  I2C_Comm_Init(u32 I2C_Speed, u16 I2C_Addr)
{
/******* GPIO configuration and clock enable *********/
  GPIO_InitTypeDef  GPIO_InitStructure;
  I2C_InitTypeDef  I2C_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
   
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_10| GPIO_Pin_11;      
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  
/*********** I2C periphral configuration **********/
  I2C_DeInit(I2C2);
  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; // fixed
  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;  // fixed
  I2C_InitStructure.I2C_OwnAddress1 = I2C_Addr;  // user parameter
  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; // fixed
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  I2C_InitStructure.I2C_ClockSpeed = I2C_Speed; // user parameter
  I2C_Cmd(I2C2, ENABLE);
  I2C_Init(I2C2, &I2C_InitStructure);

  I2C_ITConfig(I2C2, I2C_IT_EVT | I2C_IT_BUF, ENABLE);
/************** I2C NVIC configuration *************************/  
/* 1 bit for pre-emption priority, 3 bits for subpriority */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

    NVIC_InitStructure.NVIC_IRQChannel = I2C2_EV_IRQChannel;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
   
    NVIC_InitStructure.NVIC_IRQChannel = I2C2_ER_IRQChannel;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}
void I2C2_EV_IRQHandler(void)
{
        uint32_t I2C_Event;
        int i=0;
        i++;
        if(i==2)
        {
                i=0;
        }
       
          I2C_Event = I2C_GetLastEvent(I2C2);
          switch (I2C_Event)
          {
                  //case 0x20002:
                        //while(1);
                  case 0x20401:
                        while(1);
                case 0x20624:
                        while(1);
                case 0x20000:
                        while(1);
                case 0x20328:
                        while(1);
                case 0x20025:
                        while(1);
                  case 0x240A0:
                        while(1);
                  case 0x20110:
                        while(1);
                case 0x00110:
                        while(1);
/***********************slave receiver**************************************/
                case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:     /* EV1 */   
                     I2C_ITConfig(I2C2, I2C_IT_BUF , ENABLE); // also allow RxNE
                break;

              case I2C_EVENT_SLAVE_BYTE_RECEIVED:                /* EV2 */
                        /* Store I2C1 received data */
     
                     *pRxBuffer++ = I2C_ReceiveData(I2C2);
                     RxLength--;
                     if (RxLength == 0)
                {
                    //SlaveReceptionComplete = 1;
                    I2C_ITConfig(I2C2, I2C_IT_BUF , DISABLE); // only EVT(STOPF) int
                    I2C_ITConfig(I2C2, I2C_IT_EVT , ENABLE);
                }
          break;   

              case I2C_EVENT_SLAVE_STOP_DETECTED:                /* EV4 */
                        /* Clear I2C1 STOPF flag: read of I2C_SR1 followed by a write on I2C_CR1 */
                 (void)(I2C_GetITStatus(I2C2, I2C_IT_STOPF));
               I2C_Cmd(I2C2, ENABLE);
//                i2c_comm_state = COMM_DONE;
                        I2C_ITConfig(I2C2, I2C_IT_EVT, DISABLE);
                        break;
   
            case 0x20050:
                      // used when Rx and Tx handley by one mcu at the same time
                      // receive last data and clear stopf
                      // BUSY+RxNE+STOP
                *pRxBuffer++ = I2C_ReceiveData(I2C2);
                RxLength--;
                //SlaveReceptionComplete = 1;

                (void)(I2C_GetITStatus(I2C2, I2C_IT_STOPF));
                I2C_Cmd(I2C2, ENABLE);
                I2C_ITConfig(I2C2, I2C_IT_EVT | I2C_IT_BUF, DISABLE);
                I2C_ITConfig(I2C2, I2C_IT_BUF , DISABLE);
                break;
        
            case 0x20010:
                      // busy+stopf
                      // when last data read isr exist, there would be stopf flag
                      //which is set during read ISR. and as sender's check begin
                      // busy also set
//                      i2c_comm_state = CHECK_IN_PROCESS;
                      (void)(I2C_GetITStatus(I2C2, I2C_IT_STOPF));
                I2C_Cmd(I2C2, ENABLE);
                break;   
        
            default:
                break;

/***********************slave t**************************************/
          case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED:         // EV1
       
//                        i2c_comm_state = COMM_IN_PROCESS;
                             I2C_SendData(I2C2, *pTxBuffer++);
                      TxLength--;
                        I2C_ITConfig(I2C2, I2C_IT_BUF , ENABLE); // also allow RxNE
               break;
        case I2C_EVENT_SLAVE_BYTE_TRANSMITTED:              // EV3
       
                //TRA, BUSY, TXE and BTF  0x60084
        if (TxLength>0)
        {
            I2C_SendData(I2C2, *pTxBuffer++);
            TxLength--;
        }
        break;
        case 0x60080:
      // TRA, BUSY,TXE, no BTF
      // if this case added, above case would never be reached
      if (TxLength>0)
        {
            I2C_SendData(I2C2, *pTxBuffer++);
            TxLength--;
            if (TxLength ==0)
            {
              //SlaveTransitionComplete =1;
//             i2c_comm_state = COMM_DONE;
              I2C_ITConfig(I2C2, I2C_IT_BUF , DISABLE);//close TxE int
              I2C_ITConfig(I2C2, I2C_IT_ERR , ENABLE);//to handle AF from master receiver
              //PV_flag_2 = 0;
            }
        }      
      break;   
          }
}

#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *   where the assert_param error has occurred.
  * @param file: pointer to the source file name
  * @param line: assert_param error line source number
  * @retval : None
  */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  while (1)
  {}
}
#endif

/**
  * @}
  */

/**
  * @}
  */

/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/
点赞  2012-9-13 15:00
关于主函数我说明下,在 I2C2_EV_IRQHandler中最前面几个case是我测试最后进入哪儿用的,经测试,每次都是死在case 0x20110上,然后我返回去进入I2C_GetLastEvent(I2C2)中计算了下:
            他有三个标志位:flag1,flag2,lastevent
            flag1 = I2C->SR1
            flag2 = I2C ->SR2
            flag2 = flag2 << 16
            lastevent = (flag1 | flag2 ) & 0x1F
            return lastevent;
把最上面的寄存器值代入我计算了下lastevent = 0x20110
点赞  2012-9-13 15:07
B0F6ED4@0@(HU9OJTHQ_0P2.jpg 这是我的文件目录,关于I2C的都写在main.c中
点赞  2012-9-13 15:11
下面是操作流程:
点赞  2012-9-13 15:12
下载并运行从机上 006.jpg 的程序,并在中断中设置断点
点赞  2012-9-13 15:18
007.jpg 发送一字节数据
008.jpg
进入中断,寄存器的值如上
点赞  2012-9-13 15:20
有木有大神讲解一下啊 憋了几周了都没调好
点赞  2012-9-13 15:23
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复