STM32-I2C驱动-TMP101-温度传感器

       搞这个历程差不多花了我一个周末的时间,一片小小的TMP101确实让我破费脑筋。最后甚至使用了示波器直接观察SDA SCL 的波形。不过示波器的使用确实纠正我一个严重且低级的错误。这期间也在网上搜过STM32 的I2C 应用  大多都是在说 STM32 的I2C固件库写的烂、STM32的硬件有问题、I2C接口没法用等等,最后解决方式都是用软件像51那样用IO口软件模拟IIC时序。但我看了STM32最新的勘误表,根本没有所谓STM32的IIC硬件设计缺陷。我可不想把STM32用的像8051一样。我要用高效的硬件I2C而且要用ST官方库来实现~!

心得:

函数 I2C_CheckEvent  () 这个典型的用法是

while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

如果经常死在这里面那你就要注意如下的问题:

  • GPIO口的模式一定要是GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // 开漏复用功能
  • 保证的你的接线正确且速度合适。比如:SCL SDA要有上拉电阻 4K7是典型值,100K的速度最好
  • I2C_Send7bitAddress()发送要是8位数 例如你的7位地址是1001001 你不能写成0X49正确的是0x92或者是0x93最后的读写位是0(写)还是1(读)不受你添地址的影响,仅受第3个参数I2C_Direction_Transmitter或I2C_Direction_Receiver的影响。这点我是用了示波器才看出来的 呵呵~不知道是谁把示波器CH2通道打开了反相........我差点就怀疑STM32 硬件有问题.....又出现了一些小曲折 唉~
  • 最后细心写程序 比如 I2C_Send7bitAddress(I2C1, 0x92, I2C_Direction_Receiver);
     while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));这样话如论如何你都会死在这里的。反正我是出了不少这种低级错误的。

基于STM32 I2C的TMP101温度传感器的C源码 - java - stm32学习日志

我用的是3.0的库 这句是I2C_Send7bitAddress(I2C1,  0xFF, I2C_Direction_Transmitter);

红线是起始位,读写位不受0XFF控制的。

基于STM32 I2C的TMP101温度传感器的C源码 - java - stm32学习日志

SCL SDA 要有上拉电阻,VCC与GND 间最好接个104电容滤波。

基于STM32 I2C的TMP101温度传感器的C源码 - java - stm32学习日志基于STM32 I2C的TMP101温度传感器的C源码 - java - stm32学习日志

串口出温度。

再说说 STM32的固件库.....唉~确实比较另类不过ST的工程师好人做到底了一个库让人轻松一截子 请先看

最头大的  I2C_CheckEvent

  flag1 = I2Cx->SR1;
  flag2 = I2Cx->SR2;
  flag2 = flag2 << 16;
  /* Get the last event value from I2C status register */
 lastevent = (flag1 | flag2) & FLAG_Mask;
 //lastevent = (flag1 | flag2) & I2C_EVENT;
  /* Check whether the last event is equal to I2C_EVENT */
  if (lastevent == I2C_EVENT )
  {
    /* SUCCESS: last event is equal to I2C_EVENT */
    status = SUCCESS;
  }
  else
  {
    /* ERROR: last event is different from I2C_EVENT */
    status = ERROR;
  }
  return status;

看得出STM32 就是靠SR1 与SR2 来判断各种IIC的状态,不同的位组合产生多种情况 汗~~~这个确实有创意。

好在ST的工程师总结好了各种情况 我也推荐大家直接看库函数是怎么写的不要只看那个数据手册...

#define  I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED       ((uint32_t)0x00060082) /* TRA, BUSY, TXE and ADDR flags */
#define  I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED          ((uint32_t)0x00020002) /* BUSY and ADDR flags */
#define  I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED ((uint32_t)0x00860080)  /* DUALF, TRA, BUSY and TXE flags */
#define  I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED    ((uint32_t)0x00820000)  /* DUALF and BUSY flags */
#define  I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED        ((uint32_t)0x00120000)  /* GENCALL and BUSY flags */

#define  I2C_EVENT_SLAVE_BYTE_RECEIVED                     ((uint32_t)0x00020040)  /* BUSY and RXNE flags */

还有好多.........EVx 每个都有中断的。这太多了我也记不下.....总结一下吧 之说简单常用的的主模式

 

起始 标志     I2C_EVENT_MASTER_MODE_SELECT

地址写标志  I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED

数据写标志 I2C_EVENT_MASTER_BYTE_TRANSMITTED

地址读标志 I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED

数据读标志 I2C_EVENT_MASTER_BYTE_RECEIVED

 

SR1中有些读了寄存器就清了或硬件清零 也可以用 I2C_ClearFlag

注意:标志位DUALF, SMBHOST, SMBDEFAULT, GENCALL, TRA, BUSY,MSL, TXE和RXNE不能被本函数清除

