国产精品久久久久影院,成人午夜福利视频,国产精品久久久久高潮,国产精品 欧美 亚洲 制服,国产精品白浆无码流出

STM32 IIC雙機(jī)通信—— HAL庫硬件IIC版

發(fā)布者:Weasel最新更新時間:2025-02-19 來源: cnblogs關(guān)鍵字:STM32  IIC  雙機(jī)通信  HAL庫 手機(jī)看文章 掃描二維碼
隨時隨地手機(jī)看文章

  關(guān)于IIC的原理這里我就不多說了,網(wǎng)上有很多很好的解析,如果要看我個人對IIC的理解的話,可以點擊查看,這里主要講一下怎樣利用STM32CubeMx實現(xiàn)IIC的通訊,經(jīng)過個人實踐,感覺HAL庫的硬件IIC要比標(biāo)準(zhǔn)庫的穩(wěn)定。好了,下面就從STM32CubeMx 配置開始一步步實現(xiàn)IIC通訊。

  STM32CubeMx的配置,這里關(guān)于新建工程的步驟我就不細(xì)說了,如果還不會操作STM32CubeMx 的可以點擊查看, 這里主要對IIC的配置進(jìn)行說明。

  

  了解IIC的都知道,IIC通信有主從機(jī)之分,用兩片STM32進(jìn)行IIC通信當(dāng)然也不例外,不過使用STM32CubeMx 配置有一個好處,就是不用分別配置主從機(jī),在STM32CubeMx 配置里面,主從機(jī)的配置是一樣,唯一不同的就是IIC的地址如上圖,這個地址很重要,只要配置好了,基本就成功了。

  還有一個要注意的,就是IIC的SDA、SCK引腳要配置成NPP模式,不然容易出現(xiàn)信號線忙,檢測不到從機(jī)的情況。

  

  配置配好后我們生成代碼,就可以進(jìn)行通信了,主從機(jī)核心代碼如下:

 

  下面是主機(jī)的重要代碼:


/* I2C2 init function  IIC配置*/

static void MX_I2C2_Init(void)

{


  hi2c2.Instance = I2C2;

  hi2c2.Init.Timing = 0x10805D88;

  hi2c2.Init.OwnAddress1 = 20;        //用戶自己配置的地址

  hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;

  hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;

  hi2c2.Init.OwnAddress2 = 0;        

  hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK;

  hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;

  hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

  if (HAL_I2C_Init(&hi2c2) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }


    /**Configure Analogue filter 

    */

  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }


    /**Configure Digital filter 

    */

  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }


}


while(HAL_I2C_Master_Transmit_IT(&hi2c2 ,0x0b,&BUFF[0], 1)!= HAL_OK){}   

//IIC主機(jī)發(fā)送函數(shù),主要IIC配置好了,這個可以添加到main函數(shù)里面測試


關(guān)于STM32CubeMx的HAL庫IIC收發(fā)有幾種函數(shù),用戶可以根據(jù)自己不同的需求進(jìn)行選擇,以下就是主要的幾個HAL庫IIC收發(fā)函數(shù):


/* 第1個參數(shù)為I2C操作句柄

   第2個參數(shù)為從機(jī)設(shè)備地址

   第3個參數(shù)為從機(jī)寄存器地址

   第4個參數(shù)為從機(jī)寄存器地址長度

   第5個參數(shù)為發(fā)送的數(shù)據(jù)的起始地址

   第6個參數(shù)為傳輸數(shù)據(jù)的大小

   第7個參數(shù)為操作超時時間   */

HAL_I2C_Mem_Write(&hi2c2,salve_add,0,0,PA_BUFF,sizeof(PA_BUFF),0x10);


HAL_I2C_Mem_Write_IT();


HAL_I2C_Mem_Read();


HAL_I2C_Mem_Read_IT();


HAL_I2C_Mem_Read_DMA();


HAL_I2C_Mem_Write_DMA();


/*    不需要用到寄存器地址的主機(jī)HAL庫IIC收發(fā)函數(shù)   */

HAL_I2C_Master_Receive();     //STM32 主機(jī)接收,不需要用到寄存器地址

HAL_I2C_Master_Transmit();


