这里介绍Ti公司的一款低功耗高精度的电容传感器芯片FDC2214,这里我们主要讲的是其简单配置及其使用。

以下大多数的图片都来自于FDC2214的芯片手册,本人只是用来讲解,不做它用。(如有更多需要,自行前往Ti官网进行下载)

首先我们先来看一下芯片的主要特性:

从芯片手册上可知,其供电电压为2.7V到3.6V,谐振频率从10kHz to 10MHz,数据位数为28位,即精度为1/2^28,FDC2214有4个采集通道,其与MCU的通信方式为IIC。

这里我们用软件IIC来实现与FDC2214的通信。

其次我们来看一下芯片的引脚图:

通过芯片手册我们可知写时序为:

读时序为:

读完整个芯片手册我们发现,其从机的地址说的并不是很清楚,这里通过测试发现其从机地址(FDC2214为从机)如下

当ADDR为低时:0x2A,这里二进制表示为0010 1010,这里我们需要移除最高位,即为010 1010_,这里当最后一位为低时表示向FDC2214写入数据,为高时,是读出数据。

及ADDR = L:0x54为写,0x55为读;

同理当ADDR = H:0x56为写,0x57为读;

即通信的原理框图如下(以ADDR为低为例):

(1) 写时序:

(2)读时序:

了解完时序之后,我们就可以开始进行寄存器的配置,这里芯片手册上已经给出该怎么配置,如下图:

这里不细说每个寄存器是干什么的,如有需要,可以参照芯片手册,这里,我们需要改一个寄存器的配置,就是地址为0x1A的寄存器,

该寄存器的值如下:

这里我们需要配置第9位,将其配置为0,使用内部晶振,那么0x1A寄存器的值改为 0x1401。

这里我们开始写程序,

这里IIC的程序,我们使用的是正点原子的库,其库函数如下:

