野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 10828|回复: 6

stm32 iic外设做从机

[复制链接]
发表于 2017-10-30 12:32:52 | 显示全部楼层 |阅读模式
stm32 iic外设做从机的时候,我要怎么样检查发的地址是不是我的?还有应答是自动应答,还是需要我们控制?

有什么函数可以解决吗?

回复

使用道具 举报

发表于 2017-10-30 13:41:05 | 显示全部楼层
没有试过做从机,帮顶
回复 支持 反对

使用道具 举报

发表于 2017-10-31 14:54:46 | 显示全部楼层
俺也没做过从机。。。如果你是使用的IIC外设,我认为应答的处理应该都是由硬件自动完成的,应该有相应的库函数的。
回复 支持 反对

使用道具 举报

发表于 2017-11-2 22:00:07 | 显示全部楼层
帮顶!最近我也在试着用STM32做从机,如有用过的朋友,请不吝赐教!谢谢!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-3-27 22:05:55 | 显示全部楼层
这个可以用。

#include "./iic/bsp_iic.h"
#include "bsp_usart.h"

void I2C_GPIO_Config(void)
{
       GPIO_InitTypeDef GPIO_InitStructure;
   
       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
       /*I2C1 and I2C2 Periph clock enable */
       RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

       /*Configure I2C1 pins: SCL and SDA ----------------------------------------*/
       GPIO_InitStructure.GPIO_Pin=  GPIO_Pin_6 | GPIO_Pin_7; //选择待设置的GPIO管脚 PB6 scl   pb7   sda
       GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;      //管脚速率50MHz
       GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF_OD;  //复用开漏输出
       
       GPIO_Init(GPIOB,&GPIO_InitStructure);

}
/*
void I2C_Master_Init(void)
{
         I2C_InitTypeDef  I2C_InitStructure;
     
       I2C_InitStructure.I2C_Mode= I2C_Mode_I2C;
       I2C_InitStructure.I2C_DutyCycle= I2C_DutyCycle_2;
       I2C_InitStructure.I2C_OwnAddress1= I2C1_SLAVE_ADDRESS7;
       I2C_InitStructure.I2C_Ack= I2C_Ack_Enable;
       I2C_InitStructure.I2C_AcknowledgedAddress= I2C_AcknowledgedAddress_7bit;
       I2C_InitStructure.I2C_ClockSpeed= ClockSpeed;
       I2C_Init(I2C1,&I2C_InitStructure);

         I2C_Cmd(I2C1, ENABLE);
}
*/

void I2C_Slave_Init(void)
{
       I2C_InitTypeDef  I2C_InitStructure;
       /*I2C2 configuration ------------------------------------------------------*/
                        //模式
       I2C_InitStructure.I2C_Mode =I2C_Mode_I2C;
                        //在快速模式下有意义
       I2C_InitStructure.I2C_DutyCycle= I2C_DutyCycle_2;
                        //地址
       I2C_InitStructure.I2C_OwnAddress1= I2C1_SLAVE_ADDRESS7;
                        //使能答应
       I2C_InitStructure.I2C_Ack= I2C_Ack_Enable;
                        //7位
       I2C_InitStructure.I2C_AcknowledgedAddress= I2C_AcknowledgedAddress_7bit;
      //时钟速率
                         I2C_InitStructure.I2C_ClockSpeed= ClockSpeed;
       
       I2C_Init(I2C1,&I2C_InitStructure);
        
                       
                               
//                         I2C_AcknowledgeConfig(I2C1, ENABLE);
       
                        I2C_ITConfig(I2C1,I2C_IT_ERR | I2C_IT_EVT| I2C_IT_BUF,ENABLE);
                       
                         I2C_Cmd(I2C1, ENABLE);
}
void NVIC_Config(void)
{
        NVIC_InitTypeDef NVIC_InitStructure;
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
       
        NVIC_InitStructure.NVIC_IRQChannel=I2C1_EV_IRQn;
       
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
       
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
       
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
       
        NVIC_Init(&NVIC_InitStructure);
}

void I2C_Mode_Init(void)
{
    I2C_GPIO_Config();
    I2C_Slave_Init();
                NVIC_Config();
}
//Clear ADDR by reading SR1, then SR2
void I2C_clear_ADDR(I2C_TypeDef* I2Cx)
        {
        I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR);
        ((void)(I2Cx->SR2));
        }

