色另类_婷婷激情四月_亚洲精品无码不卡在线播放he_欧美第七页_精品国产综合区久久久久99_青娱乐极品盛宴在线

產品分類

當前位置: 首頁 > 工業電氣產品 > 端子與連接器 > 線路板連接器 > FFC連接器

類型分類:
科普知識
數據分類:
FFC連接器

在C2000上使用GPIO模擬I2C通信

發布日期:2022-04-28 點擊率:103

Other Parts Discussed in Post: BQ25703A

作者:TI 華北區工程師 Brian Wang 和 Young Hu

相關代碼請點擊以下附件下載:

I2C_Simulation.c         I2C_Simulation.h

 

引言

         I2C作為一種簡單的數字通訊方式,僅需要兩根數據線就可以完成近距離主機(Master)與從機(Slave)之間的通訊,節省了MCU引腳以及額外的邏輯芯片,簡化了PCB布板難度,因此得到了廣泛的應用。近年來,TI也推出了越來越多支持I2C通訊功能的芯片,大大簡化了芯片與MCU之間的通訊,方便了系統的設計。

     但在實際應用中,針對性能要求較低的應用場合,通常選擇外設較為簡單的低端主控MCU,可能并不具備I2C接口。對于此類應用,可以通過MCU的IO口進行I2C模擬,與被控器件建立通訊,達到發送控制指令、讀取內部寄存器的目的。即使在I2C接口缺失的情況下也能夠充分發揮器件的全部功能。

     本文基于C2000提供了一種利用GPIO模擬I2C控制被控芯片的解決方案,并附有完整例程。對于絕大多數采用標準I2C通信協議以及部分采用SMBus的芯片均具有參考意義。基于其它MCU的方案也可參考該例程進行移植。

一、I2C 通訊協議與GPIO模擬

     I2C總線由兩條雙向信號線構成,分別為數據線(SDA)以及時鐘線(SCL),分別用電阻進行上拉,以實現高低電平之間的切換,進行設備之間的數據交交換。I2C允許的工作電壓范圍較為寬泛,典型電壓基準為+3.3V或+5V。常見的I2C總線速率分為以下幾種模式:標準模式(100Kbit/s)、快速模式(400Kbit/s)以及高速模式(3.4Mbit/s)等。如圖為典型的I2C連接示意圖:

圖1 I2C連接示意圖

         如圖2為典型的I2C通訊幀格式示意圖。一幀完整的數據發送主要包括起始位、地址位、讀/寫位、ACK/NCK位、數據位等。下面對各部分進行簡要的講解,并介紹如何通過C2000進行實現。

圖2 I2C連接示意圖

1.1 起始及結束指令

         當某個設備在I2C總線上被配置為主機(Master),該設備可以發送起始及結束信號用來發起或結束一次I2C通信,母線電平示意圖如圖2所示。

  • 起始信號:在SCL為高電平期間,SDA由高電平轉換為低電平。

  • 結束信號:在SCL為高電平期間,SDA由低電平轉換為高電平。


圖3 I2C通訊起始及結束信號

     在C2000中,可以通過以下代碼實現起始信號的發送。其中SCL及SDA分別代表用C2000 GPIO模擬的SDA及SCL總線,具體定義請參考例程部分。


  1. void I2C_Start(void)  

  2. {  

  3.     Delay(I2CDelay);  

  4.     SCL_High();   // Set the SCL  

  5.     SDA_High();   // Set the SDA  

  6.     Delay(I2CDelay);  

  7.     SDA_Low();    // Clear the SDA while SCL is high indicates the start signal 

  8.     Delay(I2CDelay);  

  9.     SCL_Low();    // Clear the SCL to get ready to transmit

  10. }  


     可以參考以下代碼實現結束信號的發送:

  1. void I2C_Finish(void)  

  2. {  

  3.     SDA_Low();    // Clear the SDA 

  4.     SCL_Low();    // Clear the SCL  

  5.     Delay(I2CDelay);  

  6.     SCL_High();   // Set the SCL  

  7.     Delay(I2CDelay);  

  8.     SDA_High();   // Set the SDA while SCL is high indicates the finish signal  

  9. }  

