Other Parts Discussed in Thread: ADS8684
HI:
我的项目上使用TDA4VM-Q1,然后通过SPI1连接到ADS8684,SPI1的设备树配置如下:
&main_spi1 {
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins_default>;
status="okay";
spidev@0 {
spi-max-frequency = <24000000>;
reg = <0>;
compatible = "linux,spidev";
};
};
spi1_pins_default: spi1_pins_default {
pinctrl-single,pins = <
J721E_IOPAD(0x1dc, PIN_INPUT, 0) /* (Y1) SPI1_CLK */
J721E_IOPAD(0x1d4, PIN_INPUT, 0) /* (Y3) SPI1_CS0 */
J721E_IOPAD(0x1e0, PIN_INPUT, 0) /* (Y5) SPI1_D0 */
J721E_IOPAD(0x1e4, PIN_INPUT, 0) /* (Y2) SPI1_D1 */
>;
};
目前跑到LInux下已经可以识别到SPIDEV1.0,可以通过spidev_test读写
然后,我写了ADS8684的驱动,代码如下:
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef signed char s8;
typedef short s16;
typedef int s32;
typedef long long s64;
u16 My_Ad[8]={0,0,};
float ad_real[2]={0.0,0.0};
#define NO_OP 0X0000
#define STDBY 0X8200
#define PWR_DN 0X8300
#define SPIRST 0X8500
#define AUTO_RST 0XA000
#define MAN_Ch_1 0XC000
#define MAN_Ch_2 0XC400
#define MAN_Ch_3 0XC800
#define MAN_Ch_4 0XCC00
#define MAN_Ch_5 0XD000
#define MAN_Ch_6 0XD400
#define MAN_Ch_7 0XD800
#define MAN_Ch_8 0XDC00
#define MAN_AUX 0XE000
#define CH1 0x05
#define CH2 0x06
#define CH3 0x07
#define CH4 0x08
#define CH5 0x09
#define CH6 0x0a
#define CH7 0x0b
#define CH8 0x0c
static int spidev_fd = 0;
static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
{
int ret;
int out_fd;
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = len,
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};
if (mode & SPI_TX_OCTAL)
tr.tx_nbits = 8;
else if (mode & SPI_TX_QUAD)
tr.tx_nbits = 4;
else if (mode & SPI_TX_DUAL)
tr.tx_nbits = 2;
if (mode & SPI_RX_OCTAL)
tr.rx_nbits = 8;
else if (mode & SPI_RX_QUAD)
tr.rx_nbits = 4;
else if (mode & SPI_RX_DUAL)
tr.rx_nbits = 2;
if (!(mode & SPI_LOOP)) {
if (mode & (SPI_TX_OCTAL | SPI_TX_QUAD | SPI_TX_DUAL))
tr.rx_buf = 0;
else if (mode & (SPI_RX_OCTAL | SPI_RX_QUAD | SPI_RX_DUAL))
tr.tx_buf = 0;
}
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
pabort("can't send spi message");
if (verbose)
hex_dump(tx, len, 32, "TX");
if (output_file) {
out_fd = open(output_file, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (out_fd < 0)
pabort("could not open output file");
ret = write(out_fd, rx, len);
if (ret != len)
pabort("not all bytes written to output file");
close(out_fd);
}
if (verbose)
hex_dump(rx, len, 32, "RX");
}
void ADS8688_SPI_WB(uint8_t com)
{
int ret = 0;
transfer(spidev_fd,&com,0,1);
return;
ret = ioctl(spidev_fd, SPI_IOC_WR_BITS_PER_WORD, &com);
if (ret == -1)
printf("can't set bits per word\n");
else
printf("set bits per word \n");
}
uint8_t ADS8688_SPI_RB(void)
{
int ret = 0;
uint8_t bits=0;
transfer(spidev_fd,0,&bits,1);
return bits;
ret = ioctl(spidev_fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
printf("can't get bits per word");
else
printf(" bits per word");
return bits;
}
void ADS8688_WriteCommandReg(uint16_t command)//写ADS8688命令寄存器
{
ADS8688_SPI_WB(command>>8 & 0XFF);
ADS8688_SPI_WB(command & 0XFF);
}
void ADS8688_Write_Program_Register(uint8_t Addr,uint8_t data)
{
ADS8688_SPI_WB(Addr<<1| 0X01);
ADS8688_SPI_WB(data);
}
u8 ADS8688_READ_Program_Register(uint8_t Addr)
{
u8 data = 0;
ADS8688_SPI_WB(Addr<<1);
data = ADS8688_SPI_RB();
data = ADS8688_SPI_RB();
return data;
}
void Enter_RESET_MODE(void)//软件复位模式,复位 program registers
{
ADS8688_WriteCommandReg(SPIRST);
}
void AUTO_RST_Mode(void)//进入自动扫描模式
{
ADS8688_WriteCommandReg(AUTO_RST);
}
void MAN_Ch_n_Mode(uint16_t ch)//自动模式
{
ADS8688_WriteCommandReg(ch);
}
void Set_CH_Range_Select(uint8_t ch,uint8_t range) //设置各个通道的范围
{
ADS8688_Write_Program_Register(ch,range);
}
void Get_AUTO_RST_Mode_Data(uint16_t* outputdata, uint8_t chnum)
{
//读取扫描通道序列的AD转换数据code到变量数组中
u8 i=0,datal=0,datah=0;
u16 data=0;
for (i=0; i<chnum; i++)
{
ADS8688_SPI_WB(0X00);
ADS8688_SPI_WB(0X00);
datah = ADS8688_SPI_RB();
datal = ADS8688_SPI_RB();
data = datah<<8 | datal; //低位在前,低位在后
*(outputdata+i) = data;
}
}
//初始化通道1,默认正负10V范围
void ADS8688_Init_Single()
{
//ADS_8688_RST_PD_L;
//delay_us(2);
//ADS_8688_RST_PD_H;
//ADS_8688_DAISY_IN_L;
Enter_RESET_MODE();
ADS8688_Write_Program_Register(0X01,0Xff);
ADS8688_READ_Program_Register(0X01);
usleep(2);
ADS8688_Write_Program_Register(0x02,0x00);//所有通道退出低功耗状态
ADS8688_Write_Program_Register(0x01,0xff);//使能所有通道
Set_CH_Range_Select(CH1,0x00);//设置通道1的输?范围:+-2.5*Vref
// //0x00 -> +-2.5*ref
// //0x01 -> +-1.25*ref
// //0x02 -> +-0.625*ref
// //0x03 -> +2.5*ref
// //0x04 -> +1.25*ref
MAN_Ch_n_Mode(MAN_Ch_1);
//HAL_Delay(300);
}
void ADS8688_Init_Mult(void)
{
//ADS_8688_RST_PD_H;
//ADS_8688_DAISY_IN_L;
//delay_us(10);
Enter_RESET_MODE();
//进入配置
ADS8688_Write_Program_Register(0X00,0X00);
usleep(10);
//开启通道
ADS8688_Write_Program_Register(0X01,0X07);
usleep(10);
//下拉
ADS8688_Write_Program_Register(0x02,0xf8);//所有通道退出低功耗状态
usleep(10);
//设置功能
ADS8688_Write_Program_Register(0x03,0x03);
usleep(10);
//ADS8688_Write_Program_Register(0x01,0xff);//使能所有通道
Set_CH_Range_Select(CH1,0x00);//设置通道1的输入范围:+-2.5*Vref
usleep(10);
Set_CH_Range_Select(CH2,0x00);
usleep(10);
Set_CH_Range_Select(CH3,0x00);
usleep(10);
Set_CH_Range_Select(CH4,0x00);
usleep(10);
/*
Set_CH_Range_Select(CH2,0x00);
Set_CH_Range_Select(CH3,0x00);
Set_CH_Range_Select(CH4,0x00);
Set_CH_Range_Select(CH5,0x00);
Set_CH_Range_Select(CH6,0x00);
Set_CH_Range_Select(CH7,0x00);
*/
// //0x00 -> +-2. 5*ref
// //0x01 -> +-1.25*ref
// //0x02 -> +-0.625*ref
// //0x03 -> +2.5*ref
// //0x04 -> +1.25*ref
//AUTO_RST_Mode();//进入自动扫描模式
ADS8688_Write_Program_Register(0xa0,0x03);
usleep(10);
AUTO_RST_Mode();
}
uint16_t Get_MAN_Ch_n_Mode_Data(void)
{
u8 datah=0,datal=0;
//ADS_8688_nCS_L;
ADS8688_SPI_WB(0X00);
ADS8688_SPI_WB(0X00);
datah = ADS8688_SPI_RB();
datal = ADS8688_SPI_RB();
//ADS_8688_nCS_H;
return (datah<<8 | datal);
}
u16 get_ADS_ch1(void)
{
return Get_MAN_Ch_n_Mode_Data();//读取通道1数据,具体通道数由函数 MAN_Ch_n_Mode()所决定的
}
static u16 ADS_Results[4]={0,};
void get_ADS_allch(float*result)
{
Get_AUTO_RST_Mode_Data(ADS_Results,4);//?动扫描模式,?动扫描并转换8通 道。转换数据存与Results数组中
}
double get_realdata(u16 x,u8 t)//mv
{
double y;
if(!t)
{
y = (s16)(((double)(x-32762) *20.48/(double)65535)*1000);
}
else
{
y = (s16)(((double)(x-32725) *20.48/(double)65535)*1000);
}
return y;
}
//初始化多通道,默认全开、正负10V范围
void gat_real_ad(float *real_ad)
{
real_ad[0]= (float)get_realdata(My_Ad[0],0);
real_ad[1]= (float)get_realdata(My_Ad[1],1);
}
void get_ADS_1and2(u16 *My_Ad,float *real_ad)
{
Get_AUTO_RST_Mode_Data(My_Ad,2);
gat_real_ad(real_ad);
}
double get_realdata1(u16 x)
{
double y;
y=x-32768;
if(y<0) y = y * 0.0001907+0.02;
else y = y * 0.0001907+0.02;
return y;
}
int main(int argc, char *argv[])
{
int ret = 0;
int fd;
parse_opts(argc, argv);
if (input_tx && input_file)
pabort("only one of -p and --input may be selected");
spidev_fd = open(device, O_RDWR);
if (fd < 0)
pabort("can't open device");
printf("open device %s ok...",device);
/*
* spi mode
*/
ret = ioctl(spidev_fd, SPI_IOC_WR_MODE32, &mode);
if (ret == -1)
pabort("can't set spi mode");
ret = ioctl(spidev_fd, SPI_IOC_RD_MODE32, &mode);
if (ret == -1)
pabort("can't get spi mode");
/*
* bits per word
*/
ret = ioctl(spidev_fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't set bits per word");
ret = ioctl(spidev_fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
pabort("can't get bits per word");
/*
* max speed hz
*/
ret = ioctl(spidev_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't set max speed hz");
ret = ioctl(spidev_fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1)
pabort("can't get max speed hz");
printf("spi mode: 0x%x\n", mode);
printf("bits per word: %u\n", bits);
printf("max speed: %u Hz (%u kHz)\n", speed, speed/1000);
ADS8688_Init_Mult();
while(1)
{
Get_AUTO_RST_Mode_Data(ADS_Results,4);//?动扫描模式,?动扫描并转换8通 道。转换数据存与Results数组中
printf("get data:{%d,%d,%d,%d}---%f,%f,%f,%f\n",ADS_Results[0],ADS_Results[1],ADS_Results[2],ADS_Results[3], get_realdata1(ADS_Results[0]),get_realdata1(ADS_Results[1]),get_realdata1(ADS_Results[2]),get_realdata1(ADS_Results[3]));
usleep(500*1000);
}
}
但是我给通道输入数据后,通过spi读出来的数据却一直是65535,没有获取到实际的ADC通道数据,请帮忙看看这个过程中哪里有问题?