日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

外设驱动库开发笔记3:AD527x系列数字电位器驱动

發(fā)布時(shí)間:2024/7/23 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 外设驱动库开发笔记3:AD527x系列数字电位器驱动 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在一些時(shí)候我們需要使用精度更高的數(shù)字電位器來實(shí)現(xiàn)我們的應(yīng)用。我們經(jīng)常使用AD527x系列數(shù)字電位器來實(shí)現(xiàn)這類應(yīng)用。在通常情況下,AD527x系列數(shù)字電位器完全能夠滿足要求。為了減少重復(fù)工作,在這里我們將分系并實(shí)現(xiàn)AD527x系列數(shù)字電位器的驅(qū)動。

1、功能概述

我們在這里討論的AD527x系列數(shù)字電位器包括:AD5270、AD5271、AD5272和AD5724,他們的功能是相同的,主要在數(shù)字位或通訊接口上有寫差別。

AD527x系列數(shù)字電位器集業(yè)界領(lǐng)先的可變電阻性能與非易失性存儲器(NVM)于一體,這些器件的端到端電阻容差誤差小于1%,并提供50次可編程(50-TP)存儲器。將電阻值編程寫入50-TP存儲器之前,可進(jìn)行無限次調(diào)整。這些器件不需要任何外部電壓源來幫助熔斷熔絲,并提供50次永久編程的機(jī)會。在50-TP激活期間,一個(gè)永久熔斷熔絲指令會將游標(biāo)位置固定。

對于AD527x系列數(shù)字電位器,皆有一個(gè)16位寬的移位寄存器,一切對AD527x系列數(shù)字電位器的操作都是同過這個(gè)以為寄存器完成的。移位寄存器的格式如下所示。

該16位移位寄存器由兩個(gè)應(yīng)設(shè)為0的未用位、四個(gè)控制位和10個(gè)RDAC數(shù)據(jù)位組成,并且數(shù)據(jù)以MSB優(yōu)先方式加載。對于AD5271和AD5274只有8位數(shù)據(jù),則最后兩位會被忽略。四個(gè)控制位決定軟件命令的功能,具體的功能碼如下所示:

我們對AD527x系列數(shù)字電位器的操作就是以這10個(gè)命令為基礎(chǔ)的,事實(shí)上NOP命令是可以忽略的,因?yàn)樗粫腥魏尾僮靼l(fā)生。其中有命令5和命令7需要說一下。

命令7則用于設(shè)置控制寄存器。控制寄存器僅后4為有效。C0用于設(shè)置50-TP的編程使能。C1用于設(shè)置RDAC的寫保護(hù)。C2用于電阻容差校準(zhǔn)。C3則是指示50-TP的編程狀態(tài)。具體結(jié)構(gòu)如下:

而命令5用于設(shè)置讀出的50-TP的內(nèi)容。就是說這條命令用于設(shè)置我下次讀取50-TP時(shí)究竟是那一條的類容,因?yàn)榭偣灿?0條。具體的取值如下:

共50條需要50個(gè)編碼,使用了D0到DF5位,編號1開始一一對應(yīng)50個(gè)編程位置。

2、驅(qū)動設(shè)計(jì)與實(shí)現(xiàn)

我們已經(jīng)了解了AD527x系列數(shù)字電位器的基本情況,接下來我們就設(shè)計(jì)并實(shí)現(xiàn)AD527x系列數(shù)字電位器的驅(qū)動。?

2.1、對象定義

同樣的我們將基于對象操作的思想來設(shè)計(jì)AD527x系列數(shù)字電位器的驅(qū)動。既如此,我們首先必須要定義AD527x系列數(shù)字電位器對象。

2.1.1、抽象對象類型

在抽象出AD527x系列數(shù)字電位器對象類型之前,我們先來分析一下AD527x系列數(shù)字電位器。一個(gè)對象最起碼包含屬性和操作兩個(gè)特性,我們來分析一下AD527x系列數(shù)字電位器對象包含有那些屬性和操作。