HAL_I2C_Master_Receive_IT();   //中斷IIC接收 

HAL_I2C_Master_Receive_DMA();  //DMA 方式的IIC接收  


HAL_I2C_Master_Transmit_IT();   //中斷IIC發(fā)送  


HAL_I2C_Master_Transmit_DMA();   //DMA 方式的IIC發(fā)送  


HAL_I2C_Master_Transmit(&hi2c2,0x0B,PA_BUFF,sizeof(PA_BUFF),0x10); //STM32 主機(jī)發(fā)送 


/* 不需要用到寄存器地址的從機(jī)HAL庫IIC收發(fā)函數(shù)   */ 

HAL_I2C_Slave_Receive();    //STM32 從機(jī)機(jī)接收,不需要用到寄存器地址 

 

HAL_I2C_Slave_Transmit();   //STM32 從機(jī)機(jī)發(fā)送,不需要用到寄存器地址  


HAL_I2C_Slave_Receive_IT(); 


HAL_I2C_Slave_Receive_DMA(); 


HAL_I2C_Slave_Transmit_IT();


HAL_I2C_Slave_Transmit_DMA();


我這里因為只是做兩個STM32間的單向通行而已,不需要對寄存器進(jìn)行寫數(shù)據(jù)。


所以主機(jī)發(fā)送函數(shù)選擇了 HAL_I2C_Master_Transmit( ); 函數(shù),而我從機(jī)則選擇HAL_I2C_Slave_Receive( );函數(shù),從機(jī)代碼如下:


/*   I2C2 init function 從機(jī)IIC初始化配置   */

static void MX_I2C2_Init(void)

{


  hi2c2.Instance = I2C2;

  hi2c2.Init.Timing = 0x10805D88;

  hi2c2.Init.OwnAddress1 = 0x0A;

  hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;

  hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;

  hi2c2.Init.OwnAddress2 = 0;

  hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK;

  hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;

  hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

  if (HAL_I2C_Init(&hi2c2) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }


    /**Configure Analogue filter 

    */

  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }


    /**Configure Digital filter 

    */

  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK)

  {

    _Error_Handler(__FILE__, __LINE__);

  }


}


while(HAL_I2C_Slave_Receive(&hi2c2, RE_BUFF, 1, 100)!= HAL_OK) {} 

// 在配置好IIC后,可直接把該函數(shù)放到main函數(shù)測試,第一個參數(shù)是IIC通道選擇,第二個參數(shù)是接收緩存,第三個數(shù)據(jù)的是接收長度,第四個參數(shù)是超時時間


  經(jīng)過測試,發(fā)現(xiàn)如果發(fā)送數(shù)據(jù)過多,用硬件I2C收發(fā)的話,使用中斷會比較穩(wěn)定

  作為從機(jī),要與主機(jī)完成通信,有一個特別要注意的事情,就是IIC配置的地址要與主機(jī)發(fā)送的地址一致,否則無法完成應(yīng)答。我一開始就是直接發(fā)送自己在軟件配置的IIC地址,可是沒有通信成功,檢查才發(fā)現(xiàn),軟件配置好IIC后,生成代碼時,地址會最后一位補(bǔ)0,自動補(bǔ)夠8位;而我從機(jī)發(fā)送出來的地址,也會把你發(fā)送的地址最后一位改為0再發(fā)送,這個我查了一下函數(shù)地層,好像是因為這是是發(fā)送函數(shù),所以直接幫你把R/W位改為0了。所以導(dǎo)致我一開始怎么都調(diào)不通,使用邏輯分析儀后,分析采集到的數(shù)據(jù)才發(fā)現(xiàn)這個問題,于是我,直接手動改從機(jī)的IIC地址,改成邏輯分析儀發(fā)出來的地址一樣,這樣就通了。

 

  通信結(jié)果如圖所示:

  

 

