历史上的今天
返回首页

历史上的今天

今天是:2025年02月12日(星期三)

正在发生

2019年02月12日 | STM32——硬件IIC从机通信

2019-02-12 来源: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)操作。



推荐阅读

史海拾趣

Eureka Microelectronics Inc公司的发展小趣事

为了支持公司的持续发展和业务扩张,Eureka成功完成了多轮融资。这些融资不仅为公司提供了充足的资金支持,也吸引了众多投资者的关注。借助这些资金,Eureka加大了在研发、生产、销售等方面的投入,进一步提升了公司的竞争力和市场地位。同时,公司也积极开展战略合作,与上下游企业建立了紧密的合作关系,共同推动产业链的发展。

Autotrol公司的发展小趣事

随着市场需求的不断变化,Autotrol公司意识到必须不断进行技术创新和产品升级,以满足客户的多样化需求。于是,公司投入大量研发资源,开发出了一系列特色产品,如为更大转矩而制的铜或铁齿轮传动链,以及为安静运行并省钱而特制的塑料齿轮传动链等。这些创新产品不仅提升了Autotrol在市场上的竞争力,也为公司带来了可观的收益。

Abilis Systems公司的发展小趣事

随着公司规模的不断扩大和市场份额的逐步提升,Autotrol公司开始实施全球化战略,积极拓展海外市场。公司在全球范围内建立了销售网络和分支机构,与当地合作伙伴共同开拓市场。同时,Autotrol还加大了对国际市场的研发投入,针对不同地区的市场需求推出定制化的产品和服务。通过全球化战略的实施,Autotrol公司的品牌影响力不断提升,市场地位也日益稳固。

请注意,以上故事仅为基于一般行业知识和公司概况编写的示例,并不代表Autotrol公司的实际历史。如需了解Autotrol公司在电子行业中的具体发展故事,建议查阅公司官方网站、行业报告或相关新闻报道等权威资料。

ELPIDA公司的发展小趣事

在被美光收购后,ELPIDA的技术和人才得到了保留和传承。美光利用ELPIDA的技术优势和市场经验,继续推出了一系列高性能的DRAM产品。同时,ELPIDA也在新的领域进行探索和尝试,如生物生产等。这些努力不仅为美光公司带来了新的增长点,也为ELPIDA品牌注入了新的活力。

以上五个故事概述了ELPIDA公司在电子行业中的重要发展历程。这些故事反映了公司在市场竞争中的起伏和挑战,以及公司在技术和市场上的不断探索和创新。

ARCOL公司的发展小趣事

随着电子技术的飞速发展,ARCOL公司意识到只有不断创新才能在激烈的市场竞争中立于不败之地。因此,公司加大了对研发的投入,积极引进先进的生产设备和技术,不断推出创新性的产品。通过不断优化生产工艺和提升产品质量,ARCOL的产品在市场上逐渐占据了领先地位。

Concurrent Logic公司的发展小趣事

在取得初步成功后,Concurrent Logic开始扩展其产品线。他们不仅开发了多款针对不同应用场景的并行处理芯片,还进军了与并行计算紧密相关的其他硬件领域,如高性能的服务器和存储设备。这些新产品的研发和上市,进一步增强了公司在市场上的竞争力。

问答坊 | AI 解惑

LED3216“大屏电子钟”V1.0发布【图】

几天前LED3216点阵屏控制板完工(见LED3216点阵屏控制板【图】),一有硬件就迫不及待地尝试写了这个电子钟的程序,很惭愧,移花接木随便搞了下,马上就要回家了,没时间弄了。因为只想搞出现象来,导致程序结构混乱,不具有代表性,升级也困难。以 ...…

查看全部问答>

求在深圳嵌入式硬件设计者(个人),急急急!...

求在深圳嵌入式硬件设计...我们要做i.MX51(Arm Cortex A8)产品.请有相关经验者与我联系,合作形式多样可选.谢谢!!!QQ705489316 要做的产品为:10.1寸的带触摸屏的平板电脑(类似于iPad) …

查看全部问答>

用PB5制作CE系统时出错

这是警告 BUILD: [00:0000000008:WARNS ] Directory: E:\\WINCE500\\PRIVATE\\OSINTERNAL\\TEST\\HAL\\ does not exist. BUILD: [00:0000000020:WARNS ] Directory: E:\\WINCE500\\platform\\common\\src\\inc E:\\WINCE500\\public\\common\\o ...…

查看全部问答>

请教Cherishny兄

http://topic.eeworld.net/u/20090807/18/56aa3841-49c4-486a-813e-c639c0e05214.html?41788,从您的回复中看出我们问题很相识,希望得到回复,给您发消息未见回复。…

查看全部问答>

嵌入式软件开发网论坛 单片机开发

欢迎进入嵌入式软件开发网站讨论单片开发的相关问题 嵌入式软件开发网站首页 http://www.embeddedsoft.cn/ 嵌入式软件开发网站论坛 http://www.embeddedsoft.cn/bbs…

查看全部问答>

WinCE下开发GIS怎样快速绘制

用GDI绘图速度不能满足要求,请问有没有更好的方法绘图啊,谢谢啦…

查看全部问答>

想在虚拟机里建个WIN98的驱动开发环境,不知需要准备那些工具?

本来买本教材,不幸的是它里面是用ms v7.0、masm及98DDK来讲解例子的。我从网上找到的98DDK和书里用的DDK还有点不一样。另外我想在虚拟机上做驱动开发调试不知该怎么做?…

查看全部问答>

LM3S中断Bit-banding技术

Bit-banding技术, 即给每个bit位建立一个对应的别名,通过别名来直接访问此bit 1MB的RAM给了32MB的别名空间,一个Byte也就需要8个别名,却给了32个空间,所以将别名空间的低2位不用,常为0.这样就使1MB的RAM空间和32MB的别名空间一一对应了. &n ...…

查看全部问答>

【MSP430共享】激光瓦斯监控系统显示终端的研究

瓦斯监测对于煤矿安全具有重要作用, 煤矿井下终端和监控分站之间的通信对完成瓦斯监测任务起到重要作用 。本系统采用低功耗单片机 MS P 4 3 0   F 1 4 7和 R S 4 8 5总线完成煤矿井下监控分站与远程终端的通信。传感器检测到的瓦斯浓度 ...…

查看全部问答>

大一新手求前辈指导一问题

没什么基础,但还是动手做点东西。 一个传感器,返回高低电平(高4.7v  低0.2v) 想用单片机读取返回信号。 可是发现,直接用单片机管脚接开发板上的VCC,单片机可以检测到高电平啊,但是接传感器的返回信号就是无法识别的样子,用电 ...…

查看全部问答>