OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3796|回复: 3

I2C从机中断收发数据过程中字节丢失

[复制链接]

1

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2018-4-26
在线时间
7 小时
发表于 2018-4-27 10:24:32 | 显示全部楼层 |阅读模式
15金钱
我的I2C从机中断在从机发送过程中,丢失字节很严重,我这边收到的数据应该是没问题的,但可能发送这边出了点问题,上网查了下,可能是我这边在发最后以一个数据前必须给一个NACK和STOP,然后再发最后一位数据,但是这个NACK不是主机那边发给我的吗?求助大神  我这边I2C接收到数据后是放到一个全局数组里,然后再在主函数判断这个数组,并发送相应的数据过去,这个为(SendBuf[8])全局的


void App_I2C1_Configuration(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
        I2C_InitTypeDef  I2C_InitStructure;
                NVIC_InitTypeDef NVIC_InitStructure;
       
        //I2C_DeInit(I2C1) ;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
       
       
        GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE);   
       
        // I2C1 SDA and SCL configuration
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_OD;            
        GPIO_Init(GPIOB, &GPIO_InitStructure);


        /* I2C1  configuration */
        I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;                  //选择为I2C模式
        I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;         //该参数只有在I2C 工作在快速模式(时钟工作频率高于 100KHz)下才有意义。
        I2C_InitStructure.I2C_OwnAddress1 = 0x70;
        I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;          //收到数据后通过硬件自动发出应答信号
        I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
        I2C_InitStructure.I2C_ClockSpeed = 300000;            //该参数用来设置时钟频率,这个值不能高于400KHz

        I2C_Init(I2C1, &I2C_InitStructure);
               
               
               
               
                /* Configure and enable I2Cx event interrupt -------------------------------*/  
                NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;  
                NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
                NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  
                NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
                NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);//中断分组
                NVIC_Init(&NVIC_InitStructure);  


               
                /* Configure and enable I2C1 error interrupt -------------------------------*/  
                NVIC_InitStructure.NVIC_IRQChannel = I2C1_ER_IRQn;
                NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;                
                NVIC_InitStructure.NVIC_IRQChannelSubPriority =1 ;
                NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
                NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);//中断分组
                NVIC_Init(&NVIC_InitStructure);

               
                I2C_ITConfig(I2C1, I2C_IT_EVT | I2C_IT_ERR| I2C_IT_BUF , ENABLE); //开启缓存器中断和事件中断
        I2C_Cmd(I2C1, ENABLE);
}
/*
函数名: void I2C1_EV_IRQHandler(void)  

* 功能;I2C接收和发送中断
* 输入:无
* 输出:无
* 返回值:无
*/
u8 data = 0;
u8 S_data=0;
u8 RecevieBufA[8];         //从机接收操作
u8 RecevieBufB[8];
u8 SendBuf[8];
void I2C1_EV_IRQHandler(void)
{
        static u8 i;
       
        //Clear AF from slave-transmission end
        if(I2C_GetITStatus(I2C1, I2C_IT_AF))
        {
               
          I2C_ClearITPendingBit(I2C1, I2C_IT_AF);
        }
        switch(I2C_GetLastEvent(I2C1))
          {
                case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED: //EV1 start
                I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR);
                ((void)(I2C1->SR1));
                ((void)(I2C1->SR2));
                break;
               
                case I2C_EVENT_SLAVE_BYTE_RECEIVED: //EV2 receive                  
                RecevieBufA[data] = I2C_ReceiveData(I2C1);
                data++;
                break;
               
                case I2C_EVENT_SLAVE_STOP_DETECTED: //End of receive, EV4
                if((data==8)||(data==1))
                {
                        if((RecevieBufA[0]>=Button)&&(RecevieBufA[0]<=Wdg))
                        {
                                for(i=0;i<=7;i++)
                                {
                                        RecevieBufB[i]=RecevieBufA[i];
                                        RecevieBufA[i]=0;
                                }
                        data=0;       
                        }
                        else
                        {
                                for(i=0;i<=7;i++)
                                {
                                        RecevieBufA[i]=0;
                                }
                                data=0;
                        }       
                }
                else
                {
                        for(i=0;i<=7;i++)
                        {
                                RecevieBufA[i]=0;
                        }
                        data=0;
                }
               
                I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF);                 
                I2C_Cmd(I2C1, ENABLE);
                break;

                //send
                case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED: //EV1 start
                I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR);
                ((void)(I2C1->SR2));
                //Send first byte       

                I2C_SendData(I2C1, SendBuf[S_data]);       
                SendBuf[S_data]=0;
                S_data++;
                break;
         
                case I2C_EVENT_SLAVE_BYTE_TRANSMITTING:   //EV3.1
                break;
                case I2C_EVENT_SLAVE_BYTE_TRANSMITTED: //EV3 send
                I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF);

                I2C_SendData(I2C1, SendBuf[S_data]);
                SendBuf[S_data]=0;         
                S_data++;
                if(S_data>7)
                {S_data=0;}
                break;
               
                case I2C_EVENT_SLAVE_ACK_FAILURE://End of send EV3_2
                I2C_ClearITPendingBit(I2C1, I2C_IT_AF);
                break;
       
                default:  
                break;
        }
}
I2C_AcknowledgeConfig(I2C1,DISABLE);
/*
函数名:void I2C1_ER_IRQHandler(void)

* 功能;I2C错误中断
* 输入:无
* 输出:无
* 返回值:无
*/

void I2C1_ER_IRQHandler(void)
{
        /* Check on I2C1 AF flag and clear it */   
        if (I2C_GetITStatus(I2C1, I2C_IT_AF)) //no ACK
        {   
                I2C_ClearITPendingBit(I2C1, I2C_IT_AF);   
                //data = 0;   
                //S_data=0;
        }     
        /* Check on I2C1 AF flag and clear it */   
        if (I2C_GetITStatus(I2C1, I2C_IT_BERR)) // start and stop error
        {   
                I2C_ClearITPendingBit(I2C1, I2C_IT_BERR);   
        }
}


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2018-4-26
在线时间
7 小时
 楼主| 发表于 2018-4-27 10:24:33 | 显示全部楼层
回复

使用道具 举报

1

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
57
金钱
57
注册时间
2018-4-26
在线时间
7 小时
 楼主| 发表于 2018-4-27 10:38:22 | 显示全部楼层
我想了想,也不一定是发送的问题,可能接收有误。if((data==8)||(data==1))这个我已经限定了,如果接收不到正确的数,就不发送,结果确实是接收少了,我这边就不发
回复

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
13
金钱
13
注册时间
2020-3-13
在线时间
3 小时
发表于 2020-3-16 09:29:38 | 显示全部楼层
料你见我应如是 发表于 2018-4-27 10:38
我想了想,也不一定是发送的问题,可能接收有误。if((data==8)||(data==1))这个我已经限定了,如果接收不到 ...

老哥你改了哪里解决了啊
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-22 16:27

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表