補(bǔ)充2點要注意的:

  1. IIC硬件連接的時候SDA跟SCL總線注意都要上拉一個4.7K的電阻,否則IIC無法工作;

  2. 使用主從收發(fā)函數(shù)時,發(fā)送的地址要注意。如果是發(fā)送函數(shù),發(fā)送出的地址最后一位 R/W 位如果不為0,則HAL庫函數(shù)會地址把最后一位修改為0,再把地址發(fā)送出去,但是如果地址最后一位 R/W 位為0,函數(shù)就不會對地址進(jìn)行修改,直接把地址發(fā)送出去;如果是接收函數(shù),發(fā)送出去的地址最后一位 R/W位 不為1,則HAL庫函數(shù)會把地址最后一位修改為1,再把地址發(fā)送出去,但是如果地址最后一位 R/W 位為1,函數(shù)就不會對地址進(jìn)行修改,直接把地址發(fā)送出去.。所以從機(jī)地址設(shè)置,一定要與主機(jī)發(fā)出的地址一致才能正確應(yīng)答。

  例如:

 ?。?) HAL_I2C_Master_Receive(&hi2c2,0x0a,(uint8_t *)test,sizeof(test),1000); 因為這個是讀出數(shù)據(jù)函數(shù),這里發(fā)送的地址位第8位地址位 R/W 位應(yīng)該為 1,發(fā)送地址 0x0a 硬件會把最后一位改為0,把地址變成0xb 再把 0x0b這個地址發(fā)送出去 ;如果地址最后一位R/W是 1,發(fā)送地址是 0x0b ,因為最后一位為 1,那么該函數(shù)發(fā)送的地址就不會對發(fā)送的地址最后一位R/W為做出修改,直接把 0x0b 發(fā)送出去,發(fā)出去的地址依然為0x0b。

 ?。?) HAL_I2C_Master_Transmit(&hi2c2,0x0f,(uint8_t *)test,sizeof(test),1000); 因為這個是寫入數(shù)據(jù)函數(shù),R/W 位為 0,發(fā)送地址 0x0f 硬件會把最后一位改為 0 變成 0xe,如果發(fā)送的地址是 0xa ,則不會對地址進(jìn)行修改,直接把地址 0x0a 發(fā)送出去。

  

  現(xiàn)在我以F40X系列的STM32 的 IIC 讀函數(shù)為例子來翻一下函數(shù)地層分析造成這個問題的原因:

  

  來到地層我們找到發(fā)送地址的函數(shù);

  

  

  

  上面跳轉(zhuǎn)到這里我們就接近真相了,上圖1是跳轉(zhuǎn)下去的 IIC 寫函數(shù)的地層,2 是 IIC 跳轉(zhuǎn)下去的讀函數(shù)的地層,這里 ADDRESS 就是用戶寫進(jìn)IIC發(fā)送讀取函數(shù)里的尋址地址了,接下來到重點了,對于I2C_OAR1_ADD0 我們再次跳轉(zhuǎn)分析下去看看;

  

  從這里接收函數(shù)我們可以看到,I2C_OAR1_ADD0 最終的值應(yīng)該為 0x00000001,我們依舊以地址 0x 0b 為例: 0x 0b = 0000 1011 , 由或運算的定義我們可知,數(shù)據(jù)再做或運算 (|)時, 參加運算的兩個對象只要有一個為1,其值為1 , 所以 (00000001) | (0000 1011)= 0000 1011= 0x0b 。這時如果地址為 0x0xa(0000 1010),則會出現(xiàn)地址位最后一位R/W位被改為1的情況,運算過程為(00000001) | (0000 1010)= 0000 1011 = 0x0b ,結(jié)合這個地層運算,就不難解析為什么使用HAL庫的 IIC 接收函數(shù),發(fā)送出去的地址會出現(xiàn)變化的情況了。

  至于發(fā)送函數(shù)同理,I2C_OAR1_ADD0 最終的值應(yīng)該為 0x00000001,取反后就變成了 0x 1111 1110 ,由與運算(&)的定義可知兩位同時為“1”,結(jié)果才為“1”,否則為0。所以這里我們依舊以地址0x0b = 0000 1011 為例,(1111 1110) &(0000 1011)= 0000 1010 = 0x0b,所以發(fā)送函數(shù)把地址最后一位的R/W位改為了 0 ,而當(dāng)?shù)刂窞?nbsp;0x0a = 0000 1010 時,我們再進(jìn)行運算一下可得(1111 1110) &(0000 1010)= 0000 1010  = 0x0a , 地址沒有改變,所以這也就解析了上面我說的地址變化的問題了。


