文章目錄
- 前言
- 一、RT-Thread工程創建
- 二、AT24C02
- 三、函數編寫
- 1.I2C_soft.c
- 2.I2C_soft.h
- 3.main.h
- 四、效果展示
- 五、資源分享
- 總結
前言
本章是基于RT-Thread studio實現軟件模擬I2C,開發板是正點原子的STM32F4探索者,使用的RT-Thread驅動是5.1.0,使用的I2C通訊芯片是存儲芯片AT24C02,本章和前面文章不同在于I2C是軟件模擬,與設備無關,所以驅動文件不會有問題,但是對于代碼開發官方文檔有些重要內容沒有提到,本文將進行補充。
一、RT-Thread工程創建
這里只需要按前文得到一個不報錯的基礎工程,因為是軟件模擬I2C,所以不需要去cubemx進行硬件配置。
然后去board.h找到I2C的定義區間,使能一個I2C型號,將SCL和SDA按你的使用的開發板引腳定義。我這里使能了I2C1,SCL接入的引腳是PB8,SDA接入的引腳是PB9,如下。
然后去設置中打開軟件模擬I2C開關,Use GPIO to soft simulate I2C感覺重復了,開不開對工程沒有影響,對于debug message開啟的話可以看到I2C通訊的工作流程。
到此,I2C工程配置完成
二、AT24C02
AT24C02是接下來用到的I2C通訊芯片,我簡單說明一下。
AT24C02 是一款由 低功耗串行電可擦除只讀存儲器(EEPROM),通過 I2C 總線進行通信。支持標準模式(100kHz)和快速模式(400kHz)。
2K 位(256 字節)存儲空間,分為 32 頁,每頁 8 字節。地址范圍:0x00~0xFF(地址低3位為頁內地址,高5位為頁面地址)。一個頁面
只能寫入8字節,超過的數據將寫入下一個頁面。
三、函數編寫
1.I2C_soft.c
先看代碼,再看講解
#include "I2C_soft.h"
#define DBG_TAG "I2C_soft"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>#define I2C1_NAME "i2c1"
#define SLAVE_ADDR 0xa0>>1//data[0]為數據地址,后面開始是寫入數據
int write_i2c1reg(rt_uint8_t *data,rt_uint8_t data_byte)
{rt_uint8_t i2c1_flag = 0;struct rt_i2c_bus_device *i2c1_bus;i2c1_bus = (struct rt_i2c_bus_device *)rt_device_find(I2C1_NAME);if(i2c1_bus == RT_NULL){LOG_D("failed to i2c1 bus find");return -1;}i2c1_flag = (rt_uint8_t)rt_i2c_master_send(i2c1_bus, SLAVE_ADDR, RT_NULL, data, data_byte);if(i2c1_flag != data_byte){LOG_D("failed to i2c1 send");return -1;}return 0;
}
//data_add為讀數據地址
int read_i2c1reg(rt_uint8_t data_add,rt_uint8_t *data,rt_uint8_t data_byte)
{rt_uint8_t i2c1_flag = 0;struct rt_i2c_bus_device *i2c1_bus;i2c1_bus = (struct rt_i2c_bus_device *)rt_device_find(I2C1_NAME);if(i2c1_bus == RT_NULL){LOG_D("failed to i2c1 bus find");return -1;}rt_i2c_master_send(i2c1_bus, SLAVE_ADDR, RT_NULL, &data_add, 1);i2c1_flag = (rt_uint8_t)rt_i2c_master_recv(i2c1_bus, SLAVE_ADDR, RT_NULL, data, data_byte);if(i2c1_flag != data_byte){LOG_D("failed to i2c1 recv");return -1;}return 0;
}
按照圖1,器件地址應該是0xa0(W)或0xa1?,最后一位為讀寫位,但是官方手冊明確說明了不包含讀寫位。如下
所以,后面的函數默認傳入的地址是不帶最后一位的7位地址,然后根據flags標志形成8位地址作為器件地址,具體操作是將輸入的地址左移1位,然后或上讀寫位成為最終地址,那么為了保證最終地址不出錯,所以我們傳入的地址就要先右移一位。
我這里使用rt_i2c_master_send和rt_i2c_master_recv寫入和讀出數據,代碼上更簡介,這兩個函數就是把rt_i2c_transfer和傳輸的消息數組指針封裝了一下。
另外對于rt_i2c_transfer函數第三個參數我覺得官網解釋有誤,num只能是1,否則就會出錯。要符合官方文檔的定義,你每次用rt_i2c_transfer只能寫入一個字節,那就效率太低了。所以最好不要用這個函數,用上面兩個函數,如果實在要用,那就記住num只能是1,和你數組元素個數無關。
當我們使用rt_i2c_master_send傳輸數據時,如果標志位flag不寫入RT_I2C_NO_START /* 無開始條件 */
,那么自動一開始發送一個起始位和一個器件地址字節和應答,后面就是一個數據字節一個應答,達到發送的數據個數后一個停止位,剛好符合圖2中AT24C02的寫入格式,所以我的寫入函數沒有問題。就是注意數組第一位是數據字節地址,后面才是寫入的數據內容。
提示
如果分開操作,把數據地址獨立出來應該如下操作。
//data_add為數據地址,data為寫入數據數組
rt_i2c_master_send(i2c1_bus, SLAVE_ADDR, RT_I2C_NO_STOP, &data_add, 1);
rt_i2c_master_send(i2c1_bus, SLAVE_ADDR, RT_I2C_NO_START, data, data_byte);
可見RT_I2C_NO_STOP會去除停止位,RT_I2C_NO_START會去除起始位和器件地址字節
對于接收函數,按照圖3的數據格式,先采用rt_i2c_master_send(i2c1_bus, SLAVE_ADDR, RT_NULL, &data_add, 1);
發送一個讀數據地址,然后使用rt_i2c_master_recv(i2c1_bus, SLAVE_ADDR, RT_NULL, data, data_byte);
將讀到的數據存入數組data中,data_byte是讀取數據字節數,rt_i2c_master_recv的flag同理。
弄清了以上這些,遇見了其他的I2C通訊芯片,只要按照它的讀寫格式,就能利用rt_i2c_master_send和rt_i2c_master_recv配置出需要的格式。
2.I2C_soft.h
#ifndef APP_I2C_SOFT_H_
#define APP_I2C_SOFT_H_#include <board.h>
//data[0]為數據地址,后面開始是寫入數據
int write_i2c1reg(rt_uint8_t *data,rt_uint8_t data_byte);
int read_i2c1reg(rt_uint8_t data_add,rt_uint8_t *data,rt_uint8_t data_byte);#endif /* APP_I2C_SOFT_H_ */
3.main.h
#include <rtthread.h>#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include "I2C_soft.h"int main(void)
{rt_uint8_t i2c1_wd[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x10};rt_uint8_t i2c1_rd[8] = {0};write_i2c1reg(i2c1_wd, 10);rt_thread_mdelay(100);read_i2c1reg(0x00,i2c1_rd, 9);rt_thread_mdelay(100);for(int i = 0;i<9;i++){rt_kprintf("i2c1 read data id 0x%x\n",i2c1_rd[i]);}read_i2c1reg(0x08,i2c1_rd, 9);rt_thread_mdelay(100);for(int i = 0;i<9;i++){rt_kprintf("i2c1 read data id 0x%x\n",i2c1_rd[i]);}while (1){rt_thread_mdelay(1000);}return RT_EOK;
}
四、效果展示
為什么是這樣效果我就不解釋了,如果你看懂了這篇文章你就知道為什么是這樣了(AT24C02默認無數據寫入空間值為0xff)
五、資源分享
通過網盤分享的文件:I2C_soft.zip
鏈接: https://pan.baidu.com/s/1k1P0mUaXDR7jJ6dwgJJ7QQ?pwd=iims 提取碼: iims
總結
對于軟件模擬的I2C好處是兼容性好,移植容易,對硬件設計要求不高,缺點就是傳輸速率很低,效率不高,占用系統資源過大。我看了一下,好像RT-Thread并沒有設計硬件I2C驅動。另外RT-Thread可以安裝AT24C02的軟件包,可以嘗試使用一下。