//IIC
void IIC_Init(void)
{                        GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(    RCC_APB2Periph_GPIOB, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);    //PB6,PB7
}
//
void IIC_Start(void)
{SDA_OUT();     IIC_SDA=1;       IIC_SCL=1;delay_us(4);IIC_SDA=0;//START:when CLK is high,DATA change form high to low delay_us(4);IIC_SCL=0;
}
//
void IIC_Stop(void)
{SDA_OUT();IIC_SCL=0;IIC_SDA=0;//STOP:when CLK is high DATA change form low to highdelay_us(4);IIC_SCL=1; IIC_SDA=1;delay_us(4);
}u8 IIC_Wait_Ack(void)
{u8 ucErrTime=0;SDA_IN();      IIC_SDA=1;delay_us(1);    IIC_SCL=1;delay_us(1);   while(READ_SDA){ucErrTime++;if(ucErrTime>250){IIC_Stop();return 1;}}IIC_SCL=0;      return 0;
}
//Set up ACK
void IIC_Ack(void)
{IIC_SCL=0;SDA_OUT();IIC_SDA=0;delay_us(2);IIC_SCL=1;delay_us(2);IIC_SCL=0;
}
//Set up NACK(NO ACK)
void IIC_NAck(void)
{IIC_SCL=0;SDA_OUT();IIC_SDA=1;delay_us(2);IIC_SCL=1;delay_us(2);IIC_SCL=0;
}
//IIC Send Byte
void IIC_Send_Byte(u8 txd)
{                        u8 t;   SDA_OUT();         IIC_SCL=0;for(t=0;t<8;t++){              //IIC_SDA=(txd&0x80)>>7;if((txd&0x80)>>7)IIC_SDA=1;elseIIC_SDA=0;txd<<=1;       delay_us(2);   IIC_SCL=1;delay_us(2); IIC_SCL=0;    delay_us(2);}
}
//ack = 0 send Nack  ack = 1 send ACK
u8 IIC_Read_Byte(unsigned char ack)
{unsigned char i,receive=0;SDA_IN();for(i=0;i<8;i++ ){IIC_SCL=0; delay_us(2);IIC_SCL=1;receive<<=1;if(READ_SDA)receive++;   delay_us(1); }                     if (!ack)IIC_NAck();elseIIC_Ack(); return receive;
}

void IIC_Init(void)函数是初始化 SCL,SDA两个引脚;

void IIC_Start(void) 函数是产生START信号;

void IIC_Stop(void)函数是产生STOP信号;

u8 IIC_Wait_Ack(void)函数是接收从机发送的ACK;

void IIC_Ack(void)函数是主机读完数据后产生应答信号;

void IIC_NAck(void) 函数是主机读完数据后不产生应答信号;

void IIC_Send_Byte(u8 txd) 函数是发送一个字节的数据;

u8 IIC_Read_Byte(unsigned char ack)函数是接收一个字节的数据;

这里我们还需要配置与FDC2214通信的函数,向FDC2214寄存器写的函数为

//这里 FDC_Address_W =0x54
void FDC_write_reg(u8 addr,u16 value)   //addr 为寄存器地址,value为需要写入的寄存器数据
{ IIC_Start();                    //产生START信号IIC_Send_Byte(FDC_Address_W);   //发送从机地址和写信号IIC_Wait_Ack();                 //等待ACKIIC_Send_Byte(addr);            //发送需要写入的寄存器地址IIC_Wait_Ack();                 //等待ACKIIC_Send_Byte(value>>8);        //发送高8位数据IIC_Wait_Ack();                 //等待ACKIIC_Send_Byte(value&0xFF);      //发送低8位数据IIC_Wait_Ack();                 //等待ACKIIC_Stop();                      //产生STOP信号delay_ms(1);
}

从FDC2214读16位数据的函数如下:

//FDC_Address_W =0x54
//FDC_Address_R =0x55
//Receive_Date[] 为接收数据的数组
//C_Data 为一个16位无符号的整型
u16 FDC_read_reg(u8 addr)
{IIC_Start();                    //产生START信号IIC_Send_Byte(FDC_Address_W);   //发送写命令IIC_Wait_Ack();      IIC_Send_Byte(addr);            //发送需要读的寄存器的地址IIC_Wait_Ack();IIC_Start();IIC_Send_Byte(FDC_Address_R);  //发送读命令IIC_Wait_Ack();Receive_Date[0]=IIC_Read_Byte(1);  //读高8位Receive_Date[1]=IIC_Read_Byte(0);  //读低8位IIC_Stop();                       //产生STOP信号C_Data=(Receive_Date[0]<<8)+ Receive_Date[1];return C_Data;
}

从FDC2214读高8位数据的函数如下:

u8 FDC_read_reg_high(u8 addr)
{IIC_Start();IIC_Send_Byte(FDC_Address_W);   IIC_Wait_Ack();        IIC_Send_Byte(addr);IIC_Wait_Ack();IIC_Start();IIC_Send_Byte(FDC_Address_R);  IIC_Wait_Ack();Receive_Date[0]=IIC_Read_Byte(1);Receive_Date[1]=IIC_Read_Byte(0);IIC_Stop();    return Receive_Date[0];
}

从FDC2214读低8位数据的函数如下:

u8 FDC_read_reg_low(u8 addr)
{IIC_Start();IIC_Send_Byte(FDC_Address_W);   IIC_Wait_Ack();        IIC_Send_Byte(addr);IIC_Wait_Ack();IIC_Start();IIC_Send_Byte(FDC_Address_R);  IIC_Wait_Ack();Receive_Date[0]=IIC_Read_Byte(1);Receive_Date[1]=IIC_Read_Byte(0);IIC_Stop();    return Receive_Date[1];
}

FDC2214初始化的函数如下:

void FDC_Start(void)
{
FDC_write_reg(0x08,0x8329);   //(CHx_RCOUNT*16)/55M ==9.76ms,,每10ms左右可以读一次值FDC_write_reg(0x09,0x8329);FDC_write_reg(0x0A,0x8329);  FDC_write_reg(0x0B,0x8329);FDC_write_reg(0x10,0x000A);  //设置4个通道最小稳定时间FDC_write_reg(0x11,0x000A);FDC_write_reg(0x12,0x000A);FDC_write_reg(0x13,0x000A);FDC_write_reg(0x14,0x1001); //时钟除以1,设置传感器频率在0.01M到8.5M之间FDC_write_reg(0x15,0x1001);FDC_write_reg(0x16,0x1001);FDC_write_reg(0x17,0x1001);FDC_write_reg(0x19,0x0000); //不设置中断标志位FDC_write_reg(0x1B,0xC20D);//使能0,1,2,3通道,且带宽设置为10MFDC_write_reg(0x1E,0x8000); //设置4个通道的驱动电流FDC_write_reg(0x1F,0x8000);FDC_write_reg(0x20,0x8000);FDC_write_reg(0x21,0x8000);FDC_write_reg(0x1A,0x1401); //使能FDC2214,且取内部时钟为参考时钟
}

其头文件的配置如下:

#ifndef __FDC2214_H
#define __FDC2214_H
#include <sys.h>
//IO口方向#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}//IO操作函数
#define IIC_SCL    PBout(6) //SCL
#define IIC_SDA    PBout(7) //SDA
#define READ_SDA   PBin(7)  //SDA输入//IIC函数
void IIC_Init(void);
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Send_Byte(u8 txd);
u8 IIC_Read_Byte(unsigned char ack);
u8 IIC_Wait_Ack(void);
void IIC_Ack(void);
void IIC_NAck(void);                void FDC_write_reg(u8 addr,u16 value);
void FDC_Start(void);
u16 FDC_read_reg(u8 addr);
u8 FDC_read_reg_high(u8 addr);
u8 FDC_read_reg_low(u8 addr);#endif

这里为了判断我们的程序和FDC2214是没有问题,先读取相应的ID,这里有两个ID可以供我们读取:

这里我们在主函数中需要读出相应的ID,来确定FDC2214和我们IIC的程序没有问题。

其主函数如下:

int main()
{u8 lcd_id[12];u16 C_date=0;u16 ID=0;u16 C_CH0_data=0;u16 C_CH0_data_low=0;u32 C_CHO_data_final=0;u16 C_CH1_data=0;u16 C_CH1_data_low=0;u32 C_CH1_data_final=0;u16 C_CH2_data=0;u16 C_CH2_data_low=0;u32 C_CH2_data_final=0;u16 C_CH3_data=0;u16 C_CH3_data_low=0;u32 C_CH3_data_final=0;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  delay_init();    //初始化延时函数LCD_Init();      //初始化LCD显示uart_init(115200); //初始化串口IIC_Init();       //初始化 IICPOINT_COLOR=BLUE;sprintf((char*)lcd_id,"LCD ID:%04X",lcddev.id);LCD_Clear(WHITE);POINT_COLOR=BLUE;LCD_ShowString(30,70,240,16,24,"C_Chan_0:");LCD_ShowString(30,100,240,16,24,"C_Chan_1:");LCD_ShowString(30,130,240,16,24,"C_Chan_2:");LCD_ShowString(30,160,240,16,24,"C_Chan_3:");LCD_ShowString(30,190,240,16,24,"DRDY:");delay_ms(10);FDC_Start();       //FDC初始化while(1){LCD_ShowString(30,40,240,16,24,"Successful!");delay_ms(500);C_date = FDC_read_reg(0x7E);       //读取ID  ID =  FDC_read_reg(0x7F);         //读取IDif(C_date!=0xFF00 && ID!=0xFF00)           //显示ID{                  LCD_ShowxNum(139,350,ID,5,24,0);    LCD_ShowxNum(139,380,C_date,5,24,0);}        delay_ms(100);}}

FDC2214的数值是28位的,这里我们需要读两个寄存器的值(以CH0为例)分别是0x00,和0x0A:

从芯片手册可以知道(以CH0为例),0x01寄存器中为数据的低16位,0x00寄存器为数据的高12位,将两个数据合起来,即为相应的数据,其程序如下:

               if(C_date==0x5449 && ID==0x3055)    //当为相应ID时才读取寄存器的值{
//读通道0数值    C_CH0_data = FDC_read_reg(0x00)&0xFFF;C_CH0_data_low = FDC_read_reg(0x01);C_CHO_data_final =((C_CH0_data<<16)+C_CH0_data_low);
//读通道1数值        delay_ms(50);C_CH1_data = FDC_read_reg(0x02)&0xFFF;C_CH1_data_low = FDC_read_reg(0x03);C_CH1_data_final =((C_CH1_data<<16)+C_CH1_data_low);
//读通道2数值delay_ms(50);C_CH2_data=FDC_read_reg(0x04)&0xFFF;C_CH2_data_low = FDC_read_reg(0x05);C_CH2_data_final =((C_CH2_data<<16)+C_CH2_data_low);//读通道3数值      delay_ms(50);C_CH3_data=FDC_read_reg(0x06)&0xFFF;C_CH3_data_low = FDC_read_reg(0x07);C_CH3_data_final =((C_CH3_data<<16)+C_CH3_data_low);//显示相应通道读出来的值LCD_ShowxNum(139,70,C_CHO_data_final,9,24,0);      LCD_ShowxNum(139,100,C_CH1_data_final,9,24,0);LCD_ShowxNum(139,130,C_CH2_data_final,9,24,0);LCD_ShowxNum(139,160,C_CH3_data_final,9,24,0);}

读取完数值之后,其电容的计算公式以可在芯片手册找到,如下:

这里我们可以知道其电容的计算就是根据LC谐振频率的变化来计算。

这里,CHx_FIN_SEL和f_REFx可以从下图得知,DATAx即为我们读出的数值,这里就可以算出电容值。

这里我们如果发现ID读得不对,可以将SCL和SDA通过电阻(本人用的4.7K)上拉,这样就可以读取正确的ID值。

FDC2214——电容传感器芯片的使用与配置(STM32控制)相关推荐

  1. STM32芯片IO口的配置以及上拉下拉电阻介绍(一)

    STM32芯片IO口的配置以及上拉下拉电阻介绍(一) IO口常见的配置方式 推挽输出 开漏输出 STM32芯片做硬件研发的朋友们都知道.但是还是有很多做硬件的新朋友"只知其然而不知其所然&q ...

  2. Linux/Windows配置stm32免费开发环境详细流程

    系统:linux mint 18.3 xfce,windows10  stm32开发板:正点原子mini板(stm32f103rc)  烧写器:stlink v2  如果是JLINK的可以参考这篇  ...

  3. CUBEMX配置STM32实现FTP文件传输以及使用SNTP获取网络时间并写入RTC

    CUBEMX配置STM32实现FTP文件传输以及使用SNTP获取网络时间并写入RTC 引言 FTP代码库的移植 Cubemx配置SNTP以及RTC RTC配置方法 SNTP配置方法 FATFS载入RT ...

  4. 配置STM32寄存器控制GPIO点亮LED

    STM32点亮LED 寄存器方式 IO简介 1.每个IO可以自由编程,但是IO口寄存器必须按照32位字被访问. 2.每个IO端口都有7个寄存器来控制. CRL [0-7]端口配置寄存器  32位 CR ...

  5. stm32f103各个型号芯片之间程序移植(stm32的兼容问题)

    stm32f103各个型号芯片之间程序移植(stm32的兼容问题) 1.stm32f103系列的各个型号的芯片差别一般不大,都是一些flash大小不一样,一般是向下兼容(大容量芯片兼容中容量芯片)还有 ...

  6. 【CubeMX配置STM32的ADC】

    CubeMX配置STM32的ADC 包含阻塞式和非阻塞式以及多通道ADC 一.CubeMX配置STM32 1.单通道ADC 单通道的配置比较简单,需要注意的是需要中断的使能,因为在使用非阻塞式的函数时 ...

  7. 【CubeMX配置STM32驱动超声波模块(HC-SR04)】

    CubeMX配置STM32以驱动超声波模块(HC-SR04) 一.CubeMX配置STM32 1.选择定时器 选择输入捕获模式 预分频设置为71,向上计数,自动重装值65535 然后将名字改为ECHO ...

  8. 【CubeMX配置stm32定时器中断】

    CubeMX配置stm32定时器中断 一.使用CubeMX对STM32进行基础的配置 1.选择需要使用的定时器 选择TIM2和TIM3示例, 注意: TIM2和其它定时器选择时钟的方法不同,TIM3等 ...

  9. CubeMX配置STM32实现httpd服务器CGI功能并使用网页控制STM32单片机(四)

    CubeMX配置STM32实现httpd服务器CGI功能并使用网页控制STM32单片机 引言 CubeMX配置HTTPD的CGI功能 实验过程 发现的问题 总结 引言 在前三篇文章中自己介绍了如何配置 ...

最新文章

  1. VC++设置Release模式下允许调试代码
  2. 一文读懂AI 与神经网络发展历程
  3. 分布式架构的演进过程
  4. Ocelot中文文档-缓存
  5. 解决Windows 程序界面闪烁问题的一些经验
  6. matlab 凹盘,刹车盘凹槽是怎么形成的
  7. 大数据互联网架构阶段 QuartZ定时任务+RabbitMQ消息队列
  8. [python作业AI毕业设计博客]大数据Hadoop工具python教程1-HDFS Hadoop分布式文件系统...
  9. vue内容横向循环滚动_Vue替代marquee标签超出宽度文字横向滚动效果
  10. 用VisualBrush定制复杂的按钮样式
  11. 图标字体制作,mock数据
  12. 有这就够了小香港五味俱全——专升本高数
  13. VS2008 ---- VS2013各个版本下载地址
  14. C4D模型工具—提取样条
  15. 基于搜狗新闻语料库的词向量模型训练(Windows下)
  16. 屏幕录像专家限制录像时长_屏幕录像档案已更新!
  17. 开题报告、论文摘要、摘要翻译、论文结论怎么写?
  18. 免费PDF翻译,不限页数,不限字数,保留排版
  19. 【已解决】macbook软件卸载了图标还在launchpad上怎么办?一分钟搞定!
  20. 什么是React为什么使用React什么时候使用React

热门文章

  1. ReadFile 函数
  2. 【免费】无人机图像处理工具软件—批量去雾,匀光匀色,增强,对比度亮度调节
  3. 什么是Remoting
  4. 2023 华为 Datacom-HCIE 真题题库 06/12--含解析
  5. Sign in with Apple(object-c) 从开发者后台到服务端验证
  6. python中的pandas库
  7. 零基础Unreal Engine 4(UE4)图文笔记之基础篇-基本操作(二)
  8. C语言多组输入和字符输入(小白)
  9. Python之路点燃编程圈:源于不爽C语言,单枪匹马搞副业,如今吞噬世界(附链接)...
  10. java简单记事本代码_简单记事本的java程序代码