新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 基于STM32 I2C的TMP101溫度傳感器的C源碼

        基于STM32 I2C的TMP101溫度傳感器的C源碼

        作者: 時間:2016-10-07 來源:網絡 收藏

          搞這個歷程差不多花了我一個周末的時間,一片小小的確實讓我破費腦筋。最后甚至使用了示波器直接觀察SDA SCL 的波形。不過示波器的使用確實糾正我一個嚴重且低級的錯誤。這期間也在網上搜過 的I2C 應用 大多都是在說 的I2C固件庫寫的爛、的硬件有問題、I2C接口沒法用等等,最后解決方式都是用軟件像51那樣用IO口軟件模擬IIC時序。但我看了STM32最新的勘誤表,根本沒有所謂STM32的IIC硬件設計缺陷。我可不想把STM32用的像8051一樣。我要用高效的硬件I2C而且要用ST官方庫來實現~!

        本文引用地址:http://www.104case.com/article/201610/310913.htm

          心得:

          函數 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));這樣話如論如何你都會死在這里的。反正我是出了不少這種低級錯誤的。

          

         

          我用的是3.0的庫 這句是I2C_Send7bitAddress(I2C1, 0xFF, I2C_Direction_Transmitter);

          紅線是起始位,讀寫位不受0XFF控制的。

          

         

          SCL SDA 要有上拉電阻,VCC與GND 間最好接個104電容濾波。

          

         

          串口出溫度。

          再說說 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不能被本函數清除

          好了再看看 的手冊 挺簡單的。 其實對I2C的時序要求并不嚴格,應答、非應答、中止都可省略。

          網上找的

         

          SHUT DOWN 就是省電啊 less than 1μA 夠省吧。F1 與F 0 是報警溫度次數。

          

         

          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("rn");

          }



        關鍵詞: STM32 TMP101

        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 汉川市| 莎车县| 来凤县| 五莲县| 琼中| 杂多县| 东港市| 鄯善县| 永安市| 奎屯市| 邳州市| 连云港市| 邻水| 洞头县| 芜湖市| 保康县| 泰宁县| 肇源县| 嘉定区| 龙岩市| 昔阳县| 峨山| 日土县| 新龙县| 云霄县| 闽清县| 育儿| 鸡泽县| 惠来县| 深州市| 兴仁县| 柘荣县| 泾川县| 瓦房店市| 札达县| 玉田县| 德兴市| 广河县| 新巴尔虎左旗| 济源市| 阳山县|