//Clear STOPF by reading SR1, then writing CR1
void I2C_clear_STOPF(I2C_TypeDef* I2Cx)
        {
        I2C_GetFlagStatus(I2Cx, I2C_FLAG_STOPF);
        I2C_Cmd(I2Cx, ENABLE);
        }



uint8_t data = 0;
void I2C1_EV_IRQHandler(void) {
//        GPIO_SetBits(GPIOD, GREEN); //Show that we got here
        //        KV1=0;
       
                //Clear AF from slave-transmission end
                if(I2C_GetITStatus(I2C1, I2C_IT_AF)) {
                        I2C_ClearITPendingBit(I2C1, I2C_IT_AF);
                }
                //Big state machine response, since doesn't actually keep state
                switch(I2C_GetLastEvent(I2C1)) {
                        //SLAVE
                        //Receive
                        case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED: //EV1        可以到这      
                                        printf("dao");
                                I2C_clear_ADDR(I2C1);
                                break;
                        case I2C_EVENT_SLAVE_BYTE_RECEIVED: //EV2
                                //Read it, so no one is waiting, clears BTF if necessary
                                data = I2C_ReceiveData(I2C1);
//                                LED1= !(data & 0x01);
//                                LED2= !(data & 0x02);
//                                LED3= !(data & 0x04);
//                                LED4= !(data & 0x08);
                                //Do something with it
                                if(I2C_GetFlagStatus(I2C1, I2C_FLAG_DUALF)) {//Secondary Receive
                                } else if(I2C_GetFlagStatus(I2C1, I2C_FLAG_GENCALL)) {//General Receive
                                } else {//Normal
                                }
                                break;
                        case I2C_EVENT_SLAVE_STOP_DETECTED: //End of receive, EV4
                                I2C_clear_STOPF(I2C1);
                                break;

                        //Transmit
                        case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED: //EV1                             
                                I2C_clear_ADDR(I2C1);
                        printf("dao1");
                                //Send first byte
                                I2C_SendData(I2C1, 0x26);                    //这个不能少,少了数据会发送错误
               
                                break;
                        case I2C_EVENT_SLAVE_BYTE_TRANSMITTED: //EV3
                                //Determine what you want to send
                                //data = 5;
                                if(I2C_GetFlagStatus(I2C1, I2C_FLAG_DUALF)) {//Secondary Transmit
                                } else if(I2C_GetFlagStatus(I2C1, I2C_FLAG_GENCALL)) {//General Transmit
                                } else {//Normal
                                }
                                //Read flag and write next byte to clear BTF if present
                                I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF);
                                I2C_SendData(I2C1,0x26);
                                break;
                        case I2C_EVENT_SLAVE_ACK_FAILURE://End of transmission EV3_2
                                //TODO: Doesn't seem to be getting reached, so just
                                //check at top-level
                                I2C_ClearITPendingBit(I2C1, I2C_IT_AF);
                                break;
                        //Alternative Cases for address match
                        case I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED: //EV1
                                break;
                        case I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED: //EV1
                                break;
                        case I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED: //EV1
                                break;


                        //MASTER
                        case I2C_EVENT_MASTER_MODE_SELECT: //EV5, just sent start bit
                                break;
                        //Receive
                        case I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED: //EV6, just sent addr   
                                break;
                        case I2C_EVENT_MASTER_BYTE_RECEIVED: //EV7
                                break;
                        //Transmit
                        case I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED: //EV6, just sent addr     
                                break;
                        case I2C_EVENT_MASTER_BYTE_TRANSMITTING: //EV8, about to send data
                                break;
                        case I2C_EVENT_MASTER_BYTE_TRANSMITTED: //EV8_2, just sent data
                                break;

                        //Alternative addressing stuff, not going to worry about
                        case I2C_EVENT_MASTER_MODE_ADDRESS10: //EV9
                                break;
                        default:
                                //How the FUCK did you get here?
                                //I should probably raise some error, but fuck it,
                                //it's late
                                break;
                }
}

