×
单片机 > 单片机程序设计 > 详情

STM32F103 Slave I2C配置

发布时间:2020-05-19 发布时间:
|

才接触STM32开发,由于项目需求需要,需要linux系统与STM32通过I2C进行通讯,网上合适资料有限,花了不少时间,所以记录在此。


描述:Linux发送数据后,每隔10ms轮询stm32(应该做中断触发的,但由于硬件接口限制),只读一个字节判断是否有数据,如果有则读相应长度的内容。


自定义缓冲区格式:首字节为长度信息,后面是内容信息,如

uint8_t I2C_Buffer_Rx[128];//0:len  1...=>data

(1)I2C Slave初始化


void IIC_Init(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

  I2C_InitTypeDef I2C_InitStructure;

 

  RCC_APB2PeriphClockCmd  (RCC_APB2Periph_GPIOB , ENABLE);

 

 

   /* Configure I2C2 pins: SCL and SDA */ 

   GPIO_InitStructure.GPIO_Pin =   GPIO_Pin_10|GPIO_Pin_11; //10:SCL 11:SDA

   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//Out_PP;

   GPIO_Init(GPIOB, &GPIO_InitStructure);   

   RCC_APB1PeriphClockCmd  (RCC_APB1Periph_I2C2, ENABLE); 

   I2C_DeInit(I2C2);

   I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

   I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

   I2C_InitStructure.I2C_OwnAddress1 = 0x10<<1;//temp addr

   I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;

   I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

   I2C_InitStructure.I2C_ClockSpeed = 400000;

   I2C_Init(I2C2, &I2C_InitStructure);

   I2C_ITConfig(I2C2, I2C_IT_EVT|I2C_IT_BUF, ENABLE);

   I2C_Cmd(I2C2,ENABLE);

}

(2)I2C中断配置

void NVIC_Configuration(void)

{

  NVIC_InitTypeDef NVIC_InitStructure;

 

  NVIC_InitStructure.NVIC_IRQChannel = I2C2_EV_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

 

}


上述两条是基本操作,仔细看参数是没啥问题,最麻烦的是I2C状态,使用官方的问题很大,例如:

#define  I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED       ((uint32_t)0x00060082) /* TRA, BUSY, TXE and ADDR flags */


而实还有0x20402的情况,类似情况太多了,经常冒出一个新状态,并且接收和停止可能合在一起。我开始使用case语句来判断状态的,待状态测试稳定后使用if来进行Bit位判断,目前比较稳定。见I2C中断处理。


(3)I2C中断处理


此地方核心是I2C状态处理,收发的数据格式类似串口操作,代码如下:


uint8_t I2C_Buffer_Rx[128];//0:len  1...=>data

static uint8_t I2C_Buffer_Tx[128];//0:len  1...=>data

void I2C2_EV_IRQHandler(void)

{

     uint32_t  I2CFlagStatus;

     static uint8_t num = 0;

 

     I2CFlagStatus = I2C_GetLastEvent(I2C2);  // =>  (SR2<<16|SR1)

 

     if ((I2CFlagStatus & 0x02) != 0){ //bit1:addr matched

           if(I2CFlagStatus & 0x80) //bit7 Data register empty (transmitters)

            {//read            

               num = 0;  

               I2C_SendData(I2C2, I2C_Buffer_Tx[num]);

           }else{ 

               num = 1;  

              I2C_Buffer_Tx[0] = 0;

              I2C_Buffer_Rx[0] = 0;

             }

     }else if((I2CFlagStatus & 0x80) != 0){ // bit7  TxE  -Data register empty (transmitters)

           if((I2CFlagStatus & 0x04)==0){ //bit2  BTF (Byte transfer finished)

                num++;

                I2C_SendData(I2C2, I2C_Buffer_Tx[num]); //printf("I2C status:0x%xrn", I2CFlagStatus);

           }

     }else if((I2CFlagStatus & 0x40)&&(I2CFlagStatus & 0x10)){  //bit6(RxNE) +  bit4(STOPF) 

           I2C_Buffer_Rx[num] = I2C_ReceiveData(I2C2);    //g_debug_count1++;

            num++;   

           I2C_Buffer_Rx[0] = num-1;

           I2C2->CR1 |= 0x1000;//CR1_PEC_Set;

     }else if((I2CFlagStatus & 0x40) != 0){ //bit6  RxNE    -Data register not empty (receivers))

           I2C_Buffer_Rx[num] = I2C_ReceiveData(I2C2);   

           num++;     

     }else if((I2CFlagStatus & 0x10) != 0){ //bit4  STOPF -Stop detection (slave mode)

           I2C_Buffer_Rx[0] = num-1;

           I2C2->CR1 |= 0x1000;//CR1_PEC_Set;

     }else{

         printf("I2C error status:0x%xrn", I2CFlagStatus);

     }

 

I2C2->SR1=0;

I2C2->SR2=0;

}


(4)数据接收处理

我传输的数据长度是7到128字节之间。


void Recive_RXD_Deal(void)

{//I2C_Buffer_Rx  0:len  1->data

u8 i,len;

  

       len = I2C_Buffer_Rx[0];

if(len)

{

/*printf("i2c recv len:%d:",len);

for(i=1; i<=len; i++)

printf(" %x ",I2C_Buffer_Rx[i]);

printf("endrn");*/

    

                  if(len < 7) return;

       

     if( len != (I2C_Buffer_Rx[3]+1)) return;    

             

     if(I2C_Buffer_Rx[len-1] == (unsigned char )(Cheak_Sum(len-4, I2C_Buffer_Rx+3) &0xff))

UART2RXBuffer_Checked = &I2C_Buffer_Rx[1];

RXD_Deal_PROCESS();

}else{

    printf("checksum error data[%d]=> ",len);

    for(i=0; i<=len; i++) printf(" 0x%02x",I2C_Buffer_Rx[i]);

    printf("endn");

}

I2C_Buffer_Rx[0]=0;

}

}



(5)数据发送接口:



void Raspberry_Send_Datas(unsigned char  *data,uint16_t length)

{

  uint8 i;  

 

    // printf("send data len[%d]:",length);  

      for(i=0; i

   I2C_Buffer_Tx[i+1]=*(data+i);

   //  printf("%x ",*(data+i));

      }

// printf("endrn");

 

         I2C_Buffer_Tx[0] = length+1;  

}



应该就上面这些了。



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
Keil(MDK-ARM)系列教程(七)_菜单