對于AD527x系列數(shù)字電位器包含有多種器件,不同的器件在通訊接口和檔位等方面會有差別,所以我們將設(shè)備的類型作為其屬性以分辯究竟是哪種器件,進(jìn)而分辨接口和檔位差異。游標(biāo)的當(dāng)前位置以及控制寄存器的值我們也將其設(shè)置為屬性以確定設(shè)備當(dāng)前的狀態(tài)。當(dāng)設(shè)備時(shí)I2C接口時(shí),需要有一個(gè)設(shè)備地址,所以我們將設(shè)備地址設(shè)置為屬性,這個(gè)屬性只在I2C接口模式時(shí)才起作用。而在使用SPI接口的器件時(shí),需要一個(gè)片選信號,所以我們將操作片選信號作為AD527x系列數(shù)字電位器的一個(gè)操作,這個(gè)操作只在使用SPI接口的器件時(shí)才起作用。此外,AD527x系列數(shù)字電位器對象還需要實(shí)現(xiàn)數(shù)據(jù)的發(fā)送與接收以及操作過程中必要的延時(shí)函數(shù),我們均將其作為對象的操作。據(jù)上述分析我們可以抽象出AD527x系列數(shù)字電位器對象類型如下:

/*定義用于SPI接口的對象類型*/ typedef struct AD527xObject {AD527xType type; //設(shè)備類型uint8_t devAddress; //設(shè)備地址,用于I2C接口uint8_t conreg; //控制寄存器uint16_t rdac; //游標(biāo)寄存器現(xiàn)值void (*ChipSelcet)(AD527xCSType en); //片選信號,用于SPI接口void (*Receive)(struct AD527xObject *rx,uint8_t *rData,uint16_t rSize);void (*Transmit)(struct AD527xObject *rx,uint8_t *wData,uint16_t wSize);void (*Delayms)(volatile uint32_t nTime); ??????//ms延時(shí)操作指針 }AD527xObjectType;

2.1.2、對象的初始化

一個(gè)對象我們需要對其初始化才能使用,初始化函數(shù)至少包含有2方面內(nèi)容:一是為對象變量賦必要的初值;二是檢查這些初值是否是有效的。特別是一些操作指針錯(cuò)誤的話可能產(chǎn)生嚴(yán)重的后果。基于這一原則,我們設(shè)計(jì)AD527x系列數(shù)字電位器的對象初始化函數(shù)如下:

/* 初始化AD527x對象,I2C接口必須初始化devAddress,SPI接口必需初始化void (*ChipSelcet)(bool) */ void AD527xInitialization(AD527xObjectType *rx,uint8_t address,AD527xType type,AD527xReceive recieve,AD527xTransmit transmit,AD527xChipSelcet cs,AD527xDelayms delayms) {if((rx==NULL)||(recieve==NULL)||(transmit==NULL)||(delayms==NULL)){return;}if((type==AD5270)||(type==AD5271)) //使用SPI接口{if(cs==NULL) //硬件電路實(shí)現(xiàn)片選{rx->ChipSelcet=DefaultChipSelcet;}else{rx->ChipSelcet=cs;}rx->devAddress=0x00;}else //使用I2C接口{if((address==0x58)||(address==0x5C)||(address==0x5E)){rx->devAddress=address;}else if((address==0x2C)||(address==0x2E)||(address==0x2F)){rx->devAddress=(address<<1);}else{rx->devAddress=0x00;}rx->ChipSelcet=NULL;}rx->type=type;rx->conreg=0x00;rx->rdac=0x0000;rx->Receive=recieve;rx->Transmit=transmit;rx->Delayms=delayms;ReadControlRegister(rx);SetSoftShutMode(rx,SOFT_NORMAL_MODE); }

2.2、對象操作

前面我們已經(jīng)描述過,對AD527x系列數(shù)字電位器的操作命令有9個(gè)。這9個(gè)命令皆是對寄存器進(jìn)行讀寫操作的,所以我們這里將這些操作分為讀寄存器操作和寫寄存器操作,并以此設(shè)計(jì)驅(qū)動程序。

2.2.1、寫寄存器操作

首先我們需要說明寫寄存器操作是針對對象的操作函數(shù),而不是對象變量包含的操作,因?yàn)槲覀冎辉趯ο笞兞恐蟹湃胍蕾囉谕饨缙脚_的基本操作。寫寄存器操作會以回調(diào)的方式調(diào)用對象變量包含的基本操作。

因?yàn)锳D527x系列數(shù)字電位器對象包括不同接口和不同檔位的器件,所以我們設(shè)計(jì)寫寄存器操作時(shí)需要考慮AD527x系列數(shù)字電位器對象的類型。而這個(gè)類型已在初始化時(shí)賦予了對象變量。據(jù)此我們設(shè)計(jì)寫寄存器操作函數(shù)如下:

/* 寫寄存器操作 */ static void AD527xWriteRegister(AD527xObjectType *rx,uint16_t cmd) {uint8_t tData[2];tData[0]=(uint8_t)(cmd>>8);tData[1]=(uint8_t)cmd;if((rx->type==AD5270)||(rx->type==AD5271)) //SPI接口{rx->ChipSelcet(AD527xCS_ENABLE);rx->Delayms(1);}rx->Transmit(rx,tData,2);if((rx->type==AD5270)||(rx->type==AD5271)) //SPI接口{rx->Delayms(1);rx->ChipSelcet(AD527xCS_DISABLE);} }

2.2.2、讀寄存器操作

與寫寄存器操作一樣,讀寄存器操作一樣要考慮到AD527x系列數(shù)字電位器對象的類型。在使用SPI接口的對象類型種需要考慮片選信號的處理。我們設(shè)計(jì)讀寄存器操作如下:

/* 讀寄存器操作 */ static void AD527xReadRegister(AD527xObjectType *rx,uint16_t cmd,uint8_t *rData) {uint8_t tData[2];if((rx->type==AD5270)||(rx->type==AD5271)) //SPI接口{rx->ChipSelcet(AD527xCS_ENABLE);rx->Delayms(1);}rx->Transmit(rx,tData,2);rx->Receive(rx,rData,2);if((rx->type==AD5270)||(rx->type==AD5271)) //SPI接口{rx->Delayms(1);rx->ChipSelcet(AD527xCS_DISABLE);} }

2.2.3、面向命令的操作

我們已經(jīng)實(shí)現(xiàn)了對繼存存其的讀操作和寫操作,但我們并不想通過調(diào)用這兩個(gè)函數(shù)并傳遞命令來實(shí)現(xiàn)我們的應(yīng)用。所以我們將不同的操作命令所要完成的功能封裝成函數(shù),在這些函數(shù)中調(diào)用讀寫寄存器操作函數(shù)來完成。這樣使用驅(qū)動就變得更為簡便。例如我們設(shè)計(jì)讀寫RDAC的函數(shù)如下:

/* 設(shè)置AD527x游標(biāo)位置 */ void SetRDACForAd527x(AD527xObjectType *rx,uint16_t data) {uint16_t temp=0;if((rx->type==AD5271)||(rx->type==AD5274)) //256檔{temp=data>255?255:data;}else if((rx->type==AD5270)||(rx->type==AD5272)) //1024檔{temp=data>1023?1023:data;}temp=COMMAND_W_RDAC|temp;if(((rx->conreg)&0x02)!=0x02){SetControlRegister(rx,PROGRAM_RDAC_ENABLE|rx->conreg);}AD527xWriteRegister(rx,temp); }/* 讀取RDAC游標(biāo)寄存器的內(nèi)容 */ uint16_t ReadRDACFromAd527x(AD527xObjectType *rx) {uint8_t rData[2];uint16_t cmd=COMMAND_R_RDAC;AD527xReadRegister(rx,cmd,rData);rx->rdac=(rData[0]<<8)+rData[1];return rx->rdac; }

3、驅(qū)動的使用

我們已經(jīng)實(shí)現(xiàn)了AD527x系列數(shù)字電位器的驅(qū)動。接下來我們來考慮如何使用這一驅(qū)動實(shí)現(xiàn)我們的應(yīng)用。

3.1、聲明并初始化對象

我們已經(jīng)定義了AD527x系列數(shù)字電位器對象類型。所以我們先要使用對象類型聲明一個(gè)AD527x系列數(shù)字電位器對象變量。形式如下:

AD527xObjectType ad527x;

當(dāng)然,這里定義的這個(gè)對象變量還不能直接使用。我們需要使用初始化函數(shù)對這個(gè)對象變量進(jìn)行初始化。初始化函數(shù)前面已經(jīng)說過,傳遞的參數(shù)皆是與對象變量相關(guān)的。初始化函數(shù)的參數(shù)如下:

AD527xObjectType *rx,待初始化的對象變量。

uint8_t address,采用I2C接口通訊是的設(shè)備地址。

AD527xType type,對象的設(shè)備類型。

AD527xReceive recieve,數(shù)據(jù)接收函數(shù)指針。

AD527xTransmit transmit,數(shù)據(jù)發(fā)送函數(shù)指針。

AD527xChipSelcet cs,使用SPI接口通訊時(shí),片選操作函數(shù)指針。

AD527xDelayms delayms,毫秒延時(shí)操作函數(shù)指針。

對于這些參數(shù),對象變量我們已經(jīng)定義了。對象類型根據(jù)實(shí)際器件輸入即可。而設(shè)備地址在使用I2C接口時(shí)按要求輸入即可,如果是SPI接口則任意uint8_t類型的值均可。最主要的是我們需要定義幾個(gè)函數(shù),并將函數(shù)指針作為參數(shù)。這幾個(gè)函數(shù)的類型圖下:

/*定義片選信號函數(shù)指針類型*/ typedef void (*AD527xChipSelcet)(AD527xCSType en);/*定義接收數(shù)據(jù)函數(shù)指針類型*/ typedef void (*AD527xReceive)(struct AD527xObject *rx,uint8_t *rData,uint16_t rSize);/*定義發(fā)送數(shù)據(jù)函數(shù)指針類型*/ typedef void (*AD527xTransmit)(struct AD527xObject *rx,uint8_t *wData,uint16_t wSize);/*定義ms延時(shí)操作指針*/ typedef void (*AD527xDelayms)(volatile uint32_t nTime);

對于這幾個(gè)函數(shù)我們根據(jù)樣式定義就可以了,具體的操作可能與使用的硬件平臺有關(guān)系。片選操作函數(shù)只在使用SPI接口是需要定義,否則可以傳入NULL即可。具體函數(shù)定義如下:

/*定義片選信號函數(shù)*/ void AD527xCS(AD527xCSType en) {if(AD527xCS_ENABLE==en){HAL_GPIO_WritePin(GPIOF, GPIO_PIN_4, GPIO_PIN_RESET);}else{HAL_GPIO_WritePin(GPIOF, GPIO_PIN_4, GPIO_PIN_SET);} }/*定義接收數(shù)據(jù)函數(shù)*/ void AD527xReceiveData(struct AD527xObject *rx,uint8_t *rData,uint16_t rSize) {HAL_SPI_Receive (&hspi, rData, rSize, 1000); }/*定義發(fā)送數(shù)據(jù)函數(shù)*/ void AD527xTransmitData(struct AD527xObject *rx,uint8_t *wData,uint16_t wSize) {HAL_SPI_Transmit (&hspi, wData, wSize, 1000); }

對于延時(shí)函數(shù)我們可以采用各種方法實(shí)現(xiàn)。我們曹勇的STM32平臺和HAL庫則可以直接使用HAL_Delay()函數(shù)。于是我們可以調(diào)用初始化函數(shù)如下:

AD527xInitialization(&ad527x,0x00,AD5270,AD527xReceiveData,AD527xTransmitData,AD527xCS,HAL_Delay);

這是使用SPI接口器件的初始化操作,使用I2C接口的初始化操作類似次操作即可。

3.2、基于對象進(jìn)行操作

我們已經(jīng)定義了對象變量并對其進(jìn)行了初始化。接下來我們就要看看如何操作對象得到我們想要的結(jié)果。

我們在前面已經(jīng)根據(jù)操作命令做了封裝,所以我們需要什么養(yǎng)的功能只需要調(diào)用相應(yīng)的函數(shù)就可以了。如我們想要設(shè)置RDAC為最大值則:

SetValueToAd5270(&ad527x,1023);

其中第1個(gè)參數(shù)為要操作的對象指針,第2個(gè)參數(shù)為要設(shè)置的游標(biāo)位置值。

4、應(yīng)用總結(jié)

我們已經(jīng)實(shí)現(xiàn)AD527x系列數(shù)字電位器的驅(qū)動及基于此驅(qū)動的應(yīng)用,得到了與我們預(yù)期一致的結(jié)果,說明驅(qū)動的設(shè)計(jì)時(shí)符合需求的。

在使用驅(qū)動時(shí)需注意,采用I2C接口的器件需要考慮設(shè)備地址的問題。設(shè)備地址由ADDR引腳的狀態(tài)決定。由三種取值如下:

在使用驅(qū)動時(shí)需注意,采用SPI接口的器件需要考慮片選操作的問題。如果片選信號是通過硬件電路來實(shí)現(xiàn)的,我們在初始化時(shí)給其傳遞NULL值。如果是軟件操作片選則傳遞我們編寫的片選操作函數(shù)。

源碼地址GitHub:https://github.com/foxclever/ExPeriphDriver

歡迎關(guān)注:

總結(jié)

以上是生活随笔為你收集整理的外设驱动库开发笔记3:AD527x系列数字电位器驱动的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 老熟妇高潮一区二区高清视频 | 日韩字幕 | 成年人看的黄色 | 国产一级淫片a | 国产男女猛烈无遮挡免费视频动漫 | 亚洲视频123| 黑人vs亚洲人在线播放 | 光明影院手机版在线观看免费 | 国产视频h | 学生调教贱奴丨vk | 91在线免费视频观看 | 亚洲第一二区 | www麻豆视频| 蜜桃视频在线观看一区 | 麻豆av一区 | 露脸啪啪清纯大学生美女 | 超碰中文字幕 | 黑人与日本少妇 | 欧美成人极品 | 无码少妇一区二区三区 | 97操 | 嫩草影院懂你的影院 | 久草视频中文在线 | 日韩女人性猛交 | 久久网伊人 | 18久久久| 日本天天操 | 国产一区自拍视频 | 成人免费看类便视频 | 国产激情精品一区二区三区 | 一区二区三区四区在线免费观看 | 女女互慰吃奶互揉调教捆绑 | 日韩和一区二区 | 无码人妻精品一区二区三应用大全 | 2018av在线| 国产亚洲精品久久久久久 | 日韩欧美无 | 日韩有码第一页 | 国产精品久久综合视频 | free性中国hd国语露脸 | 女女调教被c哭捆绑喷水百合 | 国产精品久久久久久久久久久久久久久久久久 | 丁香婷婷一区二区三区 | 91插插插插插 | 台湾佬美性中文娱乐 | 无码少妇精品一区二区免费动态 | 欧美久久久精品 | 精品无码av一区二区三区不卡 | 任我爽在线 | 国产片网址 | 亚洲一区二区在线播放 | 久久午夜免费视频 | 无罩大乳的熟妇正在播放 | 夜夜操狠狠干 | 美女91网站| 国产乱了高清露脸对白 | 国产高清第一页 | 性——交——性——乱免费的 | 国产熟妇另类久久久久 | 国产欧美日韩在线播放 | 我和岳m愉情xxxⅹ视频 | 亚洲综合另类小说 | aa黄色片 | 亚洲国产综合一区 | 亚洲免费观看高清在线观看 | 日本一区视频在线播放 | 亚洲精品国偷拍自产在线观看蜜桃 | 国产稀缺精品盗摄盗拍 | 男人日女人逼 | 51国产偷自视频区视频 | 国产欧美日韩精品在线观看 | 免费看黄色的网站 | 成人免费看高清电影在线观看 | 少妇被又大又粗又爽毛片久久黑人 | 六月丁香婷婷激情 | 国产一级免费片 | 日韩在线视频免费 | 黄色片在线免费看 | 欧美老女人xx | 毛片在线视频观看 | 澳门黄色录像 | 国产一区二 | 一级片99 | 99久久精品国产成人一区二区 | 91免费视频入口 | 日韩一级网站 | 亚洲一区二区人妻 | 国产视频一区二区在线播放 | 久久永久免费视频 | 欧美日韩国产亚洲沙发 | 视频在线播 | 午夜视频观看 | 美女啪啪国产 | 午夜小视频在线 | 亚洲第一第二区 | 一本色道久久综合无码人妻 | 黄色精品视频在线观看 | 最新精品在线 | 一级伦理片 |