欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136

標題: IIC通信協議分析--STM32F4驅動溫濕度傳感器SHT20為例 [打印本頁]

作者: csy-2015-06    時間: 2018-10-27 10:49
標題: IIC通信協議分析--STM32F4驅動溫濕度傳感器SHT20為例
IIC總線
1       IIC總線概述(文檔有圖)
I2C總線兩線制包括:串行數據SDA(Serial Data)、串行時鐘SCL(Serial Clock)。總線必須由主機(通常為微控制器)控制,主機產生串行時鐘(SCL)控制總線的傳輸方向,并產生起始和停止條件。
IIC總線特征:同步串行半雙工(同一時刻只能是一種身份)
2       IIC總線拓撲圖
                              
SDA:雙向串行數據線,數據是一位一位傳輸,既可以從主機發送到從機,也可以從從機發送到主機
SCL:時鐘線(單向),驅動數據線SDA的信號由時鐘線SCL提供,只能由主機發送,從機接收
主機:主機產生串行時鐘(SCL)控制總線的傳輸方向,并產生起始條件(占用總線)和停止條件(釋放總線)
從機:從機也能發送數據給主機,但是從機永遠不會主動給主機發送數據。
主機是主宰
主機是如何找到從機來進行通信的呢?
2.1   主從設備通信
主機如何能找到對應的從機與其進行通信?
每個從機都有一個唯一的器件地址,主機就是通過這個器件地址去找到對應的從機與其通信。
器件地址誰分配?如何分配?(具體查看模塊手冊)
在IIC總線上,從機的器件地址可以為7位或者10位,一般情況下都是7位器件地址。
在器件地址中包含了固定地址(在高位,不可變)和可編程地址(在低位,可變)
器件地址的位數是由廠家決定
固定地址的位數和內容也是由廠家決定
可編程地址的位數由廠家決定
可編程地址的內容由使用者決定
3       IIC數據幀
UART數據幀格式:起始位+數據位(5~8)+校驗位+停止位。
IC數據幀格式:起始條件+數據位(8位)+應答位+停止條件
起始條件:一次通信的開始(主機占用總線)
數據位:從發送器到接收器,連續的8位數據
應答位:當接收器成功接收到發送器的8位數據后,必須應答。0代表應答,1代表非應答。
停止條件:一次通信的結束(主機釋放總線,雙線電平拉高)
4       標準IIC協議
空閑狀態
開始信號
停止信號
應答信號
數據的有效性
數據傳輸
4.1   空閑狀態(都拉高,數據比時鐘快)
空閑狀態:此時各個器件的輸出級場效應管均處在截止狀態,即釋放總線,由兩條信號線各自的上拉電阻把電平拉高。




4.2   起始條件(CD變低)和停止信號(CD變高、都高)
  
起始信號:當SCL為高期間,SDA由高到低的跳變;啟動信號是一種電平跳變時序信號,而不是一個電平信號。
停止信號:當SCL為高期間,SDA由低到高的跳變;停止信號也是一種電平跳變時序信號,而不是一個電平信號。
起始條件偽代碼
  
SCL=1
  
SDA=1    //起始前都是高電平
  
//延時,起始條件建立時間
  
SDA=0//SDA變低,產生起始條件
  
//延時,起始條件的保持時間
  
SCL=0//一個周期的結束
  
停止條件偽代碼
  
SCL=1
  
SDA=0//低
  
//延時,停止條件建立時間
  
SDA=1//SDA變高 產生停止條件
  
//延時,本次停止條件到下一個起始條件的時間間隔
  
4.3   位傳輸(CD準備數據,C拉高讀取D)
SCL串行時鐘的配合下,在SDA上逐位地串行傳送每一位數據。數據的準備是在SCL的低電平,數據位的傳輸是上邊沿觸發。
拉低準備數據,拉高采集數據
主機發送一位數據給從機:(主機輸出)
  
SCL=0//主機拉低時鐘線
  
SDA=0/1//主機在總線上準備數據
  
//延時,讓數據穩定在數據線上
  
SCL=1//主機拉高時鐘線
  
從機在時鐘上升沿從總線上采集數據
  
//延時,給時間從機采集數據
  
  
主機讀取從機發送的一位數據:(主機輸入)
  
SCL=0//主機拉低時鐘線
  
從機在總線上準備數據(從機自動進行,主機不動作)
  
//延時,讓數據穩定在數據線上
  
SCL=1//主機拉高時鐘線
  
主機讀取SDA//主機在時鐘上升沿從總線上采集數據
  
//延時,給時間主機機采集數據
  
  
4.4   應答位(第九位發送高(不應答)低(應答))
發送器每發送一個字節,就在時鐘脈沖9期間釋放數據線,由接收器反饋一個應答信號。
應答信號為低電平時,規定為有效應答位(ACK簡稱應答位),表示接收器已經成功地接收了該字節;
應答信號為高電平時,規定為非應答位(NACK),一般表示接收器接收該字節沒有成功
主機讀取從機的應答:(主機讀取一位數據)
主機每發送1個字節給從機后,都必須通過這個應答位查看從機是否能正常收到,如果一旦讀到的是非應答信號(‘1’),表明沒有正常接收到當前字節數據,通信就要終止(主機發送停止信號)
  
