stm32专题十六:IIC(三)stm32 IIC 固件库函数分析

最新更新时间:2021-10-22来源: eefocus关键字:stm32  IIC  固件库函数 手机看文章 扫描二维码
随时随地手机看文章

因为I2C通讯非常重要,因此要详细的分析每一个库函数


IIC初始化结构体


/** 

  * @brief  I2C Init structure definition  

  */

 

typedef struct

{

  // 指定时钟频率,这个值不能超过400kHz

  uint32_t I2C_ClockSpeed;          /*!< Specifies the clock frequency.

                                         This parameter must be set to a value lower than 400kHz */

 

  // IIC模式:可以有3种选择:I2C_Mode_I2C  I2C_Mode_SMBusDevice  I2C_Mode_SMBusHost

  uint16_t I2C_Mode;                /*!< Specifies the I2C mode.

                                         This parameter can be a value of @ref I2C_mode */

 

  

  // 占空比 I2C_DutyCycle_2  I2C_DutyCycle_16_9

  uint16_t I2C_DutyCycle;           /*!< Specifies the I2C fast mode duty cycle.

                                         This parameter can be a value of @ref I2C_duty_cycle_in_fast_mode */

 

  // 自身地址,这个可以任意给一个与其他IIC从机设备不同的地址,如0X0A

  uint16_t I2C_OwnAddress1;         /*!< Specifies the first device own address.

                                         This parameter can be a 7-bit or 10-bit address. */

 

  // 应答Ack使能 I2C_Ack_Enable  I2C_Ack_Disable

  uint16_t I2C_Ack;                 /*!< Enables or disables the acknowledgement.

                                         This parameter can be a value of @ref I2C_acknowledgement */

 

  // IIC应答地址,一般7位  I2C_AcknowledgedAddress_7bit  I2C_AcknowledgedAddress_10bit

  uint16_t I2C_AcknowledgedAddress; /*!< Specifies if 7-bit or 10-bit address is acknowledged.

                                         This parameter can be a value of @ref I2C_acknowledged_address */

}I2C_InitTypeDef;

IIC初始化函数,这里有一些值得注意的地方:


1 IIC模块时钟频率

2 分频系数

/**

  * @brief  Initializes the I2Cx peripheral according to the specified 

  *   parameters in the I2C_InitStruct.

  * @param  I2Cx: where x can be 1 or 2 to select the I2C peripheral.

  * @param  I2C_InitStruct: pointer to a I2C_InitTypeDef structure that

  *   contains the configuration information for the specified I2C peripheral.

  * @retval None

  */

void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct)

