CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

MCP4921 showing weird behavior

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
jaethelegend
Guest







MCP4921 showing weird behavior
PostPosted: Mon Jun 15, 2009 12:07 am     Reply with quote

Please note that I have posted same problem to microchip forum.

I'm experimenting with the MCP4921 chip.
The code is supposed to copy the input voltage in B0 port and output the same voltage through DAC.
With Vss to Ground, Vref to 5V, LDAC to ground,
It shows strange behavior.
When I am expecting 5V, the output is 5V.
However, When I am expecting 0V, I get 2.5V.

In other words, the output range is pretty much halved.
With playing with Vref, I found out that the output voltage range is 0.5Vref~Vref with 12bit resolution.

So, with Vref = 5, and when I enter code for 1V output, I get 2.5+2.5/5 = 3V

Below is the coding
Code:

#include<C:\Documents and Settings\Microsoft\My Documents\PIC\Header\16f886.h>
#include<C:\Documents and Settings\Microsoft\My Documents\PIC\Header\def_16f886.h>

#use delay(clock = 1000000)
#fuses INTRC_IO

#define CS PORTC6

#include<C:\Documents and Settings\Microsoft\My Documents\PIC\project1\ADC2DAC\16by2flex_lcd.h>

int16 adc_in = 0;
int16 dac_out = 0;
int16 one_digit = 0;
int16 ten_digit = 0;
int16 hund_digit = 0;
int16 thou_digit = 0;
int16 disp_number = 0;
int8 high_byte = 0;
int8 low_byte = 0;
int8 dummy = 0;

void init_rtn(){
setup_adc(ADC_CLOCK_DIV_32);
ANSEL = 0x00;
ANSELH = 0x00;
SETUP_ADC_PORTS(SAN13);
TRISB5 = 1;
set_adc_channel(13);

lcd_init();
lcd_send_byte(1,CURSOR_OFF_BLINK_OFF);
lcd_gotoxy(1,1);
LCD_putc("Incoming Voltage");
lcd_gotoxy(7,2);
lcd_putc(".");
lcd_gotoxy(9,2);
lcd_putc("V");

setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_4);
TRISC6 = 0;

LDAC = 1;
CS = 1;
}

void bcd_rtn(int16 buffer){
thou_digit = buffer/1000;
buffer-=thou_digit*1000;
hund_digit = buffer/100;
buffer-=hund_digit*100;
ten_digit = buffer/10;
}

void disp_rtn(int16 buffer){
bcd_rtn(buffer);
lcd_gotoxy(6,2);
lcd_putc(ascii_num_tbl[thou_digit]);
lcd_gotoxy(8,2);
lcd_putc(ascii_num_tbl[hund_digit]);
lcd_gotoxy(9,2);
lcd_putc(ascii_num_tbl[ten_digit]);
}

void main(void){
init_rtn();

while(1){
  adc_in = READ_ADC();
  disp_number = adc_in*5;
  disp_rtn(disp_number);
  CS = 0;
  dac_out = adc_in*4;

  dummy = dac_out>>8;
  dummy &= 0x0f;
  high_byte = dummy|0x70;
  low_byte = dac_out;

  SPI_WRITE(high_byte);
  SPI_WRITE(low_byte);

  LDAC = 0;
  delay_ms(100);

  CS = 1;
 }
}

Note that I have tried entering values directly in place of high_byte and low_byte for example,
Code:

SPI_WRITE(0x70);
SPI_WRITE(0x00);

With this coding in place of
Code:

SPI_WRITE(high_byte);
SPI_WRITE(low_byte);

I don't get 0V as an output but get 2.5V instead.

Anybody have idea??

Thanks
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Mon Jun 15, 2009 10:07 am     Reply with quote

This does not look correct:

Code:

set_adc_channel(13);

How do you get 13 when this part only has 11 A/D channels?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jun 15, 2009 11:09 am     Reply with quote

Quote:
#use delay(clock = 1000000)

Do you really want to run the internal oscillator at 1 MHz ?
Quote:
setup_adc(ADC_CLOCK_DIV_32);

If so, 1/32 is not the correct divisor value for the ADC. Look in the
ADC section of the 16F886 data sheet to see the correct divisor.
Look in the 16F886.h file to see the list of divisor constants.


Quote:
setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_4);

You have setup the SPI module to use Mode 1. See the list below:
Code:
// SPI mode definitions.
#define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1  (SPI_L_TO_H)
#define SPI_MODE_2  (SPI_H_TO_L)
#define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

But the MCP4921 data sheet clearly says that it only supports
modes 0 or 3. It won't work correctly in Mode 1. Look on pages
18 or 19 of the data sheet to see this:
http://ww1.microchip.com/downloads/en/DeviceDoc/21897B.pdf


Also, your MCP4921 code is written "inline" instead of being made into
functions, so it's not easy to understand and it's also easy to make errors.
jaethelegend
Guest







Another question.
PostPosted: Thu Jun 18, 2009 8:38 am     Reply with quote

Quote:
How do you get 13 when this part only has 11 A/D channels?

It is true that there are only 11 channels for 16f886 but with 3 missing channels for corresponding channel numbers.


Another question for pcm programmer,