SCL=0//主機拉低時鐘線            (還是拉低給數據,拉高采集數據)
  
從機根據自己接受的情況,給不給主機應答信號
  
//延時,讓數據穩定在數據線上
  
SCL=1//主機拉高時鐘線
  
主機讀取SDA//主機在時鐘上升沿從總線上采集應答信號
  
//延時,給時間主機機采集數據
  
如果采集到的0,表示有應答,如果采集到的是1,表示非應答
  
  
主機發送一個應答給從機:(主機發送一位數據)
主機每讀取完從機發送過來的一個字節數據后,都必須給從機一個應答信號。如果主機讀取完當前字節后還想從機繼續給它發下一個字節數據,就要給從機應答(‘0’),如果主機讀取完當前字節后不想從機再給它發數據,那么主機發送非應答信號(‘1’)給從機。
  
SCL=0//主機拉低時鐘線
  
SDA=0/1//主機根據自己的情況,決定給不給應答從機
  
//延時,讓數據穩定在數據線上
  
SCL=1//主機拉高時鐘線
  
從機在時鐘上升沿從總線上采集應答位
  
//延時,給時間從機采集數據
  
5       IIC的尋址方式  
器件地址(8位)組成:7位從設備地址+1位方向位
從設備地址包含了固定地址和可編程地址
方向位決定有效數據位的傳輸方向,主機---》從機(主機寫) 還是 從機----》主機(主機讀)
5.1   IIC一次完整通信
1.      主機發送起始條件(主機占用總線,喚醒總線所有的從機)
2.      主機發送器件地址(總線上所有的從機就會拿這個器件跟自身進行比較,匹配成功的那個從機就會回復                 一個應答信號給主機,并根據方向位來決定數據傳輸方向)
3.      進行有效數據交流(每傳輸完一個直接數據都要給應答)
4.      主機發送停止信號(釋放總線,結束本次通信)
5.2   IIC三種通信方式
只讀主機只讀取數據
只寫:主機僅發送數據
有讀有寫
6       GPIO口模擬IIC通信協議
GPIO初始化
作為SCL的GPIO口:時鐘線SCL只能由主機(MCU)發出,SCL既有低電平也有高電平,所以這個GPIO口可以配置成推挽輸出,另外總線結構本來就有上拉電阻,所以也可以配置成開漏輸出。
作為SDA的GPIO口:數據線SDA是雙向的,有時候需要從MCU發送,有時候又要輸入到MCU里。剛好,在M4里面,當GPIO口配置成輸出模式時,輸入電路并沒有被關閉。但是,當在采集輸入信號的時候,IO口的輸出電路就很有可能會影響到輸入信號的采集,所以必須要配置成開漏輸出,在讀取輸入信號前輸出‘1’,目的是讓輸出電路從IO口中斷開。
準備數據要延時,讀取數據也要延時
起始條件
  
void IIC_Start(void)
  
{
  
         IIC_SCL=1;
  
         IIC_SDA_OUT=1;
  
         Systick_Delay_us(1);//延時,起始條件建立時間
  
         IIC_SDA_OUT=0;//產生起始條件
  
         Systick_Delay_us(2);//延時,起始條件的保持時間
  
         
  
         IIC_SCL=0;//一個周期的結束
  
}
  
停止條件
  
void IIC_Stop(void)
  
{
  
         IIC_SCL=1;
  
         IIC_SDA_OUT=0;
  
         Systick_Delay_us(1);//延時,停止條件建立時間
  
         IIC_SDA_OUT=1;//產生停止條件
  
  
         Systick_Delay_us(1);//延時,本次停止條件到下一個起始條件的時間間隔
  
}
  
主機發送應答
  
void IIC_Send_ACK(u8 ack)
  
{
  
         IIC_SCL=0;//主機拉低時鐘線
  
         if(ack)//主機根據自己的情況,決定給不給應答從機
  
         {
  
                  IIC_SDA_OUT=1;
  
         }
  
         else
  
         {
  
                  IIC_SDA_OUT=0;
  
         }
  
         Systick_Delay_us(2);//延時,讓數據穩定在數據線上
  
         IIC_SCL=1;//主機拉高時鐘線,從機在時鐘上升沿從總線上采集應答位
  
         Systick_Delay_us(1);//延時,給時間從機采集數據
  
         
  
}
  
主機讀取應答
  
u8 IIC_Revice_Ack(void)
  
{
  
         u8 ack=0;
  
         
  
         IIC_SCL=0;//主機拉低時鐘線
  
         IIC_SDA_OUT=1;//切換成讀模式---讓輸出電路從IO口斷開*************************
  
         //從機根據自己接受的情況,給不給主機應答信號
  
         Systick_Delay_us(2);//延時,讓數據穩定在數據線上
  
         IIC_SCL=1;//主機拉高時鐘線
  
         if(IIC_SDA_IN)//主機在時鐘上升沿從總線上采集應答信號
  
         {
  
                  ack=1;
  
         }
  
         Systick_Delay_us(1);//延時,給時間主機機采集數據
  
         
  
         IIC_SCL=0;//完整周期   
  
         return ack;
  
  
}
  
主機發送一個字節數據給從機
  
u8 IIC_Send_Byte(u8 data)  
  
{
  
         u8 i;
  
         
  
         for(i=0;i<8;i++)
  
         {
  
                  IIC_SCL=0;//主機拉低時鐘線
  
                  //主機在總線上準備數據
  
                  if(data&0x80)  IIC_SDA_OUT=1;
  
                  else  IIC_SDA_OUT=0;
  
                  Systick_Delay_us(2);//延時,讓數據穩定在數據線上
  
                  IIC_SCL=1;//主機拉高時鐘線
  
                  //從機在時鐘上升沿從總線上采集數據
  
                  Systick_Delay_us(1);//延時,給時間從機采集數據
  
                  
  
                  data<<=1;//讓次高位成為最高位
  
         }
  
         
  
         return IIC_Revice_Ack(  );
  
}
  
主機讀取從機的一個字節數據
  
u8 IIC_Revice_Byte(u8 ack)
  
{
  
         u8 i;
  
         u8 data=0;
  
         
  
         for(i=0;i<8;i++)
  
         {
  
                  IIC_SCL=0;//主機拉低時鐘線
  
                  IIC_SDA_OUT=1;//切換成讀模式---讓輸出電路從IO口中斷開***************************
  
                  //從機在總線上準備數據
  
                  Systick_Delay_us(2);//延時,讓數據穩定在數據線上
  
                  IIC_SCL=1;//主機拉高時鐘線
  
                  data<<=1;//空出最低位來接受數據
  
                  //主機在時鐘上升沿從總線上采集數據   
  
                  if(IIC_SDA_IN)
  
                  {
  
                          data  |=1;
  
                  }                        
  
                  Systick_Delay_us(1);//延時,給時間主機機采集數據
  
                  
  
         }
  
         
  
         IIC_Send_ACK(ack);
  
         
  
         return data;
  
}
  
7       IIC驅動溫濕度傳感器
7.1   SHT20命令
7.2   SHT20測量時序
7.3   示例代碼
  
float Read_SHT20_Data(u8 cmd)
  
{
  
         u8 ack;
  
         u16 data=0;
  
         float DATA;
  
         IIC_Start( );//起始信號
  
         ack =  IIC_Send_Byte(SHT20_ADDR&0XFE);//發送器件地址+寫方向
  
         
  
         if(ack)//沒有應答
  
         {
  
                  IIC_Stop(  );
  
                  return -1;
  
         }      
  
         ack =  IIC_Send_Byte(cmd);//發送測量命令
  
         if(ack)//沒有應答,等待從機應答
  
         {
  
                  IIC_Stop(  );
  
                  return -1;
  
         }      
  
         do
  
         {
  
                  Delay_ms(10);//給時間測量
  
                  IIC_Start(  ); //開始信號,測量中
  
                  ack =  IIC_Send_Byte(SHT20_ADDR | 0x01);//發送器件地址+讀方向
  
         }while(ack);//沒有應答則繼續詢問,知道有應答,表明測量結束
  
         
  
         data |=  IIC_Revice_Byte(0) <<8;//高位結果
  
         data |=  IIC_Revice_Byte(1) ;   //低位結果
  
         
  
         IIC_Stop( );
  
         
  
         //------數字信號轉換成模擬信號
  
         data &=0xFFFC;//清除兩位狀態位
  
         
  
         if(cmd==T_MEASURE)
  
         {
  
                  DATA=-46.85+175.72*data/65536.0;
  
         }
  
         else  if(cmd==RH_MEASURE)
  
         {
  
                  DATA=-6.0+125.0*data/65536.0;
  
         }
  
         
  
         return DATA;
  
}
  


作者: csy-2015-06    時間: 2018-10-27 10:51
PDF文檔密碼:20171027

拓撲圖.png (55.77 KB, 下載次數: 79)

拓撲圖.png

IIC總線.pdf

966.81 KB, 下載次數: 45, 下載積分: 黑幣 -5

密碼:20181027


作者: leekuip    時間: 2020-2-28 18:18
樓主,這個有stm32F4的完成代碼嗎?我用F103的代碼移植到407上,不好使了,不知道啥問題。
作者: zycwswws    時間: 2020-6-29 22:59
非常感謝,最近在做一個相關的項目,遇到問題,能不能冒昧請教下??




歡迎光臨 (http://m.raoushi.com/bbs/) Powered by Discuz! X3.1