做了一块用于污水处理单元的控制采集板,其中传感器部分大部分是4-20ma的电流输出,由于要做全隔离设计,于是采用了TI的8路ADC芯片ADS8688实现。原理图部分如下:
驱动部分代码,在他人基础上修改而来,原作者如看到请留言我好署名上去:
void spiInit(void)
{
DDRB |= (1<<SPI_CS)|(1<<SPI_SCK)|(1<<SPI_MOSI);
PORTB |= (1<<SPI_CS);
PORTB &= ~(1<<SPI_SCK)|(1<<SPI_MOSI)|(1<<SPI_MISO);
SPCR = (1<<SPE) | (1<<MSTR);
}
unsigned char spiWrite(unsigned char data)
{
SPDR = data;
while( !(SPSR & (1<<SPIF)))
;
return SPDR;
}
/******************************************************
函数名称:WriteCommandReg
函数描述:写ADS8688命令寄存器
Calls:
Called by:
输入参数:command:命令寄存器
返回值:无
******************************************************/
static void WriteCommandReg(uint32_t command)
{
ADS8684_CS_L;
spiWrite((command & 0xff00) >> 8);
spiWrite(command & 0xff);
ADS8684_CS_H;
}
/******************************************************
函数名称:autoRstMode
函数描述:进入自动扫描模式
Calls:
Called by:
输入参数:无
返回值:无
******************************************************/
void autoRstMode(void)
{
WriteCommandReg(AUTO_RST);
}
/******************************************************
函数名称: writeProReg
函数描述:Program Register写操作
Calls:
Called by:
输入参数:Addr:Program Register地址
data:写入Program Register的值
返回值:无
******************************************************/
static void writeProReg(uint32_t Addr, uint32_t data)
{
ADS8684_CS_L;
spiWrite((Addr << 1) | WRITE);
spiWrite(data);
ADS8684_CS_H;
}
/******************************************************
函数名称:readProReg
函数描述:Program Register读操作
Calls:
Called by:
输入参数:Addr:Program Register地址
返回值:Program Register的值
******************************************************/
uint32_t readProReg(uint32_t Addr)
{
uint32_t data = 0;
ADS8684_CS_L;
spiWrite((Addr) << 1 | READ);
data = spiWrite(0XFF);
data = spiWrite(0XFF);
ADS8684_CS_H;
return data;
}
/******************************************************
函数名称:Set_Auto_Scan_Sequence
函数描述:设置自动扫描序列通道
Calls:
Called by:
输入参数:seq:需要设置Auto-Scan Sequence Enable Register的值
返回值:无
******************************************************/
void Set_Auto_Scan_Sequence(uint32_t seq)
{
writeProReg(AUTO_SEQ_EN, seq);
}
/******************************************************
函数名称:Set_CH_Range_Select
函数描述:设置各个通道的范围
Calls:
Called by:
输入参数:ch:通道输入范围寄存器地址
range:量程范围
返回值:无
******************************************************/
void setChRange(uint32_t ch, uint32_t range)
{
writeProReg(ch, range);
}
/***************************************************************************************************************/
/******************************************************
函数名称:Get_AUTO_RST_Mode_Data
函数描述:读取扫描通道序列的AD转换数据
Calls:
Called by:
输入参数:pADCData:传入gUADCData.ChADCData
chNum:总通道数
返回值:无
******************************************************/
void analogConv(uint16_t* pADCData, unsigned char chNum)
{
unsigned char i;
uint32_t data_l = 0, data_h = 0;
for (i=0; i < chNum; i++)
{
ADS8684_CS_L;
_delay_us(1);
spiWrite(0X00);
spiWrite(0X00);
data_h = spiWrite(0X00);
data_l = spiWrite(0X00);
ADS8684_CS_H;
*(pADCData + i) = (data_h << 8) | data_l; //高位在前,低位在后
}
}
/******************************************************
函数名称:Init_ADS8684
函数描述:ADS8684的初始化代码
Calls:
Called by: main
输入参数:无
返回值:TRUE:初始化成功;FALSE:初始化失败
******************************************************/
unsigned char initADS8684(void)
{
ADS8688_RST_ON;
_delay_ms(2);
ADS8688_RST_OFF;
_delay_ms(2);
WriteCommandReg(PWR_DN);
_delay_ms(2);
WriteCommandReg(STDBY);
_delay_ms(2);
WriteCommandReg(AD8688_RST);
_delay_ms(20);
setChRange(Channel_0_Input_Range,VREF_0_125);
setChRange(Channel_1_Input_Range,VREF_0_125);
setChRange(Channel_2_Input_Range,VREF_0_125);
setChRange(Channel_3_Input_Range,VREF_0_125);
setChRange(Channel_4_Input_Range,VREF_0_125);
setChRange(Channel_5_Input_Range,VREF_0_125);
setChRange(Channel_6_Input_Range,VREF_0_125);
setChRange(Channel_7_Input_Range,VREF_0_125);
Set_Auto_Scan_Sequence(0xFF);// 通道0-7
if (readProReg(AUTO_SEQ_EN) != 0xFF)
return 1;
WriteCommandReg(NO_OP);
_delay_ms(1);
autoRstMode();
return 0;
}
#ifndef ADS8688_H
#define ADS8688_H
#define SPI_CS 0
#define SPI_MISO 3
#define SPI_MOSI 2
#define SPI_SCK 1
/**************************************ADS8684寄存器********************************************/
//Command Register
#define NO_OP 0X0000
#define STDBY 0X8200
#define PWR_DN 0X8300
#define AD8688_RST 0X8500
#define AUTO_RST 0XA000
#define MAN_Ch_0 0XC000
#define MAN_CH_1 0XC400
#define MAN_Ch_2 0XC800
#define MAN_Ch_3 0XCC00
#define MAN_Ch_4 0XD000
#define MAN_Ch_5 0XD400
#define MAN_Ch_6 0XD800
#define MAN_Ch_7 0XDC00
#define MAN_AUX 0XE000
//Program Register
#define AUTO_SEQ_EN 0X01
#define Channel Power Down 0X02
#define Feature Select 0X03
#define Channel_0_Input_Range 0X05
#define Channel_1_Input_Range 0X06
#define Channel_2_Input_Range 0X07
#define Channel_3_Input_Range 0X08
#define Channel_4_Input_Range 0X09
#define Channel_5_Input_Range 0X0A
#define Channel_6_Input_Range 0X0B
#define Channel_7_Input_Range 0X0C
#define Ch_0_Hysteresis 0X15
#define Ch_0_High_Threshold_MSB 0X16
#define Ch_0_High_Threshold_LSB 0X17
#define Ch_0_Low_Threshold_MSB 0X18
#define Ch_0_Low_Threshold_LSB 0X19
#define Ch_7_Hysteresis 0X38
#define Ch_7_High_Threshold_MSB 0X39
#define Ch_7_High_Threshold_LSB 0X3A
#define Ch_7_Low_Threshold_MSB 0X3B
#define Ch_7_Low_Threshold_LSB 0X3C
#define Command_Read_Back 0X3F
#define WRITE 1
#define READ 0
#define CH7_EN 0X80
#define CH6_EN 0X40
#define CH5_EN 0X20
#define CH4_EN 0X10
#define CH3_EN 0X08
#define CH2_EN 0X04
#define CH1_EN 0X02
#define CH0_EN 0X01
#define CH7_PD 0X80
#define CH6_PD 0X40
#define CH5_PD 0X20
#define CH4_PD 0X10
#define CH3_PD 0X08
#define CH2_PD 0X04
#define CH1_PD 0X02
#define CH0_PD 0X01
#define VREF_25_25 0X00
#define VREF_125_125 0X01
#define VREF_0625_0625 0X02
#define VREF_0_25 0X05
#define VREF_0_125 0X06
#define ADS8684_CS_L PORTB&=~1
#define ADS8684_CS_H PORTB|=1
#define ADS8688_RST_OFF PORTE&=~0x80
#define ADS8688_RST_ON PORTE|=0x80
extern unsigned char spiWrite(unsigned char data);
extern unsigned char initADS8684(void);
extern void spiInit(void);
extern void analogConv(uint16_t* pADCData, unsigned char chNum);
使用方法:
初始化:
while(initADS8684())
_delay_ms(5);
读8个通道: analogConv(adc_value,8);