|
|
View previous topic :: View next topic |
Author |
Message |
akaka
Joined: 18 Jul 2012 Posts: 14
|
Interfacing AD7730 |
Posted: Sat Feb 27, 2016 4:54 am |
|
|
Hi every one I was looking for any similar post for days.....
I want to interface AD7730 Bridge Transducer ADC with a PIC.
The project it is still in Demo Mode and it's simple in main loop.
So here is the schematic
http://postimg.org/image/d77oqkcxt/
and code follows:
Libraries for AD7730
AD7730.c
Code: | /*----------------------------------------------------------------------------
File: AD7730.c
Description
Driver of AD7730
Project : Operating System for 16f88---->Test weighing scale with AD7730
Created for Version: 1.0
Updated for Version: 1.0
Last Date Modified : 20/02/2016
Copyright(c) 2016 by Chris_Kal
All Rights Reserved.
----------------------------------------------------------------------------*/
#include "AD7730.h"
#define RESET PIN_B6
#define READY PIN_B5
#define AD7730_SELECT PIN_B3
void SendAD_Data(BYTE data)
{
//delay_ms(2);
spi_write(data);
//delay_ms(5);
}
void AD7730_Init()
{
//-----------Filter Configuration-------------------------------
printf("Filter Configuration...\r\n");
output_low(AD7730_SELECT);
SendAD_Data(CR_SINGLE_WRITE | CR_FILTER_REGISTER);
SendAD_Data(FR2_SINC_AVERAGING_2048);
SendAD_Data(FR1_SKIP_OFF | FR1_FAST_OFF);
SendAD_Data(FR0_CHOP_ON);
output_high(AD7730_SELECT);
//--------------------------------------------------------------
delay_ms(30);
//----------------DAC Configuration-----------------------------
printf("DAC Configuration...\r\n");
output_low(AD7730_SELECT);
SendAD_Data(CR_SINGLE_WRITE | CR_DAC_REGISTER);
SendAD_Data(DACR_OFFSET_SIGN_POSITIVE | DACR_OFFSET_NONE);
output_high(AD7730_SELECT);
//--------------------------------------------------------------
delay_ms(30);
//---------Internal Zero Calibartion----------------------------
printf("Internal Zero Calibartion...\r\n");
output_low(AD7730_SELECT);
SendAD_Data(CR_SINGLE_WRITE | CR_MODE_REGISTER);
SendAD_Data(MR1_MODE_INTERNAL_ZERO_CALIBRATION | CURRENT_MODE_1_SETTINGS);
SendAD_Data(CURRENT_MODE_0_SETTINGS);
//waitForReady
while(input(READY) != 0) ;////not yet
output_high(AD7730_SELECT);
//---------Internal Full Calibartion----------------------------
printf("Internal Full Calibartion...\r\n");
output_low(AD7730_SELECT);
SendAD_Data(CR_SINGLE_WRITE | CR_MODE_REGISTER);
SendAD_Data(MR1_MODE_INTERNAL_FULL_CALIBRATION | CURRENT_MODE_1_SETTINGS);
SendAD_Data(CURRENT_MODE_0_SETTINGS);
//waitForReady
while(input(READY) != 0) ;////not yet
output_high(AD7730_SELECT);
//--------------------------------------------------------------
//---------------SET CONTINOUS MODE-----------------------------
printf("SET CONTINOUS MODE...\r\n");
output_low(AD7730_SELECT);
SendAD_Data(CR_SINGLE_WRITE | CR_MODE_REGISTER);
SendAD_Data(MR1_MODE_CONTINUOUS | CURRENT_MODE_1_SETTINGS);
SendAD_Data(CURRENT_MODE_0_SETTINGS);
//waitForReady
while(input(READY) != 0) ;////not yet
output_high(AD7730_SELECT);
//--------------------------------------------------------------
//---------------START CONTINUOUS READ--------------------------
printf("START CONTINUOUS READ...\r\n");
output_low(AD7730_SELECT);
SendAD_Data(CR_CONTINUOUS_READ_START | CR_DATA_REGISTER);
output_high(AD7730_SELECT);
//--------------------------------------------------------------
}
int8 ReadStatus(void)
{
int8 status;
output_low(AD7730_SELECT);
delay_ms(5);
spi_write(CR_SINGLE_READ| CR_STATUS_REGISTER);
status = spi_read(0);
output_high(AD7730_SELECT);
return status;
}
int16 Read_Mode(void)
{
int16 data;
int8 ModeH;
int8 ModeL;
output_low(AD7730_SELECT);
delay_ms(5);
spi_write(0x12); //send comm reg for read from MODE reg(opcode)
ModeH = spi_read(0); //read high byte
ModeL = spi_read(0); //read low byte
data = (ModeH<<8)|ModeL;
delay_ms(20);
output_high(AD7730_SELECT); //CS = 1
return data;
}
int8 ReadDAC(void)
{
int8 DAC;
output_low(AD7730_SELECT);
delay_ms(5);
spi_write(CR_SINGLE_READ| CR_DAC_REGISTER);
if( spi_data_is_in()){
DAC = spi_read(0);
printf("Incoming Data\r\n");
}
output_high(AD7730_SELECT);
return DAC;
}
|
AD7730.h
Code: |
#define READ_ONLY 0xFF
//Communication Register Values
#define CR_SINGLE_WRITE 0x00
#define CR_SINGLE_READ 0x10
#define CR_CONTINUOUS_READ_START 0x20
#define CR_CONTINUOUS_READ_STOP 0x30
#define CR_COMMUNICATION_REGISTER 0x00 //Write only
#define CR_STATUS_REGISTER 0x00 //Read only
#define CR_DATA_REGISTER 0x01
#define CR_MODE_REGISTER 0x02
#define CR_FILTER_REGISTER 0x03
#define CR_DAC_REGISTER 0x04
#define CR_OFFSET_REGISTER 0x05
#define CR_GAIN_REGISTER 0x06
#define CR_TEST_REGISTER 0x07
//Mode Register Values
#define MR1_MODE_IDLE 0x00
#define MR1_MODE_CONTINUOUS 0x20 //Standard Operation
#define MR1_MODE_SINGLE 0x40
#define MR1_MODE_STANDBY 0x60
#define MR1_MODE_INTERNAL_ZERO_CALIBRATION 0x80
#define MR1_MODE_INTERNAL_FULL_CALIBRATION 0xA0
#define MR1_MODE_SYSTEM_ZERO_CALIBRATION 0xC0
#define MR1_MODE_SYSTEM_FULL_CALIBRATION 0xE0
#define MR1_BU_BIPOLAR 0x00 //+- voltage defined by MR0_RANGE
#define MR1_BU_UNIPOLAR 0x10 //0 to voltage deifined by MRO_RANGE
#define MR1_WL_24_BIT 0x01
#define MR1_WL_16_BIT 0x00
#define MR0_HIREF_5V 0x80
#define MR0_HIREF_2P5V 0x00
#define MR0_RANGE_10MV 0x00
#define MR0_RANGE_20MV 0x01
#define MR0_RANGE_40MV 0x02
#define MR0_RANGE_80MV 0x03
#define MR0_CHANNEL_1 0x00
#define MR0_CHANNEL_2 0x01
#define MR0_CHANNEL_SHORT_1 0x02 //Used for internal noise check
#define MR0_CHANNEL_NEGATIVE_1_2 0x03 //Unknown use
#define MRO_BURNOUT_ON 0x04 //Advanced, to check if loadcell is burnt out
//Filter Register Values
#define FR2_SINC_AVERAGING_2048 0x80 //Base sample rate of 50 Hz
#define FR2_SINC_AVERAGING_1024 0x40 //Base sample rate of 100 Hz
#define FR2_SINC_AVERAGING_512 0x20 //Base sample rate of 200 Hz
#define FR2_SINC_AVERAGING_256 0x10 //Base sample rate of 400 Hz
#define FR1_SKIP_ON 0x02 //the FIR filter on the part is bypassed
#define FR1_SKIP_OFF 0x00
#define FR1_FAST_ON 0x01 //FIR is replaced with moving average on large step, sinc filter averages are used to compensate
#define FR1_FAST_OFF 0x00
#define FR0_CHOP_ON 0x10 //When the chop mode is enabled, the part is effectively chopped at its input and output to remove all offset and offset drift errors on the part.
#define FR0_CHOP_OFF 0x00 //Increases sample rate by x3
//DAC Register Values
#define DACR_OFFSET_SIGN_POSITIVE 0x00
#define DACR_OFFSET_SIGN_NEGATIVE 0x20
#define DACR_OFFSET_40MV 0x10
#define DACR_OFFSET_20MV 0x08
#define DACR_OFFSET_10MV 0x04
#define DACR_OFFSET_5MV 0x02
#define DACR_OFFSET_2P5MV 0x01
#define DACR_OFFSET_NONE 0x00
//current settings
#define CURRENT_MODE_1_SETTINGS (MR1_BU_UNIPOLAR | MR1_WL_24_BIT)
#define CURRENT_MODE_0_SETTINGS (MR0_HIREF_5V | MR0_RANGE_10MV | MR0_CHANNEL_1)
|
init.c
Code: | /*----------------------------------------------------------------------------
File: S_INIT.C
Description
Implementation of InitSystem() function.
Project : Operating System for 16f88---->Test weighing scale with AD7730
Created for Version: 1.0
Updated for Version: 1.0
Last Date Modified : 06/02/2016
Copyright(c) 2016 by Chris_Kal
All Rights Reserved.
----------------------------------------------------------------------------*/
/******************* Pin Description...**************************************/
//1 RA2/AN2/CVREF/VREF- NOT USED OUTPUT
//2 RA3/AN3/VREF+/C1OUT NOT USED OUTPUT
//3 RA4/AN4/T0CKI/C2OUT NOT USED OUTPUT
//4 RA5/MCLR/VPP NOT USED OUTPUT
//5 VSS
//6 RB0/INT/CCP1 AD7730_READY INPUT
//7 RB1/SDI/SDA SPI_SDI INPUT
//8 RB2/SDO/RX/DT SPI_SDO OUTPUT
//9 RB3/PGM/CCP1 AD7730_SELECT OUTPUT
//10 RA1/AN1 SOFT UART TX OUTPUT
//11 RA0/AN0 SOFT UART RX INPUT
//12 RA7/OSC1/CLKI NOT USED OUTPUT
//13 RA6/OSC2/CLKO NOT USED OUTPUT
//14 VDD
//15 RB7/AN6/PGD/ NOT USED OUTPUT
//16 RB6/AN5/PGC/ NOT USED OUTPUT
//17 RB5/SS/TX/CK NOT USED OUTPUT
//18 RB4/SCK/SCL SPI_SCK AUTO
/*The following files must be place to the main file (internal clock 8MHz)
#include <16F88.h>
//#fuses HS,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#fuses INTRC_IO,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay(clock=8000000)
#define AD7730_SELECT PIN_B3
#define SPI_SCK PIN_B4
#define SPI_SDI PIN_B1 //mosi
#define SPI_SDO PIN_B2 //miso
#use spi(master, di=SPI_SDI, do=SPI_SDO, clk=SPI_SCK, mode=0, baud=500000, stream=STREAM_SPI_AD7730,FORCE_HW)//or baud=1000000
//SOFT UART SETUP
#use rs232(baud=9600, xmit=PIN_A1, rcv=PIN_A0,FORCE_SW)
*/
//#include <16F88.h>
/********Init System***********/
void InitSystem(void)
{
set_tris_a(0x02);//RA0 Software Uart Input
set_tris_b(0x23);//pins 5, 0 & 1 are inputs all others are outputs
//setup_psp(PSP_DISABLED);
/*setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF); */
//setup_CCP1(CCP_OFF);
//setup_CCP2(CCP_OFF);
output_high(AD7730_SELECT);//set critical I/O
}
|
main file
Code: | /*----------------------------------------------------------------------------
File: weighing.c
Description
Main application for Weighing scale using AD7730
Project : Operating System for 16f88---->Test weighing scale with AD7730
Created for Version: 1.0
Updated for Version: 1.0
Last Date Modified : 24/02/2016
Copyright(c) 2016 by Chris_Kal
All Rights Reserved.
----------------------------------------------------------------------------*/
#include <16F88.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#fuses INTRC_IO,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD
#use delay(clock=8000000)
#use rs232(baud=9600, xmit=PIN_A0, rcv=PIN_A1,FORCE_SW)
#include "AD7730.c"
#include "s_init.c"
#define SPI_SCK PIN_B4
#define SPI_SDI PIN_B1 //mosi
#define SPI_SDO PIN_B2 //miso
#use spi(master, di=SPI_SDI, do=SPI_SDO, clk=SPI_SCK, mode=1, baud=250000, FORCE_HW,MSB_FIRST)//or baud=1000000
//SOFT UART SETUP
int8 result1;
int8 result2;
int8 result3;
int16 mode;
unsigned long result;
int8 first=0;
int8 nDAC;
int8 second;
int8 third;
void main(void)
{
InitSystem();
output_low(RESET);
delay_ms(250);
output_high(RESET);
delay_ms(250);
printf("Welcome\r\n");
//SendAD_Data(CR_SINGLE_WRITE | CR_MODE_REGISTER);
//delay_ms(500);
//spi_write(0xff);
first = ReadStatus();
printf("status is 0x%x\r\n",first);
// delay_ms(500);
nDAC = ReadDAC();
printf("DAC is 0x%x\r\n",nDAC);
mode=Read_Mode();
printf("Mode is 0x%x \r\n",mode);
output_low(AD7730_SELECT);
SendAD_Data(CR_SINGLE_WRITE | CR_MODE_REGISTER);
SendAD_Data(0x80);
SendAD_Data(CURRENT_MODE_0_SETTINGS);
while(input(READY) != 0) ;////not yet
output_high(AD7730_SELECT);
delay_ms(500);
mode=Read_Mode();
printf("Mode is 0x%x \r\n",mode);
//waitForReady
AD7730_Init();
printf("Init finished\r\n");
printf("Reading Registers.......\r\n");
delay_ms(500);
first = ReadStatus();
printf("status is 0x%x\r\n",first);
delay_ms(50);
mode=Read_Mode();
printf("Mode is 0x%x \r\n",mode);
while(TRUE)
{
//From the data sheet, we need to read bytes continously but hold the AD7730 DIN pin (Arduino MOSI) low, so we send 0b0000 0000 three times
output_low(AD7730_SELECT);
SendAD_Data(CR_CONTINUOUS_READ_START | CR_DATA_REGISTER);
output_high(AD7730_SELECT);
while(input(READY) != 0) ;
output_low(AD7730_SELECT);
SendAD_Data(0x30);
output_high(AD7730_SELECT);
delay_ms(250);
output_low(AD7730_SELECT);
SendAD_Data(0x11);
result1 = spi_read(0);
result2 = spi_read(0);
result3 = spi_read(0);
output_high(AD7730_SELECT);
printf("Data Registers (hex)\r\n ");
printf("result1, HEX%x\r\n",result1);
printf("result2, HEX%x\r\n",result2);
printf("result3, HEX%x\r\n",result3);
result = result3 + result2 * 256L + result1 * 256L * 256L;
printf("result %Ld\r\n",result);
delay_ms(2500);
}
}
|
On reset according to ad7730 datasheet the reset status reg seems to be fine (I read 0xc0) but after that all other regs is read 0.
I forgot to give you wirings:
AD7730 Board Easy PIC 6 (16f88)
SDI RB1
SDO RB2
CS/ RB3
SCK RB4
RDY/ RB5
RESET/ RB6
SYNC/ VCC
POL JUMPER TO GND
any ideas????
Thanks in advance
Chris |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sat Feb 27, 2016 6:29 am |
|
|
in the ccs manual , spi_write() / spi_read() includes the following info:
Code: |
This function is only available on devices with SPI hardware.
|
the hardware function in the F88 for SPI is on C3,4,5
your declaration #use spi is for software based SPI on other pins.
it doesn't work the way you think.
the problem:
you are mixing soft spi setup -with the HARDWARE only commands
of spi_read spi_write
They don't mix and match. time to read the CCS manual -
i might add that code like this:
Code: | SendAD_Data(MR1_MODE_INTERNAL_ZERO_CALIBRATION | CURRENT_MODE_1_SETTINGS); |
is actually lot LESS CLEAR than
Code: |
send_AD(0x14); // MR1_MODE_INTERNAL_ZERO_CALIBRATION ,CURRENT_MODE_1_SETTINGS
|
because for debug it's too much wasted effort to figure out the bit pattern when its a bunch of defines - that could themselves be faulty.
If ANY of that stuff was VARS - it would be different - but these are #defines and not subject to change, - but IMHO, its less clear if you actually got the code right -- the way you over-document it - just my 2 cents |
|
|
akaka
Joined: 18 Jul 2012 Posts: 14
|
|
Posted: Sat Feb 27, 2016 7:24 am |
|
|
Hi asmboy,
Thanks for your reply but I think you are a little bit confused.
16f88 is a 18 pin device there is no port C availiable.
Take a look at the following link which is the datasheet of 16f88
http://ww1.microchip.com/downloads/en/DeviceDoc/30487D.pdf
my configuration is proper for hardware SPI pins.
regards
Chris |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sat Feb 27, 2016 7:48 am |
|
|
yes - i had pins for F886 in my head - sorry
the KEY comment stands about mixing soft SPI with hard --
i still suspect that setup_spi() - not #use spi is what you want
ie: that you are not doing what you think in SPI terms.
big picture: you do setup for SOFT spi
but then use the HARD function - which is not set up the same way.
so yes - you can see data clocked and everything - but bit order may not be right because of your "mix & match" code |
|
|
akaka
Joined: 18 Jul 2012 Posts: 14
|
|
Posted: Sat Feb 27, 2016 8:13 am |
|
|
asmboy wrote: | because of your "mix & match" code |
can you be more detailed about that???
I haven't found any info in ccs manual about #use spi command isused only in software interfacing.
On the contrary FORCE_HW commands is used to configure hardware pins
I'll check in .lst file if the proper registers are configured as it should be and I will keep you informed.
Tomorrow I am going to check it using oscilloscope. |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Sat Feb 27, 2016 8:36 am |
|
|
the manual details it rather well.
when you read the bold topic SPI
you see the following:
For software support, see #USE SPI.
you are incorrectly mixing #USE - which is for soft spi code
with hard code OUTPUT and INPUT
setup_spi() does not require a #USE SPI declaration
what is most telling is this:
go READ the heading for setup_spi()
and see what I/O functions are associated with IT.
then read
#USE SPI
and note that the ONLY function associated with IT is
Quote: |
Also See: spi_xfer() |
best of luck learning SPI for CCS |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Feb 27, 2016 10:37 am |
|
|
Also, #use spi() defaults to 32-bit transfers. If you're doing only 8-bit
transfers in your code with spi_xfer(), the easiest way to fix this is to
add the BITS=8 parameter as shown in bold below:
Quote: | #use spi(master, di=SPI_SDI, do=SPI_SDO, clk=SPI_SCK, mode=1, baud=250000, FORCE_HW,MSB_FIRST, BITS=8) |
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|