最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語言軟件iic虛擬總線中間層設(shè)計(jì)詳解

 更新時(shí)間:2023年01月30日 11:33:22   作者:MacRsh  
這篇文章主要為大家介紹了C語言軟件iic虛擬總線中間層設(shè)計(jì)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

簡介

mr-soft-iic 模塊為 mr-library 項(xiàng)目下的可裁剪模塊,以C語言編寫,可快速移植到各種平臺(tái)(主要以嵌入式mcu為主)。 mr-soft-iic 模塊通過 io 模擬實(shí)現(xiàn) iic 協(xié)議。

IIC-協(xié)議

SPI 一般為一主多從設(shè)計(jì)。由2根線組成:CLK(時(shí)鐘)、SDA(數(shù)據(jù))。

接線方式

主機(jī)從機(jī)
CLKCLK
SDASDA

主機(jī)從機(jī)一 一對應(yīng)相接。

總線

IIC 通過地址碼識(shí)別設(shè)備,一條 IIC 總線最多支持掛載127個(gè)設(shè)備,通常速率為100kbit/s400kbit/s,由于SDA設(shè)置為開漏模式,因此雙向通信時(shí)需外置上拉電阻。

工作本質(zhì)

我們可以看到CLKSDA都有一個(gè)上拉電阻,而CLKSDA都為開漏(OUT-OD)下,所以只有一個(gè)下拉的MOS可以控制,因此只有下拉高阻狀態(tài)。當(dāng)高阻狀態(tài)時(shí)線上電平因?yàn)樯侠娮璧拇嬖谒詾閂CC,而下拉狀態(tài)時(shí),因?yàn)镸OS對地,所以線上電平為GND。當(dāng)主機(jī)主動(dòng)控制時(shí),就可以完成寫入的操作,當(dāng)需要讀取時(shí),只需置高阻,等待從機(jī)主動(dòng)拉低,即可完成雙向通信。

虛擬總線(中間層)設(shè)計(jì)

首先 IIC 總線的CLKSDA 這2條線是不會(huì)變動(dòng)的,所以我們可以把這部分單獨(dú)設(shè)計(jì)為iic-bus,IIC總線需要知道當(dāng)前有哪個(gè)設(shè)備擁有IIC總線的使用權(quán),為了防止出現(xiàn)搶占還需要配置一個(gè)互斥鎖。

struct mr_soft_iic_bus
{
  void (*set_clk)(mr_uint8_t level);		// 操作 CLK 的函數(shù)指針
  void (*set_sda)(mr_uint8_t level);		// 操作 SDA 的函數(shù)指針
  mr_uint8_t (*get_sda)(void);				// 讀取 SDA 的函數(shù)指針
  struct mr_soft_iic *owner;					// 當(dāng)前該總線的所有者
  mr_uint8_t lock;									// 互斥鎖
};

IIC設(shè)備唯一獨(dú)有的只有設(shè)備addr,所以我們把這部分定義為iic-device。IIC設(shè)備還需要知道自己歸屬于哪條IIC總線。

struct mr_soft_iic
{
  mr_uint8_t addr;		// 設(shè)備地址
  struct mr_soft_iic_bus *bus;		// 該設(shè)備歸屬的總線
};

當(dāng)創(chuàng)建了一條iic-bus,一個(gè)iic-device后我們需要一個(gè)掛載函數(shù),即將iic-device掛載到iic-bus

void mr_soft_iic_attach(struct mr_soft_iic *iic, struct mr_soft_iic_bus *iic_bus)
{
  iic->bus = iic_bus;
}

那么由于是虛擬總線設(shè)計(jì),當(dāng)我們要開始傳輸前需要先去獲取總線。

mr_err_t mr_soft_iic_bus_take(struct mr_soft_iic *iic)
{
  mr_uint8_t iic_bus_lock;
  mr_base_t level;
  /* check iic-bus owner */
  if(iic->bus->owner != iic)
  {
    /* check mutex lock */
    do {
      iic_bus_lock = iic->bus->lock;
    } while (iic_bus_lock != MR_UNLOCK);
    /* lock mutex lock */
    iic->bus->lock = MR_LOCK;
    /* exchange iic-bus owner */
    iic->bus->owner = iic;
  }
  else
  {
    /* lock mutex lock */
    iic->bus->lock = MR_LOCK;
  }
  return MR_EOK;
}

當(dāng)我們使用完畢后需要釋放總線

mr_err_t mr_soft_iic_bus_release(struct mr_soft_iic *iic)
{
  /* check spi-bus owner */
  if(iic->bus->owner == iic)
  {
    iic->bus->lock = MR_UNLOCK;
    return MR_EOK;
  }
  return -MR_ERROR;
}