好了再看看TMP101 的手册 挺简单的。 其实TMP101对I2C的时序要求并不严格,应答、非应答、中止都可省略。

网上找的基于STM32 I2C的TMP101温度传感器的C源码 - java - stm32学习日志

SHUT DOWN 就是省电啊  less than 1μA 够省吧。F1 与F 0 是报警温度次数。

基于STM32 I2C的TMP101温度传感器的C源码 - java - stm32学习日志

TM 报警极性.POL 也是报警的 咱先不管.....

这个STM32 历程没有借助DMA 与中断。

 

#include "STM32Lib\\stm32f10x.h"
#include "hal.h"
u8 I2c_Buf[3]="AB0";//温度存放
void I2C_Configuration(void)
{
 I2C_InitTypeDef  I2C_InitStructure;
 GPIO_InitTypeDef  GPIO_InitStructure;

 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE); //开I2C的时钟

 /* PB6,7 SCL and SDA */
 GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_6 | GPIO_Pin_7;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // 开漏复用功能
 GPIO_Init(GPIOB, &GPIO_InitStructure);
 
    I2C_DeInit(I2C1);
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; //设置I2C为I2C模式
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //I2C快速模式Tlow / Thigh = 2 就是拉扯SCL 高低电平比
    I2C_InitStructure.I2C_OwnAddress1 = 0x30; //STM32自身地址
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;  //使能应答(ACK)
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; //应答7位地址
    I2C_InitStructure.I2C_ClockSpeed = 100000; //100K速度
    
 I2C_Cmd(I2C1, ENABLE);
 I2C_Init(I2C1, &I2C_InitStructure);
 /*允许1字节1应答模式*/
 I2C_AcknowledgeConfig(I2C1, ENABLE);

}

/***************************************************
**函数名:I2C_ReadTmp
**功能:读取tmp101的2个字节温度
***************************************************/
void I2C_ReadTmp(void)

 while(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY)); /*检测总线是否忙 就是看 SCL 或SDA是否为 低 */
  
 /*允许1字节1应答模式*/
 I2C_AcknowledgeConfig(I2C1, ENABLE);


 /* 发送起始位 */
    I2C_GenerateSTART(I2C1, ENABLE);
    while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); /*EV5,主模式*/


    /*发送器件地址(写)*/
    I2C_Send7bitAddress(I2C1,  0x92, I2C_Direction_Transmitter);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

 /*发送Pointer Register*/
    I2C_SendData(I2C1, 0X00);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); /*数据已发送*/
  
 /*起始位*/
 I2C_GenerateSTART(I2C1, ENABLE);
 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
 
 /*发送器件地址(读)*/
 I2C_Send7bitAddress(I2C1, 0x92, I2C_Direction_Receiver);
 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
 /* 读Temperature Register*/
 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); /* EV7 */
 I2c_Buf[0]= I2C_ReceiveData(I2C1);
 
    I2C_AcknowledgeConfig(I2C1, DISABLE); //最后一位后要关闭应答的
    I2C_GenerateSTOP(I2C1, ENABLE);   //发送停止位 


  /*● 为了在收到最后一个字节后产生一个NACK脉冲,在读倒数第二个数据字节之后(在倒数第二个RxNE事件之后)必须清除ACK位。
● 为了产生一个停止/重起始条件,软件必须在读倒数第二个数据字节之后(在倒数第二个RxNE事件之后)设置STOP/START位。
● 只接收一个字节时,刚好在EV6之后(EV6_1时,清除ADDR之后)要关闭应答和停止条件的产生位。*/


 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); /* EV7 */
 I2c_Buf[1]= I2C_ReceiveData(I2C1);
     
 /* Decrement the read bytes counter */

   
 /*再次允许应答模式*/
 I2C_AcknowledgeConfig(I2C1, ENABLE);
}

 

/*************************************************
**函数名:void I2C_InitTmp(void)
**功能:初始化TMP101
*************************************************/
void I2C_InitTmp(void)
{

   I2C_GenerateSTART(I2C1, ENABLE);
   while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); 


   /* 发送器件地址(写)*/
   I2C_Send7bitAddress(I2C1, 0X92, I2C_Direction_Transmitter);
   while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
  
   /*发送Pointer Register*/
   I2C_SendData(I2C1, 0X01);
 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));


 /* 写Configuration Register  12位温度 连续转换*/
   I2C_SendData(I2C1, 0XFE); 
   while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
 

   I2C_GenerateSTOP(I2C1, ENABLE);
  
  
}

 


