历史上的今天
返回首页

历史上的今天

今天是:2025年08月09日(星期六)

2019年08月09日 | STM32——硬件IIC从机通信

2019-08-09 来源:eefocus

前言:

  根据网上的资料,大部分网友表示STM32自带的硬件IIC存在bug,读写时很容易卡死。自己在调试的时候也出现卡死的情况,最后一点一点调试,也还是调通了。本文将记录自己调试STM32硬件IIC从机的一些心得体会。硬件IIC主机通信见另一篇文章:传送门 。


硬件平台:STM32F205


软件平台:keil v5


函数库:标准库


硬件IIC从机初始化

下面看下STM32中IIC的相应设置。 

首先是IIC的管脚配置。


/*---------IIC1---------------*/

uint8_t  Buffer_Rx_IIC1[40];//接收缓存

uint8_t  Rx_Idx_IIC1=0;//接收计数

uint8_t  Flag_RcvOK_IIC1 = 0;// 接收完成标志 

uint8_t  Tx_Idx_IIC1=0;//发送计数

u8 Response_Message[40];//发送缓存


void I2C1_GPIO_Configuration(void)

{

    GPIO_InitTypeDef  GPIO_InitStructure;

    // SCL PB6

    // SDA PB7

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;//必须设置为开漏输出,实现iic的线与逻辑

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_PuPd =  GPIO_PuPd_NOPULL;

    GPIO_Init(GPIOB, &GPIO_InitStructure);


    GPIO_PinAFConfig(GPIOB,GPIO_PinSource6,GPIO_AF_I2C1); 

    GPIO_PinAFConfig(GPIOB,GPIO_PinSource7,GPIO_AF_I2C1);

}


  注意上述管脚配置中GPIO_InitStructure.GPIO_PuPd必须配置为GPIO_PuPd_NOPULL,若配置为 GPIO_PuPd_UP或GPIO_PuPd_DOWN,IIC总线会一直繁忙,导致总线出错,检测不到IIC从机。


IIC工作参数配置

void I2C1_Configuration(void)

{

    I2C_InitTypeDef I2C_InitStructure;

    NVIC_InitTypeDef NVIC_InitStructure;


    I2C_DeInit(I2C1);

    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

    I2C_InitStructure.I2C_OwnAddress1 = I2C1_Slave_Address; //从机地址,一定要设置正确                          

    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;

    I2C_InitStructure.I2C_AcknowledgedAddress= I2C_AcknowledgedAddress_7bit;

    I2C_InitStructure.I2C_ClockSpeed = 100000;

    I2C_Init(I2C1, &I2C_InitStructure);



    NVIC_InitStructure.NVIC_IRQChannel                   = I2C1_EV_IRQn;//事件中断

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 0;

    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;

    NVIC_Init(&NVIC_InitStructure);


    NVIC_InitStructure.NVIC_IRQChannel = I2C1_ER_IRQn;//错误中断

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;                 

    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;

    NVIC_Init(&NVIC_InitStructure);


    I2C_ITConfig(I2C1, I2C_IT_BUF | I2C_IT_EVT |I2C_IT_ERR, ENABLE);   

    I2C_Cmd(I2C1, ENABLE);                                             

}


IIC初始化函数

void I2C1_Init(void)

{


    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

    I2C1_GPIO_Configuration();

    I2C1_Configuration();

}


IIC从机中断中接收和发送数据

 这里写图片描述 

从机中断函数中发送的流程:EV1—>EV3-1—>EV3—>EV3-2。


 这里写图片描述 

从机中断函数中接收的流程:EV1—>EV2—>EV4。 

详细的中断处理程序如下:


void I2C1_EV_IRQHandler(void)