Using internal ADC doesn't seem to yield the expected value.
For example, with Vdd=5 as a reference, if I put in 2.5V, i do not get 1023*0.5 but something else.
Also, even after I switched the ADC frequency accordingly(actually, i have tried all different ADC clock frequencies), my incoming AD converted signal is very noisy(swings rapidly) even when the voltage is fed through precision calibrator.

The situation doesn't show improvement, when I change the reference voltage to external(which is also stable).

What is the problem? would using external ADC solve it?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jun 18, 2009 10:42 am     Reply with quote

Quote:
Using internal ADC doesn't seem to yield the expected value.

Post a test program that shows how you are testing this. Example:
http://www.ccsinfo.com/forum/viewtopic.php?t=32168&start=1

Also post a description of the circuit which is driving the ADC input pin.


Quote:
if I put in 2.5V

How do you know the voltage is 2.5 volts ? Have you used an
oscilloscope to look at the pin's voltage ? Is the voltage a DC level ?
Is it a steady level ? (always at 2.5 volts)
jaethelegend
Guest







PostPosted: Thu Jun 18, 2009 9:42 pm     Reply with quote

Here is the coding

Code:

#include<C:\Documents and Settings\Microsoft\My Documents\PIC\Header\16f886.h>
#include<C:\Documents and Settings\Microsoft\My Documents\PIC\Header\def_16f886.h>

#use delay(clock = 1000000)
#fuses INTRC_IO

#define CS PORTC6
#define VinRef 1
#define   VoutRef 2

#include<C:\Documents and Settings\Microsoft\My Documents\PIC\project1\ADC2DAC\16by2flex_lcd.h>

int16 adc_in = 0;
int16 dac_out = 0;
int8 one_digit = 0;
int8 ten_digit = 0;
int8 hund_digit = 0;
int8 thou_digit = 0;
int16 disp_number = 0;
int8 high_byte = 0;
int8 low_byte = 0;
int8 dummy = 0;
int8 counter = 0;


void init_rtn(){
//A/D converter initiation.
setup_adc(ADC_CLOCK_DIV_2);
ANSEL = 0x00;
ANSELH = 0x00;
SETUP_ADC_PORTS(SAN1);// Analog input is RA1 pin
TRISA1 = 1;
VCFG0 = 1; //External Vref+
set_adc_channel(1);

//LCD initiation.
lcd_init();
lcd_send_byte(1,CURSOR_OFF_BLINK_OFF);
lcd_gotoxy(1,1);
LCD_putc("Incoming Voltage");
lcd_gotoxy(7,2);
lcd_putc(".");
lcd_gotoxy(9,2);
lcd_putc("V");
//SPI Module initiation.
setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_XMIT_L_TO_H|SPI_CLK_DIV_4); //Using SPI MODE 0

//Chip select initiation.
TRISC6 = 0;
CS = 1;
}


void bcd_rtn(int16 buffer){
thou_digit = (int16)buffer/1000;
buffer-=(int16)thou_digit*1000;
hund_digit = (int16)buffer/100;
buffer-=(int16)hund_digit*100;
ten_digit = buffer/10;
}


void disp_rtn(int16 buffer){
bcd_rtn(buffer);
lcd_gotoxy(6,2);
lcd_putc(ascii_num_tbl[thou_digit]);
lcd_gotoxy(8,2);
lcd_putc(ascii_num_tbl[hund_digit]);
lcd_gotoxy(9,2);
lcd_putc(ascii_num_tbl[ten_digit]);
}

void DAC_RTN(void){
      CS = 0;
      dac_out = adc_in*4;

      dummy = dac_out>>8;
      dummy &= 0x0f;
      high_byte = dummy|0x70;
      low_byte = dac_out;
      SPI_WRITE(high_byte);
      SPI_WRITE(low_byte);
      CS = 1;
}


void main(void){
init_rtn();

   while(1){
      adc_in = READ_ADC();
      disp_number = adc_in*5;
      disp_rtn(disp_number);
      DAC_RTN();
   }
}

I am certain that the input voltage is 2.5V since it is generated by FLUKE 702 calibrator. I also measured it using another calibrator, while the voltage is fed through the voltage input.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jun 18, 2009 11:13 pm     Reply with quote

Post your compiler version.
jaethelegend
Guest







Compiler version
PostPosted: Fri Jun 19, 2009 2:47 am     Reply with quote

It is 4.057. (PC B,M,H,D)
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jun 19, 2009 2:57 pm     Reply with quote

I installed vs. 4.057 and compiled the test program shown below.
I set the AN0 pin to 2.50 volts, and checked it with a voltmeter.
The voltage is set with a 5K trimpot, with the knob set in the middle
position. The A/D converter is setup for default 8-bit output mode.
The program gives the following results, and it's correct:
Quote:
127
127
127
127
127
127
127
127

You wanted to use INTRC at 1 MHz, so I did the same thing.
I had to reduce the baud rate to 4800, because 9600 will not give good
results with a 1 MHz clock.
Code:
#include <16F886.h>
#fuses INTRC_IO, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=1000000)
#use rs232(baud=4800, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

//====================================
void main()
{
int8 result;

setup_adc_ports(sAN0);
setup_adc(ADC_CLOCK_DIV_2);
set_adc_channel(0);
delay_us(20);

while(1)
  {
   result = read_adc();
   printf("%u \n\r", result);
   delay_ms(500);
  }

}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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