//测试用 使用之前要先调用I2C_InitTmp 初始化TMP101
void I2C_Test(void)
{
 char a[8]=" ";
 u32 temp;
 float tmp;
 I2C_ReadTmp(); //读温度
 temp=I2c_Buf[0]; //转换温度
 temp=temp<<4;
 temp=temp|I2c_Buf[1]>>4;
 tmp=(temp/16.0); /*仅处理了正的温度 负温度取反后加1 再按正温度处理*/
 a[0]=(char)tmp/10+48;
 a[1]=(char)tmp%10+48;
 a[2]='.';
 a[3]=(char)((int)(tmp*10)%10+48);
 a[4]=(char)((int)(tmp*100)%10+48);
 a[5]=(char)((int)(tmp*1000)%10+48);
 a[6]='C';
 USART1_Puts(a); //USART 出温度
 USART1_Puts("\r\n");

}

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: ​ STM32-STLink是一款常见的STM32单片机的USB调试工具,它可以方便地进行芯片的程序下载、烧录、调试和监测工作。在使用STM32-STLink进行调试工作前,需要先安装STM32-STLink驱动STM32-STLink驱动可以在ST官网或软件开发社区中获取。在安装驱动前需要确保电脑已经连接上STM32-STLink,并且已经准备好了相应的开发环境。建议先卸载旧版本的驱动再进行安装。 具体操作步骤如下: 1. 连接STM32-STLink到电脑,确保正常供电和通信。 2. 安装驱动,可以从ST官网或者软件开发社区中下载最新驱动程序。 3. 解压下载的驱动程序,双击运行安装程序。 4. 驱动安装过程中需要注意选择与自己操作系统版本相对应的驱动程序,勾选“核心组件”和“驱动程序”选项,进行安装。 5. 安装完成后,重启电脑,确认驱动程序已经成功安装。 6. 打开开发环境,并连接STM32-STLink,进行调试工作。在调试过程中,可以通过STLink Utility等工具进行芯片的操作。 总之,STM32-STLink驱动STM32单片机开发必备的驱动程序之一。通过安装该驱动,可以方便地进行芯片的调试工作和程序烧录操作。 ### 回答2: stm32-stlink驱动是一种用于连接STM32单片机与电脑的驱动STM32是一种低功耗、高性能的32位微控制器,而stlink是一种芯片级调试工具,用于将计算机与STM32单片机连接起来,进行程序的调试和下载。由于stm32-stlink驱动具备高性能、可靠性和灵活性等优势,因此在计算机与STM32单片机之间的数据传输过程中发挥了重要作用。 stm32-stlink驱动可以实现多种不同的功能。例如,在调试过程中,它可以帮助开发者调试程序,并实时监测STM32单片机的运行情况。此外,该驱动还可以实现对单片机的程序下载、烧录、刷写等操作,方便开发者进行快速迭代和测试。 除了实现上述功能之外,stm32-stlink驱动还具备多种其他特点。例如,该驱动可以长时间稳定运行,且不会对系统稳定性产生不利影响。此外,该驱动还具备自动适配的能力,可以适应不同版本的STM32单片机。 在使用stm32-stlink驱动之前,开发者需要根据自己的需要进行安装和配置。具体来说,需要下载适合自己系统版本的stm32-stlink驱动,并在电脑上安装。此外,在进行开发过程中,开发者还需要根据需要对该驱动进行相应的设置和调整,以保障程序的正常运行。 总的来说,stm32-stlink驱动是一种实现STM32单片机与电脑之间数据传输的重要工具,具备多种优势和特点。在进行相关开发工作时,合理配置和使用该驱动可以极大地提高开发效率和程序稳定性。 ### 回答3: STM32-STLINK驱动是用于连接计算机和STM32微控制器开发板之间的软件程序。STM32-STLINK驱动可用于下载代码,调试和仿真微控制器。STM32-STLINK驱动由STMicroelectronics提供,并且是免费提供的。该驱动程序可以在Windows和Linux操作系统上使用,并且支持多种开发工具,例如Keil,IAR和Atollic。 在使用STM32-STLINK驱动之前,需要先将开发板与计算机连接。连接过程可以通过USB连接或JTAG/SWD接口完成。当前,STMicroelectronics生产的大多数STM32微控制器都具有内置的ST-LINK / V2-1调试器,因此无需单独购买ST-LINK外设。只需使用USB线缆将STM32板连接到计算机上,即可使用STM32-STLINK驱动。 一旦STM32开发板和计算机连接成功并且安装了STM32-STLINK驱动,就可以开始进行下载、调试和仿真微控制器的工作了。STM32-STLINK驱动提供了基本的调试工具,例如设置断点、查看变量和跟踪程序执行等功能,以帮助开发人员进行程序调试。此外,该驱动程序还支持许多高级功能,例如实时追踪、功耗分析和定时器分析等,以帮助开发人员更深入地了解和优化代码。 综上所述,STM32-STLINK驱动是连接STM32微控制器和计算机之间的关键软件程序,用于下载、调试和仿真微控制器。它具有易于使用和灵活的优点,是STM32开发的重要工具之一。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值