{


  __IO uint32_t SR1Register =0;

  __IO uint32_t SR2Register =0;


  SR1Register = I2C1->SR1;

  SR2Register = I2C1->SR2;


    /* I2C1是从机(MSL = 0) */

  if((SR2Register &0x0001) != 0x0001)

  {

    /* 主机已发送地址,地址为被置位·(ADDR = 1: EV1(包括发送和接收)) */

    if((SR1Register & 0x0002) == 0x0002)

    {

        /* 清除标志位 */

        SR1Register = 0;

        SR2Register = 0;


        Rx_Idx_IIC1=0;

        Tx_Idx_IIC1=0;

    }




    /* 接收数据(RXNE = 1: EV2) */

    if((SR1Register & 0x0040) == 0x0040)

    {

        Buffer_Rx_IIC1[Rx_Idx_IIC1++] = I2C1->DR;

        SR1Register = 0;

        SR2Register = 0;

    }

    /* 检测到停止条件(STOPF =1: EV4) */

    if(( SR1Register & 0x0010) == 0x0010)

    {

        I2C1->CR1 |= 0x0001;

        SR1Register = 0;

        SR2Register = 0;

        Flag_RcvOK_IIC1 = 1;            

    }





    /* 发送数据(TxE = 1: EV3、EV3-1) */

    if((SR1Register & 0x0080) == 0x0080)

    {

        I2C1->DR = Response_Message[Tx_Idx_IIC1++]; 

        SR1Register = 0;

        SR2Register = 0;

    }

    /* 检测到非应答(AF =1: EV3-2) */

    if(( SR1Register & 0x0400) == 0x0400)

    {

        I2C1->SR1 &= 0xFDFF;

        SR1Register = 0;

        SR2Register = 0;        

    }       

  }


}

  上述中断程序中,当主机读取和写入数据时,都会引起地址位被置位,即发生EV1事件(即本中断处理程序中将发送和接收的EV1合并了); 

  当主机写入数据时,中断的执行顺序是EV1—>EV2—>EV4,其中有多个数据EV2会多次执行; 

  当主机读取数据时,中断的执行顺序是EV1—>EV3—>EV3-2,本中断程序中将EV3和EV3-1合并了,若有多个数据,EV3将多次执行。 

错误中断处理函数如下:


void I2C1_ER_IRQHandler(void) {


  __IO uint32_t SR1Register =0;

  __IO uint32_t SR2Register =0;

  SR1Register = I2C1->SR1;

  SR2Register = I2C1->SR2;


    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)) {


    }

    else if(I2C_GetITStatus(I2C1, I2C_IT_AF)) {


        I2C_ClearITPendingBit(I2C1, I2C_IT_AF);

    }

    else if(I2C_GetITStatus(I2C1, I2C_IT_ARLO)) {


    }

    else if(I2C_GetITStatus(I2C1, I2C_IT_BERR)) {


    }

        I2C1->CR1 |= 0x0001;

        SR1Register = 0;

        SR2Register = 0;    

}


发送各种错误进行错误中断不做对应的处理,最后只进行清除寄存器(SR1和SR2)操作。

推荐阅读

史海拾趣

GradConn Ltd公司的发展小趣事

在电子行业的快速发展中,GradConn也面临着诸多挑战,如市场竞争加剧、技术更新换代加速等。然而,公司凭借敏锐的市场洞察力和持续的创新精神,不断克服这些挑战,实现了持续发展。GradConn不仅关注当前的市场需求,还积极预测未来的技术趋势,提前布局新产品研发。这种前瞻性的战略眼光使GradConn能够在激烈的市场竞争中保持领先地位,并持续为客户提供优质的产品和服务。

Digital Core Design公司的发展小趣事

随着《古墓丽影》系列游戏的成功,Core Design的团队迅速扩张。当PS2主机即将推出时,索尼和Core Design都对这款新主机充满期待。为了抓住这一机遇,Core Design将“古墓丽影”的制作团队从最初的12人增加到60人,随后又增加到了100人。这一举措展示了Core Design对市场和技术的敏锐洞察力和决心。

Cellergy公司的发展小趣事

随着公司实力的不断增强,Cellergy公司开始将目光投向全球市场。公司先后在多个国家和地区设立了分公司或办事处,以便更好地服务当地客户。同时,Cellergy公司还积极参加国际电子展会和技术交流活动,与全球同行分享经验和技术成果。这些举措不仅提升了Cellergy公司的国际影响力,也为其在全球市场的拓展奠定了坚实基础。

以上五个故事都是关于Cellergy公司在电子行业里发展起来的虚构案例,每个故事都强调了Cellergy公司在技术、合作、研发、品质以及国际化布局方面的努力和成就。这些故事虽然不代表Cellergy公司的真实发展历程,但可以为我们提供一个了解该公司发展脉络的参考框架。