void I2C1_ER_IRQHandler(void) {
//       GPIO_SetBits(GPIOD, RED);
//        LED3=0;
                //Can't use nice switch statement, because no fxn available
                if(I2C_GetITStatus(I2C1,        I2C_IT_SMBALERT)) {
                } else if(I2C_GetITStatus(I2C1, I2C_IT_TIMEOUT)) {
                } else if(I2C_GetITStatus(I2C1, I2C_IT_PECERR)) {
                } else if(I2C_GetITStatus(I2C1, I2C_IT_OVR)) {
                        //Overrun
                        //CLK stretch disabled and receiving
                        //DR has not been read, b4 next byte comes in
                        //effect: lose byte
                        //should:clear RxNE and transmitter should retransmit

                        //Underrun
                        //CLK stretch disabled and I2C transmitting
                        //haven't updated DR since new clock
                        //effect: same byte resent
                        //should: make sure discarded, and write next
                } else if(I2C_GetITStatus(I2C1, I2C_IT_AF)) {
                        //Detected NACK
                        //Transmitter must reset com
                                //Slave: lines released
                                //Master: Stop or repeated Start must must be generated
                                //Master = MSL bit
                        //Fixup
                        I2C_ClearITPendingBit(I2C1, I2C_IT_AF);
                } else if(I2C_GetITStatus(I2C1, I2C_IT_ARLO)) {
                        //Arbitration Lost
                        //Goes to slave mode, but can't ack slave address in same transfer
                        //Can after repeat Start though
                } else if(I2C_GetITStatus(I2C1, I2C_IT_BERR)) {
                        //Bus Error
                        //In slave mode: data discarded, lines released, acts like restart
                        //In master mode: current transmission continues
                }
}









//void I2C1_EV_IRQHandler(void)
//{
////        printf("Ylq"); //到这
////       
////        //check EV1 and clear it
////        while(!I2C_CheckEvent(I2C1,I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED));
////        //send data
////        printf("a");
////        I2C_SendData(I2C1,0x13);
////        printf("a");
////        while(!I2C_CheckEvent(I2C1,I2C_EVENT_SLAVE_BYTE_TRANSMITTED));
////        //clear EV3
////        I2C_SendData(I2C1,0);
////        printf("b");
////        while(!I2C_CheckEvent(I2C1,I2C_EVENT_SLAVE_ACK_FAILURE));
////        //clear i2c af flag
////        I2C_ClearFlag(I2C1,I2C_FLAG_AF);
////        printf("c");


//        //printf("8");
//        switch(I2C_GetLastEvent(I2C1))
//        {
//                    case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED:
//    {
//      //i2c is ready               
//      I2C_GenerateSTOP(I2C1, DISABLE);
//                        printf("地址匹配");
//      break;
//    }
//               
//                 case I2C_EVENT_SLAVE_BYTE_TRANSMITTING: //发送数据
//    {
//      I2C_SendData(I2C1,0x13);
//                        printf("发送数据");
//      break;
//    }

//   // 发送数据,要发送,不然锁死,不过 master 没收到

//    case I2C_EVENT_SLAVE_BYTE_TRANSMITTED:
//    {

//     I2C_SendData(I2C1,0x13);
//                        printf("发送完");

//      break;
//    }
//    case I2C_EVENT_SLAVE_STOP_DETECTED: //收到结束条件
//    {
//      I2C_ClearFlag(I2C1,I2C_FLAG_STOPF);
//                        printf("10");
//      I2C_GenerateSTOP(I2C1, ENABLE);
//                        printf("12");
//      break;
//    }
//                case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
//                {
//                        printf("4");
//      break;
//                }
//                case I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED:
//                {        printf("5");
//      break;
//                }
//                case I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED:
//                {
//                                printf("6");
//      break;
//                }

//    default: {break;}
//        }



//}

回复 支持 反对

使用道具 举报

发表于 2018-3-28 18:42:39 | 显示全部楼层
楼主这是实验成功了吗
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-4-3 23:50:05 | 显示全部楼层
凌晨6点的深圳 发表于 2018-3-28 18:42
楼主这是实验成功了吗

en ,可以用了
回复 支持 反对

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-5-15 00:10 , Processed in 0.045039 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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