天天看點

STM32F103 Slave I2C配置

今年才接觸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) 而實還有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%x\r\n", 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%x\r\n", 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("end\r\n");*/
			    
                  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("end\n");
			}
			 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<length; i++)
	{ 
	   I2C_Buffer_Tx[i+1]=*(data+i);
	   //  printf("%x ",*(data+i));
      }
	 // printf("end\r\n");

         I2C_Buffer_Tx[0] = length+1;  
}
           
應該就上面這些了。

繼續閱讀