到此其實(shí)虛擬總線已經(jīng)設(shè)計(jì)完畢,設(shè)備需要使用僅需通過掛載 、獲取、釋放 三步操作即可,其余操作交由中間層處理。 為調(diào)用接口的統(tǒng)一,設(shè)計(jì)iic-msg

struct mr_soft_iic_msg
{
  mr_uint8_t read_write;		// 讀寫模式:IIC_WR/ IIC_RD
  mr_uint8_t addr;		// 寫入/讀取 地址							
  mr_uint8_t *buffer;		// 數(shù)據(jù)地址
  mr_size_t size;		// 數(shù)據(jù)數(shù)量
};

然后通過transfer函數(shù)統(tǒng)一調(diào)用接口。

mr_err_t mr_soft_iic_transfer(struct mr_soft_iic *iic, struct mr_soft_iic_msg msg)
{
  mr_err_t ret;
  /* check msg */
  if(msg.read_write > IIC_RD)
    return -MR_ERROR;
  if(msg.addr == MR_NULL)
    return -MR_EINVAL;
  if(msg.buffer == MR_NULL || msg.size == MR_NULL)
    return MR_EOK;
  /* take iic-bus */
  ret = mr_soft_iic_bus_take(iic);
  if(ret != MR_EOK)
    return ret;
  /* send iic device and register address */
  mr_soft_iic_bus_start(iic->bus);
  mr_soft_iic_bus_send(iic->bus, iic->addr << 1);
  mr_soft_iic_bus_send(iic->bus, msg.addr);
  if(msg.read_write == IIC_WR)
  {
    /* send iic start and device write cmd */
    mr_soft_iic_bus_start(iic->bus);
    mr_soft_iic_bus_send(iic->bus, iic->addr << 1);
    /* send */
    while(msg.size)
    {
      mr_soft_iic_bus_send(iic->bus,*msg.buffer);
      ++ msg.buffer;
      -- msg.size;
    }
    /* send iic stop */
    mr_soft_iic_bus_stop(iic->bus);
  }
  else
  {
    /* send iic start and device write cmd */
    mr_soft_iic_bus_start(iic->bus);
    mr_soft_iic_bus_send(iic->bus, iic->addr << 1 | 0x01);
    /* receive */
    while(msg.size)
    {
      *msg.buffer = mr_soft_iic_bus_receive(iic->bus, (msg.size == 0));
      ++ msg.buffer;
      -- msg.size;
    }
    /* send iic stop */
    mr_soft_iic_bus_stop(iic->bus);
  }
  /* release iic-bus */
  mr_soft_iic_bus_release(iic);
  return MR_EOK;
}

使用示例

/* -------------------- 配置 -------------------- */
/* 創(chuàng)建一條 iic 總線 */
struct mr_soft_iic_bus iic_bus;
/* 適配 iic 總線接口 */
void set_clk(mr_uint8_t level)
{
  GPIO_WriteBit(GPIOA,GPIO_Pin_0,level);
}
void set_sda(mr_uint8_t level)
{
  GPIO_WriteBit(GPIOA,GPIO_Pin_1,level);
}
mr_uint8_t get_sda(void)
{
  return GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_1);
}
/* 配置 iic 總線 */
struct mr_soft_iic_bus iic_bus;
iic_bus.set_clk = set_clk;
iic_bus.set_sda = set_sda;
iic_bus.get_sda = get_sda;
iic_bus.lock = MR_UNLOCK;
iic_bus.owner = MR_NULL;
/* 創(chuàng)建一個(gè) iic 設(shè)備 */
struct mr_soft_iic iic_device;
/* 配置 iic 設(shè)備 */
iic_device.addr = 0x31;         // iic 設(shè)備地址
/* -------------------- 使用 -------------------- */
int main(void)
{
    /* 需要發(fā)送的數(shù)據(jù) */
    mr_uint8_t buffer[10]={0,1,2,3,4,5,6,7,8,9};
    /* 初始化 gpio */
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    /* 掛載 iic 設(shè)備到 iic 總線 */
    mr_soft_iic_attach(&iic_device,&iic_bus);
    /* 創(chuàng)建 iic 消息 */
    struct mr_soft_iic_msg iic_msg;
    iic_msg.addr = 0x55;            // 寫入/讀取 地址
    iic_msg.buffer = buffer;        // 數(shù)據(jù)地址
    iic_msg.size = 10;              // 數(shù)據(jù)數(shù)量
    iic_msg.read_write = IIC_WR;    // 只寫模式
    /* 發(fā)送消息 */
    mr_soft_iic_transfer(&iic_device,iic_msg);
}

剩余底層代碼位于開源代碼中,請下載開源代碼。

開源代碼倉庫鏈接 gitee.com/chen-fanyi/…

路徑:master/mr-library/ device / mr_soft_iic

請仔細(xì)閱讀README.md ?。。。?!