1.2 數據位及地址位

       I2C通訊的數據位通常由1-8的數據構成,在主機進行數據的發送以及讀取期間,SCL總線時鐘信號時鐘仍由主機發出,每個SCL高電平期間對應一位數據。在SCL高電平期間,都應該保持SDA上的數據正確,因此在實際的應用中,通常使得SDA的高電平脈寬寬于SCL。

       地址位的發送與數據位類似,實際的操作中可以將設備的7位地址位+1位讀寫位作為一個8位字節進行整體的發送。以BQ25703A為例,默認設備地址為0x6B(7bit)。則在進行讀操作時,所要發送的字節為0xD7(1101011b+1b);進行寫操作時,所要發送的整體字節為0xD6 (1101011b+0b)。

       數據位及地址位的發送均可參考以下發送一個8位byte的實現方法:

  1. void I2C_Send_Byte(unsigned char txd)  

  2. {  

  3.     int t;  

  4.     SDA_Output();   // Config SDA GPIO as output  

  5.     SCL_Low();      // Clear the SCL to get ready to transmit  

  6.     txd&=0x00FF;    // Get the lower 8 bits 

  7.     for(t=0;t<8;t++)  

  8.         {  

  9.             SDA_Data_Register = (txd&0x80)>>7;  // Send the LSB  

  10.             txd<<=1;  

  11.             Delay(I2CDelay/2);  

  12.            SCL_High();   // Set the SCL 

  13.            Delay(I2CDelay);  

  14.            SCL_Low();    // Clear the SCL  

  15.            Delay(I2CDelay/2);  

  16.         } 

  17. }  

1.3 ACK/NACK指令

     Acknowledge(ACK)以及Not Acknowledge(NACK)指令通常發生在一個byte發送結束之后,用于標志一個byte發送的成功或失敗。特別需要注意的是,即使是在ACK時鐘周期期間,SCL總線時鐘信號也是由主機產生的。

     ACK: 當一次發送結束,主機釋放SDA總線。若發送成功,從機在第9個時鐘周期內拉低SDA總線,并在整個高電平期間保持。

     NACK: 當一次發送結束,主機釋放SDA總線。若發送失敗,在第9個時鐘周期內SDA始終處于高電平。

     在通訊中作為主機的MCU通常只需要實現NACK的發送以及ACK信號的等待,具體可參考以下程序:

  1. void I2C_NAck(void)  

  2. {  

  3.     SCL_Low();     // Clear the SCL to get ready to transmit  

  4.     SDA_Low() ;    // Clear the SDA  

  5.     Delay(I2CDelay);  

  6.     SCL_High();    // Set the SCL  

  7.     Delay(I2CDelay);  

  8.     SCL_Low();      // Clear the SCL  

  9.     Delay(I2CDelay); 

  10. }  

 


  1. Uint16 I2C_Wait_Ack(void)  

  2. {  

  3.     int ErrTime=0;  

  4.     int ReadAck=0;  

  5.     SDA_Input();  // Config SDA GPIO as Input

  6.     Delay(I2CDelay);  

  7.     SCL_High();   // Set the SCL and wait for ACK  

  8.     while(1)  

  9.     {  

  10.          ReadAck = SDA_Data_Register ;  // Read the input  

  11.          if(ReadAck)  

  12.         {   

  13.              ErrTime++;  

  14.              if(ErrTime>ErrLimit)  

  15.             {  

  16.                  //Error handler:Set error flag, retry or stop.  

  17.                 //Define by users  

  18.                  return 1;  

  19.              }  

  20.         }  

  21.          if(ReadAck==0)  // Receive a ACK

  22.          {  

  23.              Delay(I2CDelay);  

  24.             SCL_Low();   // Clear the SCL for Next Transmit  

  25.              return 0;  

  26.          }  

  27.      } 

   基于以上幾個基本的I2C通訊操作,就可以發送一個完整I2C數據幀,實現基本的I2C通訊功能,構建了利用GPIO口模擬I2C進行芯片控制的基礎。

二、I2C模擬器件寄存器寫入與讀取

         在構建了基本的I2C通訊功能之后,就可以利用I2C通訊對Slave進行控制或狀態的讀取,其本質就是對Slave的內部寄存器進行讀寫操作。下面以一個典型的帶有I2C功能的8位寄存器芯片為例,介紹如何利用前文的基礎I2C模擬函數對芯片的內部寄存器進行寫入和讀取。

         I2C 寫入:要進行一次I2C寫入,MCU首先要發送一個起始位以及一個由7位slave地址位和讀寫位(0b)組成的8位硬件寫地址,而后釋放SDA總線。若地址正確,slave將拉低SDA發送一個ACK。此后,MCU發送寫入寄存器的地址,并等待slave返回的ACK。響應后,MCU發送8位數據,并在收到ACK響應后發送停止位。


圖4 I2C寫入寄存器幀格式

具體實現方法可以參考以下代碼:


  1. void I2C_Write_Register(unsigned char Device, unsigned char Register,unsigned char Value)  

  2. {  

  3.         I2C_Start();  

  4.         I2C_Send_Byte(Device); //Send the device address  

  5.         I2C_Wait_Ack();       //Wait for the ack signal  

  6.         I2C_Send_Byte(Register); //Send the register address  

  7.         I2C_Wait_Ack();       //Wait for the ack signal  

  8.         I2C_Send_Byte(Value); //Send register value  

  9.         I2C_Wait_Ack();  

  10.         I2C_Finish(); 

  11. }  

         I2C讀取:要讀取Slave的內部寄存器,MCU首先要與Slave進行一次通信,告知Slave讀取的目標寄存器,該過程與進行寫入操作類似。MCU首先發送起始位、8位Slave寫地址,并在ACK信號后發送8位的目標寄存器地址。在Slave響應該地址后,MCU重新發送一次起始位,以及8位Slave讀地址(7位地址+1b),ACK響應后MCU釋放SDA總線,并繼續發送SCL時鐘信號讀取SDA上的內容。接收完成后,MCU 發送NACK位以及STOP位結束一次寄存器讀取操作。


圖5 I2C讀取寄存器幀格式

       8位Byte的讀方法可以參考以下代碼:

  1. unsigned char I2C_Read_Byte(void)  

  2. {  

  3.     int t,rxData;  

  4.     unsigned char receive;  

  5.     SDA_Input();  

  6.     for(t=0;t<8;t++)  

  7.     {  

  8.         SCL_Low();   // Clear the SCL 

  9.         Delay(I2CDelay);  

  10.          SCL_High();   // Set the SCL  

  11.          receive<<=1;  

  12.          rxData = SDA_Data_Register ;  

  13.          if(rxData)  

  14.          {  

  15.              receive++;  

  16.          }  

  17.          Delay(I2CDelay);  

  18.      }  

  19.      return receive; 

  20. }

          寄存器的讀方法可以參考以下代碼:


  1. unsigned char I2C_Read_Register(unsigned char Device_Write,unsigned char Device_Read, unsigned char Register)  

  2. {  

  3.     unsigned char ReadData;  

  4.     I2C_Start();  

  5.     I2C_Send_Byte(Device_Write); //Send the device address  

  6.     I2C_Wait_Ack();             //Wait for the ack signal  

  7.     I2C_Send_Byte(Register);    //Send the register address  

  8.     I2C_Wait_Ack();             //Wait for the ack signal  

  9.     I2C_Start();  

  10.     I2C_Send_Byte(Device_Read); //Send register value  

  11.     I2C_Wait_Ack();  

  12.     SDA_High();                  // Set the SDA  

  13.     ReadData = I2C_Read_Byte();  

  14.     I2C_NAck();  

  15.     Delay(1);  

  16.     I2C_Finish();  

  17.     return ReadData; 

  18. }  

三、參考例程

       本文附帶的例程中包含了完整GPIO模擬I2C通訊的頭文件以及函數,下面對例程中的主要內容進行介紹,以方便讀者理解。

圖6 I2C通訊程序架構

 

3.1宏定義

1)定義硬件通訊通訊地址及寄存器地址:

  1. #define Device_Address_Write 0xC0  

  2. #define Device_Address_Read 0xC1   

  3. #define REG_1 0x01  

  4. #define REG_2 0x02  

  5. #define REG_3 0x03  

  6. #define REG_4 0x04  