{

  uint16_t tmpreg = 0, freqrange = 0;

  uint16_t result = 0x04;

  uint32_t pclk1 = 8000000;  // 只是初始化时给的值,没有意义,给0也可以

  RCC_ClocksTypeDef  rcc_clocks;

 

/*---------------------------- I2Cx CR2 Configuration ------------------------*/

  // 配置IIC模块输入时钟频率,标准模式至少为2MHz,快速模式至少为4MHz,最大为36MHz

  /* Get the I2Cx CR2 value */

  // 先暂存CR2,只处理FREQ[5:0]位,其他位不变

  tmpreg = I2Cx->CR2;

  /* Clear frequency FREQ[5:0] bits */

  // 清除FREQ[5:0]位

  tmpreg &= CR2_FREQ_Reset;

  /* Get pclk1 frequency value */

  RCC_GetClocksFreq(&rcc_clocks);

  // 获得APB1总线的时钟频率(36MHz)

  pclk1 = rcc_clocks.PCLK1_Frequency;

  /* Set frequency bits depending on pclk1 value */

  // 计算FREQ[5:0]位写入值(36,已经是最大值)

  freqrange = (uint16_t)(pclk1 / 1000000);

  tmpreg |= freqrange;

  /* Write to I2Cx CR2 */

  // 写入到CR2寄存器

  I2Cx->CR2 = tmpreg;

 

/*---------------------------- I2Cx CCR Configuration ------------------------*/

  // 配置CCR寄存器(设置标准/快速模式、占空比、时钟控制分频系数等)

  /* Disable the selected I2C peripheral to configure TRISE */

  I2Cx->CR1 &= CR1_PE_Reset;

  /* Reset tmpreg value */

  /* Clear F/S, DUTY and CCR[11:0] bits */

  tmpreg = 0;

 

  /* Configure speed in standard mode */

  // I2C_ClockSpeed <= 100k时,配置为标准模式

  if (I2C_InitStruct->I2C_ClockSpeed <= 100000)

  {

    /* Standard mode speed calculate */

    // APB1总线时钟/2/I2C_ClockSpeed = 分频系数

    result = (uint16_t)(pclk1 / (I2C_InitStruct->I2C_ClockSpeed << 1));

    // 允许设定的最小值为0x04,在快速DUTY模式下允许的最小值为0x01;

    /* Test if CCR value is under 0x4*/

    if (result < 0x04)

    {

      /* Set minimum allowed value */

      result = 0x04;  

    }

    /* Set speed value for standard mode */

    tmpreg |= result;  

    /* Set Maximum Rise Time for standard mode */

    I2Cx->TRISE = freqrange + 1; 

  }

  /* Configure speed in fast mode */

  // 快速模式下,分频系数的计算

  else /*(I2C_InitStruct->I2C_ClockSpeed <= 400000)*/

  {

    if (I2C_InitStruct->I2C_DutyCycle == I2C_DutyCycle_2)

    {

      /* Fast mode speed calculate: Tlow/Thigh = 2 */

      result = (uint16_t)(pclk1 / (I2C_InitStruct->I2C_ClockSpeed * 3));

    }

    else /*I2C_InitStruct->I2C_DutyCycle == I2C_DutyCycle_16_9*/

    {

      /* Fast mode speed calculate: Tlow/Thigh = 16/9 */

      result = (uint16_t)(pclk1 / (I2C_InitStruct->I2C_ClockSpeed * 25));

      /* Set DUTY bit */

      result |= I2C_DutyCycle_16_9;

    }

 

    /* Test if CCR value is under 0x1*/

    if ((result & CCR_CCR_Set) == 0)

    {

      /* Set minimum allowed value */

      result |= (uint16_t)0x0001;  

    }

    /* Set speed value and set F/S bit for fast mode */

    tmpreg |= (uint16_t)(result | CCR_FS_Set);

    /* Set Maximum Rise Time for fast mode */

    I2Cx->TRISE = (uint16_t)(((freqrange * (uint16_t)300) / (uint16_t)1000) + (uint16_t)1);  

  }

 

  /* Write to I2Cx CCR */

  // 写入到CCR寄存器,并使能IIC

  I2Cx->CCR = tmpreg;

  /* Enable the selected I2C peripheral */

  I2Cx->CR1 |= CR1_PE_Set;

 

/*---------------------------- I2Cx CR1 Configuration ------------------------*/

  // 配置IIC模式、应答

  /* Get the I2Cx CR1 value */

  tmpreg = I2Cx->CR1;

  /* Clear ACK, SMBTYPE and  SMBUS bits */

  tmpreg &= CR1_CLEAR_Mask;

  /* Configure I2Cx: mode and acknowledgement */

  /* Set SMBTYPE and SMBUS bits according to I2C_Mode value */

  /* Set ACK bit according to I2C_Ack value */

  tmpreg |= (uint16_t)((uint32_t)I2C_InitStruct->I2C_Mode | I2C_InitStruct->I2C_Ack);

  /* Write to I2Cx CR1 */

  I2Cx->CR1 = tmpreg;

 

/*---------------------------- I2Cx OAR1 Configuration -----------------------*/

  // 配置IIC应答地址位数

  /* Set I2Cx Own Address1 and acknowledged address */

  I2Cx->OAR1 = (I2C_InitStruct->I2C_AcknowledgedAddress | I2C_InitStruct->I2C_OwnAddress1);

}

在上一节中提到,IIC发送/接收过程会产生相应的事件,我们通过检测事件来判断当前运行的状态,以下是检测函数


ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT);