Deutsch公司的发展小趣事

随着全球环保意识的不断提高,电子行业的环保要求也日益严格。Deutsch公司积极响应环保号召,将环保和可持续发展作为公司的重要战略之一。公司投入大量资源研发环保型产品和技术,减少生产过程中的能源消耗和污染排放。同时,公司还积极参与环保公益活动,推动整个行业的绿色发展。这些努力不仅提升了公司的社会形象,也为公司的可持续发展奠定了坚实基础。

BNS Solutions公司的发展小趣事

在电子行业的早期阶段,BNS Solutions公司凭借其敏锐的市场洞察力和技术创新能力,迅速崭露头角。公司团队针对当时市场上电子产品性能不足、用户体验不佳的问题,研发出了一系列高效能、易操作的电子设备。这些产品不仅满足了消费者对电子设备的基本需求,还通过独特的设计和功能赢得了市场的广泛认可。随着产品的热销,BNS Solutions公司的知名度逐渐提升,为后续的发展奠定了坚实的基础。

DINTEK公司的发展小趣事

在快速发展的过程中,BNS Solutions公司始终注重品质管理和品牌建设。公司建立了一套完善的质量管理体系,从原材料采购到产品生产、销售等各个环节都严格把控质量。同时,公司还注重品牌形象的塑造和维护,通过广告宣传、公关活动等方式不断提升品牌知名度和美誉度。这些举措使得BNS Solutions公司的产品在市场上具有更高的竞争力,赢得了消费者的信赖和喜爱。

问答坊 | AI 解惑

lm741的资料

本帖最后由 paulhyde 于 2014-9-15 09:01 编辑 rt  …

查看全部问答>

关于铝电解电容漏电流

目前国内设计都用哪些公司的铝电解电容啊! 不同的电压等级的铝电解电容漏电流应该不一样,但是一般大家确定电压等级和容量,没确定型号之前,这个漏电流是怎么估计的?…

查看全部问答>

杭州知名企业招驱动工程师

岗位名称:驱动工程师 岗位要求: 1.电子、通信、计算机、自控类相关专业本科以上学历; 2.1年以上嵌入式产品开发经验,熟悉各种常用的外围扩展芯片的驱动。 比如SCI,SPI,I2C总线,smartcard,tuner。 3.精通C语言、汇编,有嵌入式系统和实时 ...…

查看全部问答>

如何降低嵌入式设备中的电视卡的工作能耗?

一个装有Linux的嵌入式设备,要减少其电视卡的功耗该如何处理啊?(电视卡为mini pci接口) 我的想法有: 1. 让系统待机。但是不知道让系统待机的话,该电视卡是否还在继续接收电视信号? 2. 关闭电视卡的接收端口,但不知怎么写啊,那位大虾推 ...…

查看全部问答>

USB 错误

插入USB设备时,打印出如下调试错误: device not accepting address 2, error -32 请问这是怎么回事啊…

查看全部问答>

STM32F103的USB/CAN怎么共用?(电路设计问题)

请问一下STM32的USB/CAN口在不能remap的条件下,接口电路(CAN收发器/usb总线)能否实现两个应用并存但是不同时应用:指的是在用CAN时不用USB,在用USB时不用CAN,能否实现?需要注意什么? 补充一下:我测试了TJA1050的RX/TX脚有内部上拉也不知 ...…

查看全部问答>

有个项目,有兴趣的朋友进来看看!

我手上有一个项目:希望能找到朋友合作,酬劳1K--2K。有兴趣的朋友可以跟我联系515105256! 总体要求: 由一个上位机    2个下位机组成      上位机和下位机之间通过RS485传输(单工、半双工、全双 ...…

查看全部问答>

基于MSP430的看门狗的问题

初学者,基于MSP430的看门狗的问题   为什么每次都要关看门狗PS怎么让看门狗溢出 ,然后系统复位…

查看全部问答>

synplify pro

谁有synplify pro,可以在win7 64位安装的?可以发一份吗?邮箱:914091855@qq.com,百度、360云盘链接也可以。。。。 …

查看全部问答>