Device_Address_Write

硬件寫地址:默認地址0x60(7bit)+0b

Device_Address_Read

硬件讀地址:默認地址0x60(7bit)+0b

REG_1 - 4

硬件內部寄存器地址

   表1 硬件讀寫地址及寄存器地址

     在調用此代碼時,只需在.h文件依照所用器件實際情況修改硬件地址及各寄存器地址,就可以很方便地調用相關函數。

2)定義I2C通訊速率

  1. #define I2CDelay 1    // Define to configure I2C rate  





I2CDelay

I2C通訊時鐘高低電平時間

       表2 I2C通訊速率

     通過改變I2CDelay可以設置I2C通訊時鐘的高低電平持續時間,進而改變I2C的通訊速率。實際應用中,該值可以通過實際測試進行調整,以達到理想的通訊速率。

3)定義IO口動作

  1. #define SDA_High() {GpioDataRegs.GPASET.bit.GPIO7 = 1;EALLOW;GpioCtrlRegs.GPADIR.bit.GPIO7=1;EDIS;} 

  2. #define SDA_Low() {GpioDataRegs.GPACLEAR.bit.GPIO7 = 1;EALLOW;GpioCtrlRegs.GPADIR.bit.GPIO7=1;EDIS;}//To clear the SDA line. Disable protection for writing register  

  3. #define SDA_Input() {EALLOW;GpioCtrlRegs.GPADIR.bit.GPIO7=0;EDIS;}  // SDA DIR=Input  

  4. #define SDA_Output(){EALLOW;GpioCtrlRegs.GPADIR.bit.GPIO7=1;EDIS;}  // SDA DIR=Output  

  5. #define SDA_Data_Register GpioDataRegs.GPADAT.bit.GPIO7  

  6. #define SCL_High() {GpioDataRegs.GPASET.bit.GPIO6 = 1;}     //Set the SCL line  

  7. #define SCL_Low() {GpioDataRegs.GPACLEAR.bit.GPIO6 = 1;}  //Clear the SCL line  