/**

  * @brief  Checks whether the last I2Cx Event is equal to the one passed

  *   as parameter.

  * @param  I2Cx: where x can be 1 or 2 to select the I2C peripheral.

  * @param  I2C_EVENT: specifies the event to be checked. 

  *   This parameter can be one of the following values:

  *     @arg I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED           : EV1

  *     @arg I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED              : EV1

  *     @arg I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED     : EV1

  *     @arg I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED        : EV1

  *     @arg I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED            : EV1

  *     @arg I2C_EVENT_SLAVE_BYTE_RECEIVED                         : EV2

  *     @arg (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_DUALF)      : EV2

  *     @arg (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_GENCALL)    : EV2

  *     @arg I2C_EVENT_SLAVE_BYTE_TRANSMITTED                      : EV3

  *     @arg (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_DUALF)   : EV3

  *     @arg (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_GENCALL) : EV3

  *     @arg I2C_EVENT_SLAVE_ACK_FAILURE                           : EV3_2

  *     @arg I2C_EVENT_SLAVE_STOP_DETECTED                         : EV4

  *     @arg I2C_EVENT_MASTER_MODE_SELECT                          : EV5

  *     @arg I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED            : EV6     

  *     @arg I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED               : EV6

  *     @arg I2C_EVENT_MASTER_BYTE_RECEIVED                        : EV7

[1] [2]
关键字:stm32  IIC  固件库函数 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic552246.html

上一篇:stm32专题十六:IIC(二)stm32 IIC通讯过程 标志位
下一篇:stm32专题十七:AT24C02

推荐阅读

NVIC中断优先级管理
一,STM32中断介绍CM3内核支持256个中断,16个内核中断和240个外部中断,具有256级可编程中断设置STM32只使用了CM3内核的一部分,84个中断:16个内核中断+68个可屏蔽中断(外部中断),具有16级可编程的中断优先级STM32F103系列只有60个可屏蔽中断(F107系列有68个)二,中断管理STM32有如此多的中断,那么是如何进行管理的中断优先级分组: SCB->AIRCR [10:8]3位寄存器 :配置分组,确定中断具有几位抢占优先级和几位响应优先级每一个中断都具有一个[7:4]4位IP寄存器,通过这4个位来设置抢占和响应优先级, 16级可编程中断优先级(2的4次方=16)配置分组寄存器SCB->
发表于 2021-11-30
NVIC中断优先级管理
关于STM32 NVIC配置的解释
大部分学习用的开发板在配置各个外设的中断优先级时,习惯在每个外设的初始化文件里都进行NVIC group配置,例如在ADC和Usart都有NVIC的配置如下:ADC中:void ADC_NVIC_Configuration(void){NVIC_InitTypeDef NVIC_InitStructure;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);NVIC_InitStructure.NVIC_IRQChannel =ADC1_2_IRQn;     //开启ADC_Channel8中断NVIC_InitStructure.NVIC_IRQChannelPree
发表于 2021-11-30
STM32外部中断(EXTI)分析和应用
本篇博文基于STM32F103ZET6芯片,与大多数STM32F10x芯片兼容;代码基于ST官网提供的3.5.0标准库如有不足之处,还望前辈多多指教;一些需要了解的基础知识STM32每个GPIO口都可以作为外部中断输入口使用每个中断都设有状态位每个中断/事件都有独立的触发和屏蔽设置。STM32103有19个外部中断(但是供GPIO口使用的中断只有16个)分别是:0~15:对应外部中断IO的输入中断16 : 连接到PVD输出17 :连接到RTC闹钟时间18 :连接到USB唤醒事件这里会容易出现一个问题说:STM32F103ZET6的GPIO管脚一共有6*16即96个GPIO管脚,如何对应只有0~15共16个的外部中断机制;请看
发表于 2021-11-30
<font color='red'>STM32</font>外部中断(EXTI)分析和应用
STM32使用systick定时器定义硬件精准延时函数
定时器不同,SysTick这个定时器以及相关寄存器在CM3内核里。《STM32使用手册》里对并没有涉及SysTick的内容,只能去《Cortex-M3权威指南》看(PDF的133页);寄存的可寻址,且寄存器被定义在程序包中的core_m3.c 中,涉及相关的编程时一定要注意;可以工作在芯片的睡眠状态下;SysTick被捆绑在NVIC(中断向量控制器)中,可以产生异常(异常号:15),这是在操作系统下为系统提供时间基准的必要条件;每个CM3内核都含有一个SysTick,这样方便程序移植;SysTick时钟源的选择可以来自于外部,也可以来自于内部;使用来自外部的时钟源的时候要根据具体芯片生产厂商的手册;(本博文采用外部时钟源)SysTick
发表于 2021-11-30
<font color='red'>STM32</font>使用systick定时器定义硬件精准延时函数
STM32 标准固件库的下载,文件介绍和工程的建立(综合)
下启动文件文件名一样,为什么会这样的?原因是stm32的开发环境不止一种,这个文件夹名分别代表了各个环境的启动文件,比如如果用KEIL MDK环境开发就选择arm文件夹下的启动文件,如果用IAR环境开发就选择iar环境下的启动文件;startup_stm32f10x_XX.s:芯片启动文件;主要功能有两个:① 程序开始运行后,使程序进入系统初始化函数SystemInit(),在此处,完成对芯片的时钟系统,管脚等进行初始化;② 初始化结束后使程序进入主函数main()进行;这里发现一个问题:arm文件夹下不止这一种,那么应该选择哪一个那?看下表(其他几个暂时用不着,先不介绍,后续用到的时候再补充)stm32f10x.h:STM32F10x
发表于 2021-11-30
<font color='red'>STM32</font> 标准固件库的下载,文件介绍和工程的建立(综合)
STM32处理器输入捕获分析
/比较模式寄存器TIMx_CCMR1(当然还有CCMR2,两个寄存器配置CH1~4的输入输出)捕获作为输入,因此我们只用图片中寄存器的后下部分;CC1S[1:0] : (1)决定定时为输出(比较)或输入(捕获)模式;(2)决定IC1信号源的选择(后边详细介绍);IC1PSC[1:0]:选择对IC1的分频模式(但是这个分频和定时器TIMx_PSC寄存器的分频并不太一样,但功能是一样的)IC1F[3:0]:输入捕获1滤波器(详细功能可以参考STM32手册,这里这个功能不作为细说,本博文也用不到)(2)捕获/比较使能寄存器TIMx_CCER1使能寄存器中除了对输入使能的控制之外,还有对输入输出极性的控制;(此时为输入模式下)CCxP
发表于 2021-11-29
<font color='red'>STM32</font>处理器输入捕获分析
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2021 EEWORLD.com.cn, Inc. All rights reserved