免费电子商务网站模板,男女做那个的视频网站,wordpress商城 微信支付宝,企业网址在产品设计过程中#xff0c;很多时候都会用到ADC器件#xff0c;而在一些特殊场合还需要一些特别的ADC器件。我们在这篇中将讨论常用于医疗器件方面的#xff0c;DDC114这款电流输入ADC#xff0c;并为其设计一个驱动程序。
1、功能概述 模数转换器DDC114是一款电流输入型… 在产品设计过程中很多时候都会用到ADC器件而在一些特殊场合还需要一些特别的ADC器件。我们在这篇中将讨论常用于医疗器件方面的DDC114这款电流输入ADC并为其设计一个驱动程序。
1、功能概述 模数转换器DDC114是一款电流输入型ADC通过对微小电流信号采用电荷积分的方式进行模数转换。包括4路输入每路输入有2路积分电容有2路AD转换器每2路输入共用1个AD转换器。其内部结构框图如下 DDC114采用48脚QFN封装其量程范围、数据格式、转换周期、操作模式等都是通过配置硬件引脚来实现配置的。其封装样式及引脚定义如下 DDC114通过SPI接口输出数字化的结果该SPI接口由一组数据时钟(DCLK)一个有效数据引脚(DVALID)一组串行数据输出引脚(DOUT)和一组串行数据输入引脚(DIN)组成。DDC114电流积分型AD芯片各路交叉积分与转换积分与转换过程以及数据输出基本是独立进行的。DIN只在多个转换器级联时使用否则应该绑定到DGND。当移位寄存器包含有效数据时DVALID输出变低。相应的逻辑时序如下 DDC114存在连续模式和非连续模式两种。当积分时间大于数据转换时间时就切换到了连续模式当积分时间小于数据转换时间时就转换到了非连续模式。有关连续与非连续模式的所需时钟周期如下 为了获得最好的噪声抑制特性一般来说我们需要将CONV转换信号与CLK时钟的上升沿同步。
2、驱动设计与实现 我们已经了解了DDC114电流输入型ADC的基本特性接下来我们就依据这些特性和要求实现DDC114电流输入型ADC的驱动程序。
2.1、对象定义 与前面一样我们依然是基于对象的思想来实现DDC114电流输入型ADC的驱动。所以我们首先来考虑DDC114电流输入型ADC作为对象的基本属性和操作。 首先我们来考虑DDC114对象的属性我们使用DDC114的目的就是获取各通道的数据所以我们将当前时刻的数据作为属性记录下来。数据格式虽然是通过硬件管脚来设置的但在不同的数据格式下解析数据的方式也是不一样的所以我们将当前配置的数据格式当作属性记录下来。同样的不同数据格式下量程和零点的设置也是不一样的所以我你们将其作为属性记录下来方便完成数据解析。我们知道DDC114连续工作时需要控制转换信号CONV我们需要记录他每一时刻的状态以便控制CONV信号的切换所以我们将器状态也定义为对象的属性。 而DDC114对象所需要进行的基本操作主要有控制CONV信号、控制RESET信号、控制TEST信号、获取DVALID状态并从SPI获取这些操作都依赖于具体的平台所以我们将其定义为对象的操作这样可以通过函数指针的方式方便操作。还有基于时序控制的需要我们需要微秒延时函数而延时函数也依赖于具体的软硬件平台所以我们将其定义为对象的操作。综上所述我们可以定义DDC114的对象类型如下
/*定义DDC114对象类型*/
typedef struct Ddc114Object {uint32_t dCode[4];Ddc114PinSetType convStatus;Ddc114FormatType format; //数据输出格式uint32_t codeRange; //输出量程编码uint32_t codeZero; //输出零点编码void (*GetDatas)(uint8_t *rData,uint16_t rSize);uint8_t (*GetValid)(void);void (*SetConv)(Ddc114PinSetType conv);void (*SetReset)(Ddc114PinSetType reset);void (*SetTest)(Ddc114PinSetType test);void (*Delayus)(volatile uint32_t nTime); //实现us延时操作
}Ddc114ObjectType;我们定义了DDC114的对象类型这样我们就可以很容易得到我们想要的DDC114对象变量。但是每个对象都是独一无二的所以我们需要一个初始化对象变量的过程所以我们考虑实现一个DDC114对象变量的初始化函数。而需要初始化的就是对象的属性和操作据此我们定义DDC114对象变量的初始化函数如下
/*DDC114对象初始化*/
void Ddc114Initialization(Ddc114ObjectType *ddc, //DDC114对象变量Ddc114FormatType format, //数据输出格式DDC114GetDatas getDatas, //获取测量数据函数指针DDC114GetValid getValid, //数据有效性状态获取函数指针DDC114SetConv conv, //转换设置函数指针DDC114SetReset reset, //复位操作函数指针DDC114SetTest test, //测试模式操作函数指针DDC114Delayus delayus //微秒延时函数指针)
{if((ddcNULL)||(getDatasNULL)||(getValidNULL)||(convNULL)||(resetNULL)||(testNULL)||(delayusNULL)){return ;}ddc-GetDatasgetDatas;ddc-GetValidgetValid;ddc-SetConvconv;ddc-SetResetreset;ddc-SetTesttest;ddc-Delayusdelayus;ddc-formatformat;if(formatDDC114_OUT20){ddc-codeRange1048575;ddc-codeZero4096;}else{ddc-codeRange65535;ddc-codeZero256;}for(int i0;i4;i){ddc-dCode[i]ddc-codeZero;}ddc-SetTest(DDC114_Pin_Reset);ddc-SetReset(DDC114_Pin_Reset);ddc-Delayus(100);ddc-SetReset(DDC114_Pin_Set);ddc-convStatusDDC114_Pin_Reset;ddc-SetConv(ddc-convStatus);
}2.2、对象操作 我们对DDC114要进行哪些操作呢复位、测试、获取状态等都是我们可以进行的操作但最重要的还是从DDC114获取转换数据。当DDC114的数据准备好之后就会将DVALID信号拉低检测到DVALID信号就可以通过SPI端口获取数据。DDC114通过SPI端口一次性传送4个通道的数据根据数据格式的不同分别传送80位或者64位。其操作时序如下图所示 根据上述的描述及时序图我们可以编写获取DDC114转换数据的函数如下
/*DDC114获取各通道的转换数据*/
void Ddc114GetDataCode(Ddc114ObjectType *ddc)
{uint8_t rData[10];uint16_t timeOut0;if(ddc-convStatusDDC114_Pin_Reset){ddc-convStatusDDC114_Pin_Set;}else{ddc-convStatusDDC114_Pin_Reset;}ddc-SetConv(ddc-convStatus);while((ddc-GetValid())(timeOut500)){timeOut;}if(ddc-format DDC114_OUT20){ddc-GetDatas(rData,10);}else{ddc-GetDatas(rData,8);}Ddc114ParseDatas(ddc,rData);
}我们读到了DDC114的输出数据后是一个80位或者64位的数据流。我们感兴趣的是各个通道的转换数据所以我们还需要对数据进行解析。而各通道转换数据的格式如下 我们根据设定的数据格式以及读取的数据位可以解析得到各个通道的转换值。
/*解析从DDC114读取的数据*/
static void Ddc114ParseDatas(Ddc114ObjectType *ddc,uint8_t *rData)
{uint32_t tCode[10]{0};if(ddc-formatDDC114_OUT20){for(int i0;i10;i){tCode[i](uint32_t)(rData[i]);}ddc-dCode[0]((tCode[7]0x0F)16)(tCode[8]8)tCode[9];ddc-dCode[1](tCode[5]12)(tCode[6]4)((tCode[7]0xF0)4);ddc-dCode[2]((tCode[2]0x0F)16)(tCode[3]8)tCode[4];ddc-dCode[3](tCode[0]12)(tCode[1]4)((tCode[2]0xF0)4);}else{for(int i0;i8;i){tCode[i](uint32_t)rData[i];}ddc-dCode[0](tCode[6]8)tCode[7];ddc-dCode[1](tCode[4]8)tCode[5];ddc-dCode[2](tCode[2]8)tCode[3];ddc-dCode[3](tCode[0]8)tCode[1];}
}3、驱动的使用 我们已经设计并实现了DDC114电流输入型ADC的驱动程序。接下来我们将简单的说明如何使用这一驱动并设计一个简单的示例验证这一驱动程序的正确性。
3.1、声明并初始化对象 我们是基于对象设计的DDC114电流输入型ADC的驱动程序所以在使用驱动时我们需要先声明一个对象变量然后基于该对象变量来实现具体的对象操作。我们先声明对象如下
Ddc114ObjectType ddc;声明了这个对象变量之后我们还需要使用初始化函数对其进行初始化方可使用。这一初始化函数拥有8个参数
Ddc114ObjectType *ddc, //DDC114对象变量
Ddc114FormatType format, //数据输出格式
DDC114GetDatas getDatas, //获取测量数据函数指针
DDC114GetValid getValid, //数据有效性状态获取函数指针
DDC114SetConv conv, //转换设置函数指针
DDC114SetReset reset, //复位操作函数指针
DDC114SetTest test, //测试模式操作函数指针
DDC114Delayus delayus //微秒延时函数指针第一个参数为所要初始化的对象变量。第二个参数是数据格式根据具体的应用设置我们这里是将它设置为20数据的格式。主要的实现的是后面6个函数指针它们都是用于实现DDC114在具体的应用平台的操作函数。原型定义如下
typedef void (*DDC114GetDatas)(uint8_t *rData,uint16_t rSize);
typedef uint8_t (*DDC114GetValid)(void);
typedef void (*DDC114SetConv)(Ddc114PinSetType conv);
typedef void (*DDC114SetReset)(Ddc114PinSetType reset);
typedef void (*DDC114SetTest)(Ddc114PinSetType test);
typedef void (*DDC114Delayus)(volatile uint32_t nTime); //实现us延时操作在使用前我们先来实现这6个面向平台的操作接口函数具体实现如下
/* 读取数据 */
static void GetDatasFromDDC(uint8_t *rData,uint16_t rSize)
{HAL_SPI_Receive(hspi1, rData, rSize, 1);
}/*读取有效引脚*/
static uint8_t ReadValidPin(void)
{return HAL_GPIO_ReadPin(DDC_DVALID_GPIO_Port,DDC_DVALID_Pin);
}/*设置转换引脚*/
static void SetConvPin(Ddc114PinSetType conv)
{if(convDDC114_Pin_Reset){HAL_GPIO_WritePin(DDC_CONV_CTL_GPIO_Port, DDC_CONV_CTL_Pin, GPIO_PIN_RESET);return;}HAL_GPIO_WritePin(DDC_CONV_CTL_GPIO_Port, DDC_CONV_CTL_Pin, GPIO_PIN_SET);return;
}/*设置复位引脚*/
static void SetResetPin(Ddc114PinSetType reset)
{if(resetDDC114_Pin_Reset){HAL_GPIO_WritePin(DDC_RESET_GPIO_Port, DDC_RESET_Pin, GPIO_PIN_RESET);return;}HAL_GPIO_WritePin(DDC_RESET_GPIO_Port, DDC_RESET_Pin, GPIO_PIN_SET);return;
}/*设置测试引脚*/
static void SetTestPin(Ddc114PinSetType test)
{if(testDDC114_Pin_Reset){HAL_GPIO_WritePin(DDC_TEST_GPIO_Port, DDC_TEST_Pin, GPIO_PIN_RESET);return;}HAL_GPIO_WritePin(DDC_TEST_GPIO_Port, DDC_TEST_Pin, GPIO_PIN_SET);return;
}而延时函数则用我们在STM32平台统一使用的微秒延时函数。定义了这些函数后我们就可以初始化对象变量如下
/*DDC114对象初始化*/Ddc114Initialization(ddc, //DDC114对象变量DDC114_OUT20, //数据输出格式GetDatasFromDDC, //获取测量数据函数指针ReadValidPin, //数据有效性状态获取函数指针SetConvPin, //转换设置函数指针SetResetPin, //复位操作函数指针SetTestPin, //测试模式操作函数指针Delayus //微秒延时函数指针);3.2、基于对象进行操作 完成了对象的初始化后我们就可以基于对象来实现相应的操作了。在我们这个应用实例中我们使用它来采集光度数据值。
/*光度检测处理*/
void DePhotometricMeasurement(void)
{if(aPara.phyPara.waveband9){luxCode[0].dCode0;luxCode[1].dCode0;luxCode[2].dCode0;luxCode[3].dCode0;ddcPeriod0;}else{ddcPeriod;if(ddcPeriod1){/*DDC114获取各通道的转换数据*/Ddc114GetDataCode(ddc);if(dataOrder[aPara.phyPara.waveband]15){dataOrder[aPara.phyPara.waveband]0;}for(int i0;i4;i){luxCode[i].fData.waveBandaPara.phyPara.waveband1;luxCode[i].fData.serialnumberdataOrder[aPara.phyPara.waveband];luxCode[i].fData.dataCodeddc.dCode[i]0xFFFFF;}dataOrder[aPara.phyPara.waveband];ddcPeriod0;}}aPara.phyPara.dataCode1luxCode[0].dCode;aPara.phyPara.dataCode2luxCode[1].dCode;aPara.phyPara.dataCode3luxCode[2].dCode;aPara.phyPara.dataCode4luxCode[3].dCode;
}4、应用总结 我们设计并实现了DDC114电流输入型ADC的驱动程序。在我们的一个应用实例中我们使用这一驱动程序采集了光度数据。测试结果如下图 其中的红色数据就是我们通过调试工具查看到的DDC114的数据对应4个通道。上面的为原始数据通过上位软件查看的结果如下 经过上述测试说明我们设计的DDC114的驱动程序是正确的。在使用时需要注意几点一是最好将MCU的SPI接口配置为主机模式而不仅仅是只读模式二是SPI的速度最好不要太快虽然DDC114可以达到10M的频率但高速时波形会变差三是积分时间一定要规划好否则很容易出现超量程的现象。
欢迎关注