關(guān)鍵字:STM32  IIC  雙機(jī)通信  HAL庫 引用地址:STM32 IIC雙機(jī)通信—— HAL庫硬件IIC版

上一篇:STM32 HAL庫利用DMA實現(xiàn)串口不定長度接收方法
下一篇:STM32 GPIO重映射

推薦閱讀最新更新時間:2025-07-03 11:53

【STM32CubeMX】3,STM32HAL庫運用小方法
1,當(dāng)在hal頭文件中看到該函數(shù)時,還不理解,直接復(fù)制百度就好 如HAL_UART_Transmit(),有些論壇講解的非常詳細(xì) 2,hal_adc.c文件一般都是詳細(xì)解釋, hal_adc.h文件都是關(guān)鍵函數(shù)的綜述,這個對于快速上手非常重要
[單片機(jī)]
【STM32CubeMX】3,<font color='red'>STM32</font>的<font color='red'>HAL庫</font>運用小方法
STM32硬件IIC操作解析
  IIC 即Inter-Integrated Circuit(集成電路總線),這種總線類型是由飛利浦半導(dǎo)體公司在八十年代初設(shè)計出來的一種簡單、雙向、二線制、同步串行總線,主要是用來連接整體電路(ICS) ,IIC是一種多向控制總線,也就是說多個芯片可以連接到同一總線結(jié)構(gòu)下,同時每個芯片都可以作為實時數(shù)據(jù)傳輸?shù)目刂圃础_@種方式簡化了信號傳輸總線接口。   I2C串行總線一般有兩根信號線,一根是雙向的數(shù)據(jù)線SDA,另一根是時鐘線SCL。所有接到I2C總線設(shè)備上的串行數(shù)據(jù)SDA都接到總線的SDA上,各設(shè)備的時鐘線SCL接到總線的SCL上。   為了避免總線信號的混亂,要求各設(shè)備連接到總線的輸出端時必須是漏極開路(OD)輸出或
