实操记录4:拯救精密电子天平,MP3002复活记
接线实现
实验用的主板与新增的控制板飞线连接:
前期调试时,因为控制板单独接的电源,走了不少弯路.
程序模块组成
因为外围回路均已固定,所以程序的核心主要是针对A/D芯片ADS1240的通讯,辅助的部分主要是将通讯得到的数据进行处理和输出,后期丰富完整程序的各个功能,也可以根据情况增加自己想实现的功能.另外,面板按键信号的输入处理,在后期也是要考虑的事情.
综上,程序主体部分需要考虑的(或需要用到的)模块大致如下:
A/D驱动
围绕以上模块可以准备相关的驱动了,根据设计进度可以做相应的调整或修订.
下面着重分析一下A/D模块 ADS1240驱动实现过程,因为这是整个工作的核心.
德仪的这片A/D已有20多年的历史了,一些主要的指标如下:
感兴趣的同学可以从下面给的官方地址download原版datasheet:
https://www.ti.com/sitesearch/docs/universalsearch.tsp?searchTerm=ads1240#q=ads1240&t=everything&linkId=1
共有16条指令.指令并不多,但方方面面都有考虑到,设置也比较复杂.目前本人还没有全用到,也仅涉及到主要的几项,其余的待后面有时间再仔细研究.
实际板上通信通道只用到4个信号(红色部分),输入采样也仅用到Ain1通道,所以数据采集不用考虑多通道轮询,省不少事.只不过根据选用的主板,需要将原先的SPI通道的RST管脚重定义为!DRDY信号.
这里注意一点:用于ADS1240的SPI通道驱动方式最好使用"硬件驱动 “,而尽量不要使用"软件模拟”,在之前,因为DRDY信号需要复用管脚,由于使用了软件模拟驱动,致使管脚复用一直不正常,后来换成strongerHuang写的"硬驱",问题迎刃而解.
下面这段是 ADS1240寄存器指令注释
。
/*1240寄存器
ADDRESS REGISTER BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0
00H SETUP ID ID ID ID BOCS PGA2 PGA1 PGA0 //BOCS:电流源 PGA:增益倍数
01H MUX PSEL3 PSEL2 PSEL1 PSEL0 NSEL3 NSEL2 NSEL1 NSEL0 //设置正极和负极的输入端口
02H ACR DRDY U/B SPEED BUFEN BIT_ORDER RANGE DR1 DR0 //DRAY:读数据 U/B:数据格式(单双极性) SPEED:128/256分频选择 BUFFN:缓冲0/1 数据高位/低位在前 数据速度:15/7.5/3.75/Reserved Hz
03H ODAC SIGN OSET6 OSET5 OSET4 OSET3 OSET2 OSET1 OSET0 //数据偏移
04H DIO DIO_7 DIO_6 DIO_5 DIO_4 DIO_3 DIO_2 DIO_1 DIO_0 //寄存器数据
05H DIR DIR_7 DIR_6 DIR_5 DIR_4 DIR_3 DIR_2 DIR_1 DIR_0 //端口输入输出设定
06H IOCON IO7 IO6 IO5 IO4 IO3 IO2 IO1 IO0 // i/o配置
07H OCR0 OCR07 OCR06 OCR05 OCR04 OCR03 OCR02 OCR01 OCR00 //低8位偏置系数
08H OCR1 OCR15 OCR14 OCR13 OCR12 OCR11 OCR10 OCR09 OCR08 //中8位偏置系数
09H OCR2 OCR23 OCR22 OCR21 OCR20 OCR19 OCR18 OCR17 OCR16 //高8位偏置系数
0AH FSR0 FSR07 FSR06 FSR05 FSR04 FSR03 FSR02 FSR01 FSR00 //低8位寄存器
0BH FSR1 FSR15 FSR14 FSR13 FSR12 FSR11 FSR10 FSR09 FSR08 //中8位寄存器
0CH FSR2 FSR23 FSR22 FSR21 FSR20 FSR19 FSR18 FSR17 FSR16 //高8位寄存器
0DH DOR2 DOR23 DOR22 DOR21 DOR20 DOR19 DOR18 DOR17 DOR16 //高8位输出寄存器
0EH DOR1 DOR15 DOR14 DOR13 DOR12 DOR11 DOR10 DOR09 DOR08 //中8位输出寄存器
0FH DOR0 DOR07 DOR16 FSR21 DOR04 DOR03 DOR02 DOR01 DOR00 //低8位输出寄存器
这里主要使用前面3项就可以将ADS1240驱动起来,可以获取到采样到的压力传感器mV原始数据,做简单的处理后就可以用于屏幕的重量显示了.
ADS1240初始化
:
void ADS1240_Init(void)
{
// ADS1240_Config(); // 可以在此处配置SPI,GPIO和RCC 本例因为SPI采用的是硬件驱动,所以此处初始化已由SPI统一完成
ADS1240_WriteReadByte(ADS_RESET); //(0xFE)
TIMDelay_Nms(2);
/*各项主要指令设置*/
ADS1240_Setup(BOCS_0, PGAGain_32); //设置不使用电流源(0x00) 增益倍数为32(0x05)
TIMDelay_N10us(5);
ADS1240_MUX(P_AIN1, N_AINCOM); //正极性通道选AIN1 (0x10) 负极性通道全屏蔽接COM(0x08)
TIMDelay_N10us(5);
ADS1240_ACR(U_B_1, Speed_0,Bufen_1,Order_0, Range_0,DR_75); //数据为单正数(0x00) 时钟128(0x00) 有缓冲(0x10) 数据高位在前(0x00) 满量程±VREF(0x00) 刷新率7.5Hz(0x01)
}
参照前表,可以解读调整初始化参数,所有参数宏均在头文件中定义.
读写数据
:
uint8_t ADS1240_WriteReadByte(uint8_t data)
{
uint8_t databak;
ADS1240_CS_ENABLE;
databak = SPI1_WriteReadByte(data); //返回读取值
ADS1240_CS_DISABLE;
return(databak);
}
因为采用SPI硬件驱动,写指令只要简单的把指令传给SPI就行,如果要读数据,也只要直接接收返回的数据即可,无需为时序纠结.
板上ADS1240的!CS已经直接接地.信号也并未使用.此处使能只是保持程序完整性,SPI中片选已设置为"软件控制".
指令时序
:
/*******************************************************************************
*SETUP
*******************************************************************************/
void ADS1240_Setup(uint8_t bocs, uint8_t PGAGain)
{
ADS1240_WriteReadByte(ADS_WREG | ADS_SETUP); //0x50|0x00 表示对SETUP地址0x00进行写操作(0x50)
ADS1240_WriteReadByte(0x00); //00表示此操作(写入)后续寄存器的个数为0
ADS1240_WriteReadByte(bocs | PGAGain); //传入的数据0x00|0x05 = 0x05
//最终时序 0x50 0x00 0x00
}
/*******************************************************************************
*MUX
*******************************************************************************/
void ADS1240_MUX(uint8_t positiveChannel, uint8_t negativeChannel) //0x51
{
ADS1240_WriteReadByte(ADS_WREG | ADS_MUX); //(0x50|0x01)
ADS1240_WriteReadByte(0x00);
ADS1240_WriteReadByte(positiveChannel | negativeChannel); //(0x10|0x08 = 0x18)
//最终时序 0x51 0x00 0x18
}
/*******************************************************************************
*ACR
*******************************************************************************/
void ADS1240_ACR(uint8_t ub, uint8_t speed, uint8_t buffer, uint8_t order, uint8_t range, uint8_8 dr) //0x52
{
ADS1240_WriteReadByte(ADS_WREG | ADS_ACR); //(0x50|0x02)
ADS1240_WriteReadByte(0x00);
ADS1240_WriteReadByte(ub | speed | buffer | order | range | dr); // 0x00|0x00|0x10|0x00|0x00|0x01=0x11
//最终时序 0x52 0x00 0x11
}
ADS1240同样也具备地址连续操作的能力,所以以上时序也可以通过改写第二句"连续地址"值为2,一次将3条指令写入,效率要高一些.只不过牺牲程序一些可读性:
ADS1240_WriteReadByte(0x02); //后续地址的数量=2
其余初始化参数的设定类似.照此编写即可.
正确的时序应该类似这样的(注意52地址写入的并不是上面设定的值):
验证后,下一步就可以获取数据.
读取数据:
/*******************************************************************************
*Val
*******************************************************************************/
int32_t ADS1240_ReadADC()
{
uint8_t temp[3]; //临时数据寄存
uint32_t Val = 0; //返回的数据值
if(ADS1240_READY_PIN()) //DRDY引脚高电平表示数据没准备好
{
return 0;
}
else
{
temp[0] = ADS1240_WriteReadByte(ADS_RDATA); //读取数据高8位 ADS_RDATA:0x01
TIMDelay_N10us(1);
temp[1] = ADS1240_WriteReadByte(ADS_RDATA); //读取数据中8位
TIMDelay_N10us(1);
temp[2] = ADS1240_WriteReadByte(ADS_RDATA); //读取数据低8位
TIMDelay_N10us(1);
Val = (uint32_t)(temp[0] << 16) + (uint32_t)(temp[1] << 8) + (temp[2] ); //拼接数据
return (Val); // 返回数据值
}
}
返回的Val值就可以交给main()去处理了.
(未完)