SDA_High()

將SDA對應GPIO置1

SDA_Low()

將SDA對應GPIO置1

SDA_Input

將SDA對應GPIO設為輸入狀態

SDA_Output

將SDA對應GPIO設為輸出狀態

SDA_Data_Register

SDA對應GPIO數據寄存器

SCL_High()

將SCL對應GPIO置1

SCL_Low()

將SCL對應GPIO置0

表3 IO口動作宏定義

         將GPIO口的動作以宏定義的形式定義為SDA、SCL的動作,以增強代碼的可讀性。在進行程序移植時,只需要根據單片機實際情況將宏定義內的代碼更換成對應GPIO口動作的代碼,不需要對程序其他部分進行改動。其中EALLOWEDIS語句是TI C2000產品改變GPIO口方向時需要解除相應的保護,請根據具體情況進行改動。

4)定義Delay函數

  1. #define Delay(A) DELAY_US(A)  

       Delay()函數用于進行程序中SDA、SCL的高低電平延時,在例程中實際被定義成DELAY_US()函數。在移植過程需要根據實際情況修改宏定義,更改成適用用戶MCU的延時函數,不需要對后續程序進行修改。

3.2 I2C通訊功能函數

  1. void I2C_Start(void);  

  2. void I2C_Finish(void);  

  3. Uint16 I2C_Wait_Ack(void);  

  4. void I2C_NAck(void);  

  5. void I2C_Send_Byte(unsigned char xtd);  

  6. unsigned char I2C_Read_Byte(void);  

函數名稱

功能描述

void I2C_Start(void)

發送I2C通訊起始信號

void I2C_Finish(void)

發送I2C通訊結束信號

Uint16 I2C_Wait_Ack(void)

等待Ack應答信號,返回接收狀態

void I2C_NAck(void)

發送一個NAck信號,用于寄存器讀取

void I2C_Send_Byte(unsigned char xtd)

發送一個字節

unsigned char I2C_Read_Byte(void)

讀取一個字節

void Gpio_setup(void)

GPIO口配置

void I2C_Write_Register(unsigned char Device, unsigned char Register, unsigned char value)

I2C 寫寄存器函數

void I2C_Read_Register(unsigned char Device_Write, unsigned char Device_Read, unsigned char Register)

I2C 讀寄存器函數

表4 I2C通訊函數

四、總結

       針對由于MCU缺少I2C接口而不能直接使用I2C與外圍芯片進行通訊的問題,本文給出了使用IO模擬I2C接口的方法。首先,從I2C協議入手對數據幀中各個位的邏輯電平進行了詳細介紹,并給出基于C2000 GPIO的具體實現方法;在此基礎上,以常見的8位I2C通訊Slave為例介紹了內部寄存器的讀取邏輯,并給出了實現方法。最后,針對附帶的參考例程內容進行了介紹,方便讀者參考例程,其它MCU也可以在本例程上進行快速的移植。本文為使用IO模擬I2C需求給出了一種有效的解決方案。

下一篇: PLC、DCS、FCS三大控

上一篇: 基于C2000的軟件串口

推薦產品

更多
主站蜘蛛池模板: 欧美黑人疯狂性受xxxxx喷水 | 欧美日日射 | 亚洲在线观看 | 国产精品久久久久久久y | 欧美日韩福利视频 | 色撸网| 欧美日剧在线免费 | 色婷综合 | 精品久久一区 | 久碰人澡人澡人澡人澡91 | 美女狠狠干 | 国内精品久久久久久2021浪潮 | 亚洲欧洲精品在线 | 香蕉视频在线播放 | 国产午夜精品久久久 | 国产成年网站v片在线观看 中文字幕在线免费视频 | 天天干天天干天天干天天干天天干 | www.4hu影院| 亚洲视频在线视频 | 99久久九九爱看免费直播 | 久久精品国产一区 | 久久一日本道色综合久久 | 十八勿入| 999久久久久久久久6666 | 久久草在线视频 | 天天干天天色综合 | 欧美狠狠操 | 中文字幕av一区二区 | 国产一区二区三区免费 | 亚洲综合在线视频 | 在线欧美日韩 | 精品日韩在线观看 | 国产精品成人在线 | 午夜天堂精品久久久久 | 亚洲欧美第一页 | 国产成人精品一区二区三区四区 | 91精品综合久久久久久五月天 | 奇米影视777中文久久爱 | 久久宗合色 | 久久精品久久久久久 | 奶子吧naiziba.cc免费午夜片在线观看 |