[單片機(jī)]
<font color='red'>STM32</font><font color='red'>硬件</font><font color='red'>IIC</font>操作解析
關(guān)于51單片機(jī)雙機(jī)通信
上圖為雙機(jī)通信示意圖,下面分別給出雙機(jī)通信的程序 //用于接收方 #include #define uchar unsigned char; #define uint unsigneed int; uchar a;//用于保存發(fā)來的數(shù)據(jù) uchar b ={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82, 0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //數(shù)碼管顯示0-9; void init(void) { SCON = 0x50; PCON = 0x00; TMOD = 0x20; TH1 = 0xf4; TL1
[單片機(jī)]
關(guān)于51單片機(jī)<font color='red'>雙機(jī)通信</font>
STM32F7xx —— 啟動文件和HAL庫
一.庫開發(fā)的優(yōu)勢 開發(fā)速度快,便于移植。 二.stm32F7xx幾個重要文件 1. HAL庫關(guān)鍵文件 文件 描述 stm32f7xx_hal_ppp.c/h 基本外設(shè)的操作API stm32f7xx_hal_ppp_ex.c/h 拓展外設(shè)特性的API stm32f7xx_hal.c/h HAL通用API(如HAL_Init, HAL_Delay等) stm32f7xx_hal_conf.h HAL的配置文件,選擇使能某種功能 stm32f7xx_hal_def.h HAL的通用數(shù)據(jù)類型和定義 stm32f7xx_ll_ppp.c/h 復(fù)雜外設(shè)的底層實現(xiàn) 2.stm32f7
[單片機(jī)]
基于HAL庫處理UART中斷并接收串口傳入的數(shù)據(jù)
研究了下HAL庫,在百度上面找發(fā)現(xiàn)很多UART串口接收,串口中斷處理是從USART那邊直接抄過來的,使用的是標(biāo)準(zhǔn)庫一類的,在用HAL庫配置的工程中完全沒法使用,另辟蹊徑,通過在文檔中翻找HAL打頭的函數(shù)發(fā)現(xiàn)已經(jīng)有十分簡單的封裝了。 正確的獲取接收數(shù)據(jù)的方法是: 1.在進(jìn)入中斷后使用HAL庫函數(shù)中的HAL_UART_GetState函數(shù)確定UART的接收是否結(jié)束,這個函數(shù)也可以判斷發(fā)送數(shù)據(jù)是否忙碌等(HAL_UART_BUSY_xx) 2.處理緩存中的數(shù)據(jù),提取保存到自定義的變量數(shù)組中,用HAL_UART_Receive函數(shù)實現(xiàn) 3.重置中斷標(biāo)志位 這一個函數(shù)演示了UART4如何正確的接收數(shù)據(jù),再發(fā)送回去,平臺是
[單片機(jī)]
STM32CubeMX Hal庫的一些坑
使用的是stm32f103 V1.40版本的庫 UART DMA發(fā)送的問題 發(fā)送函數(shù) HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size); 發(fā)送完畢之后成功的回調(diào)函數(shù)也正常,可是再次發(fā)送的時候就發(fā)不出去了。一直返回錯誤。 我們看下這個函數(shù)的代碼 HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) { uint32_t *tmp;
[單片機(jī)]
HAL庫教程13:AD+DMA采集數(shù)據(jù)的濾波
??借助DMA可以快速采集大量數(shù)據(jù),如果數(shù)據(jù)采集過來卻不使用就是浪費。在我的板子上,AD值代表溫度,如果系統(tǒng)檢測到溫度過高,可能會采取一些強(qiáng)制的保護(hù)措施。而AD采樣是容易受干擾的,所以要對采樣數(shù)據(jù)進(jìn)行濾波,減少噪聲對系統(tǒng)的干擾。接下來我們采用計算平均值的算法來濾波。 ??我們從每256個數(shù)據(jù)中,提取出1個算數(shù)平均值。2個通道,每個通道采集256個數(shù)據(jù)的話,共需要采集512個數(shù)據(jù)。由于DMA轉(zhuǎn)換數(shù)據(jù)是循環(huán)進(jìn)行的,如果等512個數(shù)據(jù)全部采集完,再做算數(shù)平均的話,新的數(shù)據(jù)已經(jīng)采集完畢,舊的數(shù)據(jù)被覆蓋,發(fā)生了改變。因此可以采用分兩段處理的思想。 ??開啟一個1024大小的數(shù)組,在前半段轉(zhuǎn)化完成時,也就是前512個數(shù)據(jù)個數(shù)據(jù)已經(jīng)處理完畢的時
[單片機(jī)]
IIC讀寫AT24Cxx (S3C2440)
IIC(Inter-Integrated Circuit,I2C)總線是一種由PHILIPS公司開發(fā)的兩線式串行總線,用于連接微處理器及其外圍設(shè)備,它的最主要優(yōu)點是簡單和有效。它只需要數(shù)據(jù)線SDA和時鐘線SCL,就能夠?qū)崿F(xiàn)CPU與被控IC之間、IC與IC之間進(jìn)行雙向傳送。 s3c2440內(nèi)部有一個IIC總線接口,因此為我們連接帶有IIC通信模塊的外圍設(shè)備提供了便利。它具有四種操作模式:主設(shè)備發(fā)送模式、主設(shè)備接收模式、從設(shè)備發(fā)送模式和從設(shè)備接收模式。在這里我們只把s3c2440當(dāng)做IIC總線的主設(shè)備來使用,因此只介紹前兩種操作模式。在主設(shè)備發(fā)送模式下,它的工作流程為:首先配置IIC模式,然后把從設(shè)備地址寫入接收發(fā)送數(shù)據(jù)移位寄存器II
[單片機(jī)]
<font color='red'>IIC</font>讀寫AT24Cxx (S3C2440)
小廣播
設(shè)計資源 培訓(xùn) 開發(fā)板 精華推薦

最新單片機(jī)文章

 
EEWorld訂閱號

 
EEWorld服務(wù)號

 
汽車開發(fā)圈

 
機(jī)器人開發(fā)圈

電子工程世界版權(quán)所有 京ICP證060456號 京ICP備10001474號-1 電信業(yè)務(wù)審批[2006]字第258號函 京公網(wǎng)安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved