关于电容采集芯片PCAP01AD芯片配合STM32的编程问题

问题遇到的现象和发生背景

本人需要做一个电容信号采集并输出电容值的模块,做的是4X4的阵列电容,通过上下极板横纵交错形成的单个电容,单个电容通过模拟开关ADG734接入电容采集芯片PCAPO1AD芯片进行采集,将采集的数据存入数组中通过串口发送至上位机,目前用2X2的电容进行测试,发现只能进行单个的电容测试,对模拟开关的控制引脚也只能接一个,模拟开关为adg734,它是含有四个单刀双掷开关,当控制单刀双掷开关的引脚检测到高电平就掷向A,低电平就掷向B,所以通过施加高低电平来依次选通阵列电容的行列来对阵列式电容依次进行单个电容一 一采集,在进行单个电容测试的时候可以正常输出数据,但是在进行切换行列接入引脚的时候(也就是通过STM32io口的高低电平控制ADG734的开关控制叫依次接入阵列电容的四个电容),会把模拟开关芯片直接烧坏。

img

img

img

img

img

img

下面是通过SPI写入PCAP01AD芯片的代码

问题相关代码,请勿粘贴截图

unsigned long cap_status = 0,cap_reszult0 = 0,cap_temp = 0;
float cap_val = 0.0f;
unsigned int value[4]={0};
int main(void)
{
SystemInit(); //系统初始化

Delay_Init();

Cap_Enable_two();

SPI_Configuration();

USART_Configuration();

cap01_init();

delay_ms(500);
while(1)
{
GPIO_SetBits(GPIOB,GPIO_Pin_8);
GPIO_SetBits(GPIOB,GPIO_Pin_12);
    __3nop();
      Delay_us(100);
 Read_Value();
    value[0]=cap_val;
    __3nop();
    __3nop();
    GPIO_ResetBits(GPIOB,GPIO_Pin_12);
    __3nop();

GPIO_SetBits(GPIOB,GPIO_Pin_15);
__3nop();
Delay_us(100);
Read_Value();
value[1]=cap_val;
__3nop();
__3nop();

    GPIO_ResetBits(GPIOB,GPIO_Pin_8);
    __3nop();
    GPIO_ResetBits(GPIOB,GPIO_Pin_15);
    __3nop();

GPIO_SetBits(GPIOB,GPIO_Pin_11);
__3nop();
GPIO_SetBits(GPIOB,GPIO_Pin_12);
__3nop();
Delay_us(100);
Read_Value();
value[2]=cap_val;
__3nop();

    GPIO_ResetBits(GPIOB,GPIO_Pin_12);
    __3nop();

GPIO_SetBits(GPIOB,GPIO_Pin_15);
__3nop();
Delay_us(100);
Read_Value();
value[3]=cap_val;
__3nop();
GPIO_ResetBits(GPIOB,GPIO_Pin_11);
__3nop();
GPIO_ResetBits(GPIOB,GPIO_Pin_15);
__3nop();
SendDebugData(value, 16);
__3nop();

delay_ms(1000);
}

}

void SendDebugData(unsigned int *Data, unsigned char ByteNum)
{
int i;
unsigned char *p;
__3nop();
USART_SendData(USART1, 0XAA);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, 0XAA);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, 0X00);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
USART_SendData(USART1, 0X00);
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);

p = (unsigned char *)& (*Data);   //发送数据
for(i = ByteNum; i > 0; i--)
{
    USART_SendData(USART1, *(p + i - 1));
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}
}

void Read_Value(void)
{
SPI_Disable();
__3nop();
write_date_8(0x48); //写入读取状态寄存器的操作码
__3nop();
cap_status = spi_read();//读取状态寄存器,返回结果应该为0x100000或0x900000,测量通讯的准确性

      SPI_Disable();
    __3nop();
    write_date_8(0x41);   //addr1 Res1 C1 LSB 0-7.9999  0b01xxxxxx 写入读取结果寄存器的操作码
    __3nop();
  cap_reszult0 = spi_read();//得到结果寄存器的数据 24位

     //cap_reszult0 = 0x1b3011;
    cap_temp = 0x1fffff;
    cap_val = (double)cap_reszult0/(double)cap_temp;       // 为C0/C1的比值
    cap_val = cap_val*100000000;                      // cap_val 为待测电容的容值,100为基准电容容值,乘以10^6扩充为int型方便后续数据处理

}

