|
|
View previous topic :: View next topic |
Author |
Message |
amate
Joined: 29 Aug 2010 Posts: 14 Location: SPAIN
|
what is wrong in this ADS1211 code ? |
Posted: Tue May 20, 2014 11:53 am |
|
|
I use pins: DO, SDI, DRDY and Clock, SC always selected (0).
I wish to modify CMR with BIAS=1, SDL=1, then if I check Bias pin I know if has been modified.
Xtal of ADS is 8 MHz, and micro is 12 MHz (18F46K80).
I use real circuit for test.
But result that don't write to CMR and program hangs. I think that it hangs inside write_adc_instr().
Code: |
/*programa para probar el AD1211 con driver ad1211b.c
*/
#include <18F46K80.h>
#device adc=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128
#FUSES NOXINST
#FUSES HSH //High speed Osc, high power 16MHz-25MHz
#FUSES NOPLLEN //4X HW PLL disabled, 4X PLL enabled in software
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES BORV27 //Brownout reset at 2.7V
#FUSES WDT_SW //No Watch Dog Timer, enabled in Software
#use delay(clock=12000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#define ADC_DRDY PIN_D1
#define ADC_DO PIN_D2
#define ADC_DI PIN_D3
//#define ADC_CS PIN_D5
#define ADC_CLK PIN_D6
//-------------declarations--------------------
void write_adc_instr(int8 data); //send Instuction
void write_adc_byte(int8 data);
void write_4byte(long long int value); //serial aout of 4 bytes
void set_command(long long int value); //send CMR
void config_ADC(void); //build and send CMR
long long int read_adc_3byte(void); //serial read 3 byte
long long int get_tension(void); //read 3 DOR registers
//--------------------minimum program for test--------------------
void main()
{
long long int resistencia;
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_timer_4(T4_DISABLED,0,1);
Output_low( ADC_DO); //pin ADC_DO output
input(ADC_DI); //input
output_low(pin_D5); //chip select permanently
delay_ms(1000); // tiempo para estabilizar el ADC
printf("Hola Antonio Mate \n\r");
config_ADC(); //configura el ADC
delay_ms(100);
printf("Hola de nuevo \n\r");
while(1){
output_high(PIN_B1); //led on
resistencia = get_tension();
printf("get= %LX - ",resistencia);
delay_ms(500);
output_low(PIN_B1); //led OFF
delay_ms(500);
}
}
//-------------------------definitions-------------------------------
void config_ADC(void)
{ int8 CMR0=100,CMR1=0,CMR2=0,CMR3=0x82;
long long int comando;
comando=make32(CMR3,CMR2,CMR1,CMR0);
set_command(comando); //carga los 4 registros de command
}
void write_adc_instr(int8 data) //envia un byte
{ while(!input(ADC_DRDY)); //waiting DRDY=1
while(input(ADC_DRDY)); //waiting falling DRDY
delay_us(4); // > 5.5Txy; Txy=0.125 us with 8 Mhz clock
write_adc_byte(data);
}
void write_adc_byte(int8 data) //rutina de envio de un byte
{
int8 i,data1=data; //para no modificar data
for(i=0;i<8;++i) {
output_high(ADC_CLK);
output_bit(ADC_DI, shift_left(&data1,1,0));
delay_us(10);
output_low(ADC_CLK);
delay_us(10);
}
}
void write_adc_4byte(long long int data) //envia los 4 bytes
{ long long data1=data;
int8 i;
for(i=1;i<=32;++i) {
output_high(ADC_CLK);
output_bit(ADC_DO, shift_left(&data1,4,0));
delay_us(10);
output_low(ADC_CLK);
delay_us(10);
}
}
long long int read_adc_3byte()
{ int8 i;
long long data=0;
for(i=1;i<=24;++i) {
output_high(ADC_CLK);
delay_us(10);
shift_left(&data,3,input(ADC_DO));
output_low(ADC_CLK);
delay_us(10);
}
return ((data>>8)&0x00FFFFFF);
}
long long int get_tension()
{ long long value=0;
write_adc_instr(0xC0); //read from addres of DOR
value=read_adc_3byte();
return value;
}
void set_command(long long value)
{
write_ADC_instr(0x64); //write to command addres 100
write_adc_4byte(value);
input(ADC_DI);
}
|
All your opinions will be very well received
antonio mate |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Tue May 20, 2014 4:37 pm |
|
|
Code: |
{ while(!input(ADC_DRDY)); //waiting DRDY=1
while(input(ADC_DRDY)); //waiting falling DRDY
|
look at the data sheet!!!!!!
there will NEVER be a LOW time(or any transition) until you write some (valid) SPI data !!!!!! |
|
|
amate
Joined: 29 Aug 2010 Posts: 14 Location: SPAIN
|
reading from ads1211 |
Posted: Wed May 21, 2014 8:47 am |
|
|
I have read notes about ADS and I have not seen you say, more and more, with the same config and write functions now I can modify the 4 bytes of CMR, that means that are correct.
But I cannot read, I have this modified function for read the 3 bytes of DOR. Code: |
long long int read_adc_3byte() //lee los 3 Bytes de DOR
{
int8 i;
long long data=0;
while(!input(ADC_DRDY)); //waiting DRDY=1
while(input(ADC_DRDY)); //waiting falling DRDY
delay_us(4); // > 5.5Txy; Txy=0.125 us with 8 Mhz clock
write_adc_byte(0xC0);
input(ADC_DI);
delay_us(5);
for(i=0;i<24;++i) {
output_high(ADC_CLK);
delay_us(5);
shift_left(&data,3,(input(ADC_DI)));
output_low(ADC_CLK);
delay_us(5);
}
return (data);
}
|
There are here any error?
Thanks for be patient |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Wed May 21, 2014 12:11 pm |
|
|
Without seeing AND studying the full SETUP sequence you sent the part (?)
no way to tell what error might lurk in the routine you extracted here.
and be sure to look at figure 6 in the data sheet-
as 0Xc0 looks wrong as an "INSR" prefix for starters ........
remember that you are dealing with a VERY complex part. |
|
|
amate
Joined: 29 Aug 2010 Posts: 14 Location: SPAIN
|
reading from ads1211 |
Posted: Wed May 21, 2014 1:33 pm |
|
|
Hello, thanks for your time and collaboration.
0xC0 - b11000000-is the instruction for Read (1) , three bytes (10) from address 0000.(High Byte of DOR).
If the Command register is written OK means that this part of code is correct,I check this changing Bias and Data rate.
Then, after sending this instruction is when happen the problem, but I don't see if is software problem, or timing problem.
This is the minimum software I use now for test:
Code: | /*program for testing ADS1211
*/
#include <18F46K80.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128
#FUSES NOXINST
#FUSES HSH //High speed Osc, high power 16MHz-25MHz
#FUSES NOPLLEN //4X HW PLL disabled, 4X PLL enabled in software
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES BORV27 //Brownout reset at 2.7V
#FUSES WDT_SW //No Watch Dog Timer, enabled in Software
#use delay(clock=12000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#define ADC_DRDY PIN_D1
#define ADC_DO PIN_D2
#define ADC_DI PIN_D3
//#define ADC_CS PIN_D5
#define ADC_CLK PIN_D6
//-------------declarations--------------------
void write_adc_instr(char data); //send Instruction
void write_adc_byte(char data); //serial out of 1 byte
void write_4byte(long long int value); //serial aout of 4 bytes
void set_command(long long int value); //send CMR
void config_ADC(void); //build and send CMR
long long int read_adc_3byte(void); //serial read 3 byte of DOR
//--------------------minimum program for test--------------------
void main()
{
long long int medida;
float resistencia;
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_timer_4(T4_DISABLED,0,1);
input(ADC_DI); //input
output_low(pin_D5); //chip select permanently
delay_ms(1000); // tiempo para estabilizar el ADC
config_ADC(); //configura el ADC
delay_ms(100);
while(1){
medida = read_adc_3Byte();
resistencia= (float)medida*5600.0/0x7FFFFF ;
printf("get= %LX - RES= %W1.6\n\r",medida,resistencia);
delay_ms(1000);
delay_ms(1000);
}
}
//-------------------------definitions-------------------------------
void config_ADC(void)
{ char CMR0=0x38,CMR1=0x01,CMR2=0,CMR3=0x80;//Byas=1,DataRate=312
long long int comando;
comando=make32(CMR3,CMR2,CMR1,CMR0);
set_command(comando); //carga los 4 registros de command
}
void write_adc_instr(char data) //envia un byte
{
while(!input(ADC_DRDY)); //waiting DRDY=1
while(input(ADC_DRDY)); //waiting falling DRDY
delay_us(4); // > 5.5Txy; Txy=0.125 us with 8 Mhz clock
write_adc_byte(data); //send Byte
}
void write_adc_4byte(long long int data) //send 4 bytes
{ long long data1=data;
int8 i;
for(i=1;i<=32;++i) {
output_high(ADC_CLK);
output_bit(ADC_DI, shift_left(&data1,4,0));
delay_us(5);
output_low(ADC_CLK);
delay_us(5);
}
}
void set_command(long long value)
{
write_ADC_instr(0x64); //write (0),4 (11)Bytes to adress 100-(b01100100)
write_adc_4byte(value);
}
long long int read_adc_3byte() //read 3 Bytes de DOR
{
int8 i;
long long data=0;
while(!input(ADC_DRDY)); //waiting DRDY=1
while(input(ADC_DRDY)); //waiting falling DRDY
delay_us(4); // > 5.5Txy; Txy=0.125 us with 8 Mhz clock
write_adc_byte(0xC0); //instruction for read, 3 bytes fron address 000
input(ADC_DI);
for(i=0;i<24;++i) {
output_high(ADC_CLK);
delay_us(5);
shift_left(&data,3,(input(ADC_DI)));
output_low(ADC_CLK);
delay_us(5);
}
return (data);
}
may be one timing problem?
Ther are not much soft. abou ADS1211/ads1213 in this forum
|
|
|
|
amate
Joined: 29 Aug 2010 Posts: 14 Location: SPAIN
|
reading from ads1211 |
Posted: Wed May 21, 2014 1:38 pm |
|
|
sorry i erased this code line inside the main() :config_ADC();
Must be between two delays_ms(1000).
Thanks |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed May 21, 2014 4:02 pm |
|
|
If you want help, post a link to the schematic for your board.
This forum doesn't support image posting, so you need to post a link
to the schematic if you bought the board, or if you made the board
by yourself, then upload the schematic to a free image hosting website
such as http://postimage.org/ and post a link to it here.
----
Edited to put in correct link for image hosting service.
Last edited by PCM programmer on Mon Jun 29, 2015 3:33 pm; edited 1 time in total |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu May 22, 2014 3:25 am |
|
|
For studying your program we need to know what communication method you are using: 2, 3, 4, or multi-wire?
As PCM Programmer said, a schematic picture here will say more than 1000 words.
I can't solve your problem, but here are a few things I noticed to make your program better:
1) Your write_adc_byte(0 function is writing data to ADC_DI, but the write_adc_4byte() function writes to ADC_DO. Even without knowing your hardware connections this seems like a bug to me.
2) Variable types like int and long are not compatible between different compilers. Best is to use types like int8 and int32. You are already using int8, but instead of int32 you are using 'long long int'. Not wrong, but confusing.
3) Try to be consistent in how you code. For example you are using function names with capital letters and other times not, for example: 'output_low' and 'Output_low'. One for loop is counting 0 up to 8, the other from 1 up and including 32. The programming style for how you use the '{}' characters and indentation is different in many locations. etc.
4) The #use RS232 line always should include the 'ERRORS' parameter so the compiler can reset the UART in case of errors. Without this you have to write your own code to reset error conditions.
5) Code: | #FUSES HSH //High speed Osc, high power 16MHz-25MHz | According to comment this fuse is for 16<Hz or higher. You have defined a clock speed of 12MHz. Something is wrong here. |
|
|
amate
Joined: 29 Aug 2010 Posts: 14 Location: SPAIN
|
working with ADSS1211 |
Posted: Sun May 25, 2014 4:40 am |
|
|
You are right Ckielstra, there are many errors, I am learning.
I have modified according you, and modify the functions. Now I can read and write in all registers of ADS1211.
Was important to do reset in ADS. In self calibrate write values in registers OFF and FULL far from limits 0 and 0x7FFFFF, may be the consequence that DOR don't correspond with reality, it is smaller.
May be that the analog module of ADS were damaged?
Also, readings from DOR are 2% different. What can be the reason?
I will follow for solving these points.
Thanks a lot for your support.
Antonio Mate Code: | /*programa para probar el AD1211
use DRDY, SDIO,SCLK,connected to PIC according #defines
CS is conected permanently to ground(PIN D5=0)
DR=432, Vref=2.625, Channel=1;
*/
#include <18F46K80.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128
#FUSES NOXINST
#FUSES HSM //High speed Osc, high power 16MHz-25MHz
#FUSES NOPLLEN //4X HW PLL disabled, 4X PLL enabled in software
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES NOIESO //Internal External Switch Over mode disabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES BORV27 //Brownout reset at 2.7V
#FUSES WDT_SW //No Watch Dog Timer, enabled in Software
#use delay(clock=12000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#define ADC_DRDY PIN_D1
//#define ADC_DO PIN_D2
#define ADC_DIO PIN_D3
#define ADC_CLK PIN_D6
//-------------declarations--------------------
void write_adc_instr(char data); //send Instruction
void write_adc_byte(char value); //serial out of 1 bytes
void write_4byte(int32 value); //serial aout of 4 bytes
void write_adc_3byte(int32 value);
void set_command(int32 value); //send CMR
void config_ADC(void); //build and send CMR
void ADC_reset(void);
void ADC_self_cal(void);
void ADS_wait(void);
int8 read_adc_byte(void); //serial read 1 byte
int32 read_adc_3byte(void); //serial read 3 byte
int32 read_DOR(void); //serial read 3 byte of DOR
int32 read_ADC_full(void);
int32 read_ADC_off(void);
void set_ADC_offset(int32 value);
void set_ADC_full(int32 value);
void timer_04(void); //more times used => less rom
//--------------------minimum program for test--------------------
void main() //program for test diferents functions and ADS1211
{
int32 medida,full_data,off_data;
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_timer_4(T4_DISABLED,0,1);
input(ADC_DIO); // ADC_DI input
output_low(pin_D5); // chip select permanently
printf("Hola 1 - ");
config_ADC(); // configura el ADC
//ADC_self_cal();
set_ADC_offset(0x000000);
set_ADC_full(0x7FFFFF);
while(1){
medida = read_DOR();
full_data=read_ADC_full();
off_data=read_ADC_off();
printf("DOR = %LX ; off= %LX ;full= %LX ;DORd= %Lu \n\r",
medida,off_data,full_data,medida);
delay_ms(200);
}
}
//-------------------funtions definitions-------------------------------
void timer_04()
{delay_us(4);}
//------------------
void config_ADC(void)
{ ADC_reset();
ADC_self_cal();
char CMR0=0xB0,CMR1=0x04,CMR2=0,CMR3=0x80;
int32 comando;
comando=make32(CMR3,CMR2,CMR1,CMR0);
set_command(comando); //write 4 bytes in command address
}
//-------------------------
void ADS_wait(void)
{ while(!input(ADC_DRDY)); //waiting DRDY=1
while(input(ADC_DRDY)); //waiting falling DRDY
}
//------------------------------
void write_adc_instr(char data) //send 1 instr. byte
{ ADS_wait();
write_adc_byte(data);
input(ADC_DIO);
}
//-------------------
void write_adc_byte(char data) //send 1 instr. byte
{ int8 i;
timer_04();//delay_us(4);
for(i=0;i<8;++i) {
output_high(ADC_CLK);
output_bit(ADC_DIO,shift_left(&data,1,0));
timer_04();//delay_us(4); // > 5.5Txy; Txy=0.125 us with 8 Mhz clock
output_low(ADC_CLK);
timer_04();//delay_us(4);
}
input(ADC_DIO);
}
//---------------------
void write_adc_4byte(int32 data) //sen 4 byte serial
{ int32 data1=data;
int8 i;
timer_04();
for(i=1;i<=32;++i) {
output_high(ADC_CLK);
output_bit(ADC_DIO, shift_left(&data1,4,0));
timer_04();//delay_us(4);
output_low(ADC_CLK);
timer_04();//delay_us(4);
}
input(ADC_DIO); //ADC_DIO input direction
}
//----------------------------
void write_adc_3byte(int32 data) //sen 4 byte serial
{ int32 data1=data;
int8 i;
data1<<=8;
for(i=1;i<=24;++i) {
output_high(ADC_CLK);
output_bit(ADC_DIO, shift_left(&data1,4,0));
timer_04();//delay_us(4);
output_low(ADC_CLK);
timer_04();//delay_us(4);
}
input(ADC_DIO); //ADC_DIO input direction
}
//----------------------
void set_command(int32 value)
{
write_ADC_instr(0x64); //write to command addres 100
write_adc_4byte(value);
ADS_wait();
}
//---------------------
void set_ADC_offset(int32 value)
{write_adc_instr(0x48);
write_ADC_3byte(value);
}
//----------------------------
void set_ADC_full(int32 value)
{write_adc_instr(0x4C);
write_ADC_3byte(value);
}
//------------------------------
int32 read_adc_3byte(void) //read 3 Bytes
{
int8 i;
int32 data=0;
timer_04();//delay_us(4); // > 5.5Txy; Txy=0.125 us with 8 Mhz clock
for(i=1;i<=24;++i) {
output_high(ADC_CLK);
shift_left(&data,3,input(ADC_DIO));
timer_04();//delay_us(4);
output_low(ADC_CLK);
timer_04();//delay_us(4);
}
return (data);
}
//-----------------------------
char read_adc_byte(void) //read 1 byte
{
int8 i,data=0;
timer_04();//delay_us(4);
for(i=1;i<=8;++i) {
output_high(ADC_CLK);
timer_04();//delay_us(4);
shift_left(&data,1,input(ADC_DIO));
output_low(ADC_CLK);
timer_04();//delay_us(4);
}
return (data);
}
//-----------------------
int32 read_DOR() //read DOR register
{ int32 DOR_data;
write_ADC_instr(0xC0); //order for read 3 bytes beginig in addres 000
DOR_data=read_adc_3byte(); //read the 3 bytes
return DOR_data;
}
//--------------------
void ADC_reset(void) //reset ADS1211
{ output_high(ADC_CLK);
delay_us(37); //300*Txy
output_low(ADC_CLK);
delay_us(5);
output_high(ADC_CLK);
delay_us(87); // 700*Txy
output_low(ADC_CLK);
delay_us(5);
output_high(ADC_CLK);
delay_us(137); //1100*Txy
output_low(ADC_CLK);
delay_us(10);
}
//---------------------
void ADC_self_cal(void) //self calibration
{
write_ADC_instr(0x05);
write_adc_byte(0x20);
ADS_wait();
}
//----------------------------
int32 read_ADC_off() //Read OFF register
{int32 off_data;
write_ADC_instr(0xC8); //order for read 3 bytes beginig in addres 000
off_data=read_adc_3byte(); //read the 3 bytes
return off_data;
}
//------------------------------
int32 read_ADC_full() //Read FULL register
{int32 full_data;
write_ADC_instr(0xCC); //order for read 3 bytes beginig in addres 000
full_data=read_adc_3byte(); //read the 3 bytes
return full_data;
}
|
|
|
|
amate
Joined: 29 Aug 2010 Posts: 14 Location: SPAIN
|
Solved the problem |
Posted: Mon May 26, 2014 7:57 am |
|
|
Problem was the external erratic Vref, it very noisy.
Once I solved this, the software function correctly.
I am doing one circuit for read 4 PT1000/100 with ADS1211 and one micro,with automatic detection of type.
When finish I will facilitate the complete program.
Thanks a lot
antonio mate |
|
|
|
|
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
|