历史上的今天
返回首页

历史上的今天

今天是:2025年04月08日(星期二)

正在发生

2019年04月08日 | STM32F103 Slave I2C配置

2019-04-08 来源:eefocus

才接触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;  

}



应该就上面这些了。

推荐阅读

史海拾趣

Discrete Semiconductor Industries公司的发展小趣事

“全球晶联”是Discrete Semiconductor Industries公司中一家注重国际化合作的代表。该公司积极与国际知名企业开展技术合作和市场拓展,通过引进先进的技术和管理经验,不断提升自身的竞争力。同时,全球晶联还积极开拓国际市场,参加各种国际展览和交流活动,加强与国际客户的沟通和合作。这种国际化合作的发展模式使得全球晶联在国际市场上取得了显著的成绩,成为了全球半导体行业的重要参与者之一。

CINCH公司的发展小趣事

CINCH公司作为一家在电子行业颇具影响力的企业,始终致力于技术研发和产品创新。某年,公司研发团队成功开发出一种新型的连接器技术,该技术不仅提高了数据传输速度,还增强了设备的稳定性和耐用性。这一技术突破迅速引起了市场的关注,CINCH公司趁热打铁,推出了一系列基于新技术的产品,迅速占领了市场份额,实现了业务的快速增长。

Crystek公司的发展小趣事

为了进一步扩大市场份额和提升品牌影响力,Crystek公司积极拓展国际市场,与全球多家知名企业建立了合作关系。通过与这些企业的深入合作,Crystek公司的产品得以广泛应用于无线、微波无线电、电信、工业、企业、航空航天和政府部门等各个领域。同时,公司还积极参加国际电子展览和技术交流会议,与全球同行交流学习,不断提升自身的技术水平和市场竞争力。

FTDI公司的发展小趣事

为了进一步扩大市场份额和提升品牌影响力,Crystek公司积极拓展国际市场,与全球多家知名企业建立了合作关系。通过与这些企业的深入合作,Crystek公司的产品得以广泛应用于无线、微波无线电、电信、工业、企业、航空航天和政府部门等各个领域。同时,公司还积极参加国际电子展览和技术交流会议,与全球同行交流学习,不断提升自身的技术水平和市场竞争力。

Advanced Detector Corp公司的发展小趣事

Advanced Detector Corp公司成立于上世纪80年代,由一群热衷于探测器技术研发的科学家和工程师创立。在创立初期,ADC便专注于开发高精度、高灵敏度的探测器技术,以满足当时日益增长的电子测量需求。公司通过持续的技术创新,逐渐在探测器领域取得了突破性的进展,并成功推出了一系列具有竞争力的产品。

Good Sky Electric Co Ltd公司的发展小趣事
电气原理图在摇臂钻床维修中起着至关重要的作用。它详细描绘了设备的电气控制系统和元件之间的连接关系,为维修人员提供了准确的故障排查和检修依据。通过仔细阅读和分析电气原理图,维修人员可以迅速定位故障点并采取相应的修复措施,从而缩短维修时间并降低维修成本。

问答坊 | AI 解惑

步进电机教程

本帖最后由 paulhyde 于 2014-9-15 03:34 编辑 和大家一同分享  …

查看全部问答>

电阻色相环识别方式

电阻色相环识别方式…

查看全部问答>

转-做模拟、高频经验谈

电路理论和实践之精深,远远不是几年时间就能全面掌握的。这几年自己在学习电路尤其是高频和天馈方面也走了不少弯路,君也是同路人,不妨在此谈谈——尤其是将来想做模拟和高频、天馈的同志们,也许看了本人的教训,以后不会走那么多弯路(觉得有道 ...…

查看全部问答>

频率和波特率的转换公式什么?

各位专家,我问一下很简单的问题,不过这也不知道怎么算出来的,呵呵呵呵呵!11.0592KHZ和9600波特率怎么换算的?谢谢大家了!…

查看全部问答>

多核与多CPU的区别?

什么是多核? 它们有什么区别?…

查看全部问答>

EVC4.0下字符串转换问题?高手快进

我准备在EVC4.0+oledb+sql ce2.0开发程序,在wince.net下运行。     CString str0;     str0=\"select EmployeeID,LastName,FirstName \";         str0=str0+\"from Employees\";     &n ...…

查看全部问答>

全新STM8S问世为8位微控制器的性能、可扩展性和价值树立新

意法半导体(ST)全新STM8S问世为8位微控制器的性能、可扩展性和价值树立新标杆利用STM8S的平台理念和先进架构技术,增强功能,缩短设计周期,提高灵活性中国,2009年3月4日 —— 意法半导体(纽约证券交易所代码:STM)今天宣布,针对 ...…

查看全部问答>

lm3s811的板子

lm3s811的板子,在flashdown是一直提示flash download failed cortex-m3! 使用的是KEIL编译环境!…

查看全部问答>

过零触发双硅输出光耦-MOC3061的应用

晶闸管的触发方式有移相触发和过零触发两种。常用的触发电路与主回路之间由于有电的联系,易受电网电压的波动和电源波形畸变的影响,为解决同步问题,往往又使电路较为复杂。MOTOROLA公司生产的MOC3021-3081器件可以很好地解决这些问题。该器件用 ...…

查看全部问答>

这些LCD没资料,放着没用,扔了可惜

下面这个双LCD,拆下来后也没有找到资料: 下面这个是好记星上拆的: 下面这两个好象有资料, 谁要送谁…

查看全部问答>