void cap01_init(void)
{
unsigned long int REG[11] = {
0xC04200FF,//addr0 0xC04200FF

0xC1201022,//addr1 0xC1201022 固定
0xC20F250B,        //PC2 IS USED           
0xC30D0064,//addr3 0xC30D0064
             //0Bxx(CY_CLK_SEL):CDC循环的时钟基准 0-20us 2-1us(当外部4M晶振时) 3-0.25us(当外部4M晶振时);
             //0B0;
             //0Bxxxxx(SEQ_TIME):在时钟-触发模式设置触发的周期(TMEAS_TRIG_SEL=2) 0-关闭 ;
             //0B0;
             //0Bxx(CMEAS_FAKE):设定CDC每次测量的后的假测量次数,可从04选择;
             //0Bxxx...(C_AVRG):CDC测量后内部平均的次数。设置为0无效,默认为1;
0xC4080000,//addr4 0xC4080000
             //0B00;
             //0Bxx(CMEAS_STARTPIN):选择相应的输出电容测量的脉冲触发管脚 0-PG0 1-PG1 2-PG2 3-PG3;
             //0Bxx(CMEAS_TRIG_SEL):选择电容测量的触发源 0-仅软件触发 1-持续模式 2-时钟触发模式 3-脉冲触发模式;
             //0Bxxxxxxxxxx(CMEAS_CYTIME):设置用于电容测量的CDC周期时间 (CMEAS_CYTIME+1)*Clock_PeriodClock_period=20us/1us/0.25us根据CYCLKSEL=0/2/3;
             //0B000;
             //0Bx(TMEAS_CYTIME):设置用于温度测量的周期时间 0-140us(推荐) 1-280us;
             //0Bxx(TMEAS_STARTPIN):选择用于温度测量的脉冲触发管脚 0-PG0 1-PG1 2-PG2 3-PG3;
             //0Bxx(TMEAS_TRIG_SEL):选择温度测量的触发源.选项23请不要应用; 0-关闭/操作码触发 1-CMEAS-触发(通过C-测量,推荐) 2-时钟触发模式 3-脉冲触发模式
0xC5000000,//addr5 0xC5000000
             //0Bxx(T_AVRG):0-1无平均 1-4次平均 2-8次平均 3-16次平均; 
             //0Bxxx...(TMEAS_TRIG_PREDIV):RDC相对于CDC的测量出现的次数 01次; 
0xC6000040,//addr6 0xC6000040
             //0X00; 
             //0Bx(TMEAS_FAKE):0-2次假测量 1-8次假测量; 
             //0Bxxxxxxx(TMEAS_7BITS):选择温度补偿的连接方式; ?
             //0X40; ?
0xC71F0000,//addr7 0xC71F0000 固定
0xC8800010,//addr8 0xC8800030 DSP设置
0xC9FF000F,//addr9 0xC9FF000F PWM/PDM设置
0xCA180047,//addr10 0xCA180087
             //0X1800
             //0Xxx(V_CORE_CTL):控制1.8 V 核心电压调节器 0x47-标准 0x87-低功耗    
};

SPI_Enable();
delay_ms(1);
write_date_8(0x88);        //上电复位。复位所有状态。
delay_ms(1);

spi_test();                 //测试 通讯是否正常

//SPI_Enable();
//delay_ms(1);
//write_date_8(0x88);        //上电复位。复位所有状态。
//delay_ms(1);

write_firmware();       //这个是写入的固件

SPI_Disable();
__3nop();
write_date_32(0xc04200FF);   //寄存器0设置:关闭SRAM与OTP比较;关闭OTP内部错误检测与修复;配置为单从机模式。打开写入读出保护。
//write_date_32(REG[0]);

SPI_Disable();
__3nop();
write_date_32(0xC1201022);   //寄存器1设置,固定写入。
//write_date_32(REG[1]);

SPI_Disable();
__3nop();
write_date_32(0xc20F450B);   //P0 P1 P2 P3 接入测量,单一电容漂移模式
//write_date_32(REG[2]);

SPI_Disable();
__3nop();
write_date_32(0xc30d0064);   //测量周期为20us;时钟触发测量模式。5.24s触发一次测量。200次平均测量。2次假测量(前两次数据丢弃)
//write_date_32(REG[3]);

SPI_Disable();
__3nop();
write_date_32(0xc4080000);   //触发方式选择。定时器触发。0xc4080510不用温度测量
//write_date_32(REG[4]);    

SPI_Disable();
__3nop();
write_date_32(0xc5000000);   //
//write_date_32(REG[5]);    

SPI_Disable();
__3nop();
write_date_32(0xc6000040);   //0xc6004140不用温度测量
//write_date_32(REG[6]);    

SPI_Disable();
__3nop();
write_date_32(0xc71F0000);    //固定写入
//write_date_32(REG[7])    ;

SPI_Disable();
__3nop();
write_date_32(0xc8800010);     //内部单片机程序存储空间选择。
//write_date_32(REG[8]);    

SPI_Disable();
__3nop();
write_date_32(0xc9FF000F);     //设置PWM输出引脚。输出数据位数。0xc9BF208F
//write_date_32(REG[9]);    

SPI_Disable();
__3nop();
write_date_32(0xca180047);     //设置内部DSP工作电压。    

SPI_Disable();
__3nop();
write_date_32(0xD4000001);    //芯片开始工作。寄存器20
__3nop();

SPI_Disable();
__3nop();
write_date_8(0x8a);           //复位输出结果数据。
__3nop();

SPI_Disable();
__3nop();
write_date_8(0x8c); //开始电容测量。

}

