综述
PGA280是TI的一款程控增益的芯片,但是它可以实现的功能很多,本身还有6个IO口可以作为后续的扩展,所以可能实际用到的也是一些其他的基础的程控增益,使得PGA280的驱动不多。我也有幸拿到了这款芯片,就用F407简单驱动一下,主要是用一下基础的放大功能,连带写一下寄存器的读写,也方便读者能够自行驱动其他功能。
供电
芯片供电最大是40V,也就是从VSP和VSN供电,我给的±15V,可以正常使用,此时输入信号范围可能在±12V左右,基本上够用。
DVDD我给的是3.3V,32的引脚基本上也是这个等级。
另外芯片还需要给输出单独供电,可能是为了隔离,方式输出电压太高烧了后面的ADC等外设,这里需要额外注意一下,我一开始就是没有考虑这个,卡了好久。
通信协议
芯片使用SPI进行通信,时序图如下:
上面是寄存器的写时序,下面是读时序,数据在时钟信号的下降沿有效。我用的是cubeMX,在设置里面配置如下图,时钟极性为低电平,时钟相位为第二个沿,此时数据在时钟信号的下降沿有效。
这里需要一个片选端,直接配置NSS为硬件输出模式就可以,我习惯使用一个输出的IO口(图中的PC4)来作片选信号,每次传输数据之前拉低。
另外还有一些其他参数,比如时钟信号的频率,手册里面给出了最大值是16MHz,一般也用不到这么高的频率,太高可能使得时钟信号失真,我一般使用的还是百kHz级别的时钟频率。
另外我们还可以从这里获得传输数据,16位是可以的,8位其实也可以,16位要注意一下传输函数中参数的强制类型转换,其他博客有提到就不赘述了,我使用的其实是8位,每次拉低CS之后传输两次就行了。
数据帧的组成
在手册中明确给出了数据帧的组成,就是4位指令+4位地址+8位数据,从上面也可以看出来。
我们主要用到的也是这两个指令,所以读寄存器的最高四位是1000,也就是8
写寄存器的最高四位是0100,也就是4
(这里面的T有其他含义,我还没有完全弄明白,就不写的,但是直接写0是可以实现功能的)
寄存器的地址
数据帧的第一个字节的第四位是寄存器的地址,芯片中一共有13个寄存器可操作:
手册中后面还给出了每一个寄存器每一个位的含义,后面会写一些重要的(用到的)寄存器。
比如说我们要给第0个寄存器写数据15,那么我们的指令组成0x4015,4表示写,0是寄存器地址,15是指令,如果要读就是0x8000,此时在发送第二个字节的同时要接收另一根数据线上的数据,所以第二个字节压根不用发送,直接接收就行。
操作一些用到的寄存器
信号通道配置
这里的信号通道指的是输入信号到增益网络的那部分,后面的MUX我觉得是跟扩展相关的,就先不写了,这里粘一下手册上的图:
这张图上的开关可以通过寄存器来配置,但是A1b这些带b的是自动控制的,如果增益网络过载就会自动接通缓冲器BUF(这里保留一下,印象中是这样没有验证,参考手册)。
这两个寄存器就是对上图中开关的操作,1表示闭合,0表示断开
比如说我们要配置A1和C2闭合,其他断开,那么需要发送0x4642
然后需要注意一下默认复位的时候是A1和A2闭合,也就是信号从1+和1-进入
增益的配置
这里需要用到寄存器0
这个寄存器的含义也很明确,可以看出我们设置增益的时候要有一个向左移3位的操作(后面的代码会有体现,也有其他思路读者可以自己思考一下)
然后G4的含义需要注意一下,是一个附加的增益因子,低三位与后面的多路复用外设有关,先不考虑
复位
复位有一个专门的寄存器,直接写0x4101就可以,软件写1,硬件置0
错误标志位
这个寄存器给出了一些错误标志位,往里面写1能够给它复位,也可以直接读出来看看芯片是否正常工作,其中含义可以直接翻译一下理解。
程序设计
经过上面的了解应该可以自己写个程序了。我只写一下比较重要的函数,由于调试的时候出了一些意外,我的函数写的比较乱,但是是可以使用的。
下面这个是读数据的代码,上面已经说过data的第八位无效,所以也没用可以随便写,然后pcheck是校验用的,但是这里面注释掉了,而且上电默认没有校验,不用担心这个
//定义一个片选端
#define CS_GPIO GPIOC
#define CS_PIN GPIO_PIN_4
uint8_t pdata = 0;
uint8_t pcheck;
uint8_t PGA280_read(uint16_t *data)
{
uint8_t read_data = 0;
pcheck = 0x9B;
pdata = ((*data) & 0xFF00)>>8;
pcheck += pdata;
HAL_GPIO_WritePin(CS_GPIO,CS_PIN,GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1, &pdata, 1, 100);
*data >>= 8;
pdata = (*data) & 0xFF;
pcheck += pdata;
HAL_SPI_Receive(&hspi1, &read_data, 1, 1);
// HAL_SPI_Transmit(&hspi1, &pcheck, 1, 1);
HAL_GPIO_WritePin(CS_GPIO,CS_PIN,GPIO_PIN_SET);
return read_data;
}
下面是写数据的指令,校验同上,没有发送。
void PGA280_write(uint16_t *data)
{
pcheck = 0x9B;
pdata = ((*data) & 0xFF00)>>8;
pcheck += pdata;
HAL_GPIO_WritePin(CS_GPIO,CS_PIN,GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1, &pdata, 1, 100);
pdata = (*data) & 0xFF;
pcheck += pdata;
HAL_SPI_Transmit(&hspi1, &pdata, 1, 100);
// HAL_SPI_Transmit(&hspi1, &pcheck, 1, 1);
HAL_GPIO_WritePin(CS_GPIO,CS_PIN,GPIO_PIN_SET);
}
下面是初始化指令,要注意一些寄存器的设置要能看懂,特别是信号通路的开关,下面配的是1+和GND有效,可以自己换一下看看效果
void PGA280_init(void)
{
uint16_t cmd;
cmd = 0x4101; //reset 也可以
PGA280_write(&cmd);
HAL_Delay(1000);//复位需要时间
cmd = 0x44FF;
PGA280_write(&cmd); //复位所有错误标志位
cmd = 0x4642;
PGA280_write(&cmd); //打开1+和GND
}
然后是设置增益的函数,这里仅供参考,我只是提供一种思路,基本上能学到这里应该也能自己写出来了
/*G的取值:
取值为0-9
实际上的增益 = 1/8 * 2^G
因此 G = 3 的时候增益为1
*/
uint16_t data;
void set_G(uint16_t G)
{
data = G << 3;
data &= 0x00F8;
data |= 0x4000;
PGA280_write(&data);
}
//将最高位置1,可以实现1.375倍数输出
void set_big_G(uint16_t G)
{
data = G << 3;
data &= 0xF8;
data |= 0x4080;
PGA280_write(&data);
}
下面是读取错误标志位寄存器的函数
uint8_t reg[13];
//提前定义一个reg,长度13,单字节
void PGA280_get_reg(void)
{
uint16_t i;
uint16_t cmd;
uint16_t x = 0;
for(i = 0;i <= 13;i++)
{
if(i==1) continue; //寄存器1不可读
x = i<<8;
cmd = 0x8000;
cmd |= x; //这里是为了生成读指令
reg[i] = PGA280_read(&cmd);
}
}
void PGA280_reset_errflag(void)
{
uint16_t cmd;
cmd = 0x44FF;
PGA280_write(&cmd); //复位所有错误标志位
}
主函数中除了自动生成的初始化代码之外,加上PGA280的初始化,然后随便写个循环读读错误寄存器,再设置一下增益看看效果就行。
uint16_t j=0;
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
PGA280_init();
while (1)
{
HAL_Delay(200);
j++;
j %= 10;
PGA280_reset_errflag(); //每次设置之前复位错误标志
set_big_G(j);
HAL_Delay(20);
PGA280_get_reg();
}
}
像函数声明这类的细节就交给读者自行完善了,解决一些常见的报错应该是绰绰有余的,目前手里只有不太工整的能跑的工程,如果需要可以留下邮箱,后面或许会完善一下。