以上就是C語言軟件iic虛擬總線中間層設(shè)計(jì)詳解的詳細(xì)內(nèi)容,更多關(guān)于C語言軟件iic虛擬總線中間層的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 淺談C++ 虛函數(shù)

    淺談C++ 虛函數(shù)

    這篇文章主要介紹了C++ 虛函數(shù)的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)c++,感興趣的朋友可以了解下
    2020-09-09
  • C語言實(shí)現(xiàn)對文件進(jìn)行操作的示例詳解

    C語言實(shí)現(xiàn)對文件進(jìn)行操作的示例詳解

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)對文件進(jìn)行操作的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)C語言有一定的幫助,需要的可以參考一下
    2023-04-04
  • C++類和對象基礎(chǔ)詳解

    C++類和對象基礎(chǔ)詳解

    類是創(chuàng)建對象的模板,一個(gè)類可以創(chuàng)建多個(gè)對象,每個(gè)對象都是類類型的一個(gè)變量;創(chuàng)建對象的過程也叫類的實(shí)例化。每個(gè)對象都是類的一個(gè)具體實(shí)例(Instance),擁有類的成員變量和成員函數(shù)
    2021-08-08
  • C++中關(guān)于委派(Delegates)的實(shí)現(xiàn)示例

    C++中關(guān)于委派(Delegates)的實(shí)現(xiàn)示例

    這篇文章主要介紹了C++中關(guān)于委派(Delegates)的實(shí)現(xiàn)示例,針對C++11的一些新特性進(jìn)行講解,需要的朋友可以參考下
    2015-07-07
  • Qt處理焦點(diǎn)事件(獲得焦點(diǎn),失去焦點(diǎn))

    Qt處理焦點(diǎn)事件(獲得焦點(diǎn),失去焦點(diǎn))

    本文主要介紹了Qt處理焦點(diǎn)事件(獲得焦點(diǎn),失去焦點(diǎn)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-12-12
  • 基于C++中sprintf的錯(cuò)誤總結(jié)詳解

    基于C++中sprintf的錯(cuò)誤總結(jié)詳解

    本篇文章是對C++中sprintf的錯(cuò)誤進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++中線性代數(shù)計(jì)算Eigen庫的使用教程詳解

    C++中線性代數(shù)計(jì)算Eigen庫的使用教程詳解

    Eigen是一個(gè)基于線性代數(shù)的C++模板庫,主要用于矩陣、向量、數(shù)值求解和相關(guān)算法,本文主要為大家簡單聊聊Eigen庫的使用,希望對大家有所幫助
    2023-12-12
  • C語言實(shí)現(xiàn)單鏈表的基本功能詳解

    C語言實(shí)現(xiàn)單鏈表的基本功能詳解

    鏈表是一個(gè)結(jié)構(gòu)體實(shí)現(xiàn)的一種線性表,它只能從前往后,不可以從后往前,在實(shí)現(xiàn)單鏈表的操作時(shí),需要用指針來操作。本文主要介紹了實(shí)現(xiàn)單鏈表的基本功能的代碼示例,具有一定價(jià)值,感興趣的同學(xué)可以學(xué)習(xí)一下
    2021-11-11
  • C++指針與數(shù)組:指針詳解

    C++指針與數(shù)組:指針詳解

    本文從初學(xué)者的角度,深入淺出地講解C++中的指針、數(shù)組指針,對最?;煜囊脗鬟f、值傳遞和指針傳遞做了區(qū)處,需要的朋友可以參考下
    2021-09-09
  • C語言 風(fēng)靡一時(shí)的黃金礦工游戲?qū)崿F(xiàn)流程詳解

    C語言 風(fēng)靡一時(shí)的黃金礦工游戲?qū)崿F(xiàn)流程詳解

    《黃金礦工》是一款非常經(jīng)典的游戲。在游戲中,玩家通過不斷挖礦,獲取金子,最終能夠闖入下一關(guān)。在這個(gè)過程中,會(huì)不斷有巖石、煙霧、老鼠來搗亂,甚至還會(huì)出現(xiàn)扛著炸藥包的小老鼠,玩家必須戰(zhàn)勝它們,才能進(jìn)入更深的礦坑
    2021-11-11

最新評論

垣曲县| 乡宁县| 遂昌县| 资中县| 绥棱县| 资阳市| 通化县| 乌兰察布市| 鄂伦春自治旗| 赣州市| 贵港市| 平潭县| 崇左市| 广平县| 图们市| 祁东县| 韶山市| 佛山市| 合山市| 扎兰屯市| 策勒县| 缙云县| 大田县| 泽普县| 富平县| 清丰县| 柏乡县| 永登县| 夹江县| 梨树县| 泉州市| 平武县| 开江县| 甘泉县| 台北市| 佛坪县| 灌云县| 绿春县| 中山市| 贡山| 隆子县|