运行结果及报错内容

模拟开挂芯片也就是控制4个电容接入的芯片在切换中直接被烧坏

我的解答思路和尝试过的方法

我的理解是PCAP01AD芯片是通过对比较被测电容和基准电容的充放电时间来计算被测电容值的,它先对被测电容进行充电,然后对芯片内部电阻放电,完成一个测量周期,但是可能因为我对此芯片的设定是持续不断的测量的,可能在PCAP01AD芯片正在放电的时候我通过ADG734切换了接入的电容,本应该放电的电容的上下极板被直接接入GND,导致上一个带电电容通过ADG734直接对地放电,导致ADG734被击穿,于是我取下了损坏的两个控制电容行列接入的ADG734芯片,换上了全新的芯片,一块板子将他们两块芯片的8个接地的引脚全部悬空(如原理图中两个S1B-S4B),另一块板子将他们悬空起来串电阻接地防止他们放电时电流过大。

img

我想要达到的结果

我的预期是在程序控制中能够达到我先切换ADG734开关接入某个待测电容,切换完成后再让PCAP01AD芯片开始测量,测量完成后读取数据放入数组中,当两行两列电容全部测完再发送出去,主要问题就是如何对PCAP01AD配置才能够通过程序随时控制它开始停止测量,而不会在我切换开关时刚好在测量或者切换完成又没在测量呢?并且根据它的测量原理如何合理选择充放电时间让放电避免击穿ADG734呢?下图是PCAP01AD的部分说明

img

img

img

img

img

本问题已解决,主要还是对pcap01寄存器配置问题,只要在需要测量的时候打开,测量完毕关闭即可

你好,我是有问必答小助手,非常抱歉,本次您提出的有问必答问题,技术专家团超时未为您做出解答


本次提问扣除的有问必答次数,已经为您补发到账户,我们后续会持续优化,扩大我们的服务范围,为您带来更好地服务。