Can someone tell me why this code doesnt do its job? I am new to uVision. The code should turn on the LED diodes as you turn the potentiometer. For example, if its on position 0V the first LED should be lit, and if its on position 3.3V the last one. Tnx in advance
#include <stdio.h> #include <stdlib.h> #include <LPC214x.h>
void delay(int i){ unsigned int j; for(j=0; j < i; j++); }
int main (void) { unsigned int rez; IODIR1 = 0x00FF0000; //diode postavljene kao output AD0CR = 0x00200402; //ADC1: 10-bit AIN1 @ 3MHz
while(1){ AD0CR |= 0x01000000; // start AD konverzije
while ((AD0DR1 & 0x80000000) == 0); // cekanje da se konverzija zavrsi
AD0CR &= ~0x01000000; //stop AD konverzije rez = AD0DR1 & 0x0000FFC0; if(rez < 128) IOSET1 = 1 << 16; else if(rez > 128 && rez < 256) IOSET1 = 1 << 17; else if(rez > 256 && rez < 256+128) IOSET1 = 1 << 18; else if(rez > 256+128 && rez < 512) IOSET1 = 1 << 18; else if(rez > 512 && rez < 512+128) IOSET1 = 1 << 19; else if(rez > 512+128 && rez < 768) IOSET1 = 1 << 20; else if(rez > 768 && rez < 768+128) IOSET1 = 1 << 21; else if(rez > 896 && rez < 1024) IOSET1 = 1 << 22; else IOSET1 = 1 << 23;
delay(100000); }
}
You seem new to this forum too. Note the posting instructions for source code directly above the message input box.
You have a lot of IOSET1 use. That will set new diodes. It will not turn off other diodes.
Next thing is that you mask out the ADC data with AD0DR1 & 0x0000FFC0. That means that the minimum value you get out is zero. Next value is 64. Next is 128. The largest value is exactly your mask 0x0000FFC0 = 65472.
But you only compare values up to 1024.
The solution is that the value you get out from AD0DR1 should be shifted right 6 steps before being assigned to rez. Then you will have an ADC range from 0 to 1023, and your comparisons would be much eaiser to do.
But then again you could divide (or shift) yet more, so you make the value 128 times smaller. So instead of 0..1023 it would be 0..7. That would directly represent your 8 different bar steps.
I modified the code like this and it is still not working... :/
#include <stdio.h> #include <stdlib.h> #include <LPC214x.h> void delay(int i){ unsigned int j; for(j=0; j < i; j++); } int main (void) { unsigned int rez, val; IODIR1 = 0x00FF0000; //diode postavljene kao output AD0CR = 0x00200402; //ADC1: 10-bit AIN1 @ 3MHz while(1){ IOCLR1 = 0x00FF0000; //gasenje svih LED AD0CR |= 0x01000000; // start AD konverzije while ((AD0DR1 & 0x80000000) == 0); // cekanje da se konverzija zavrsi AD0CR &= ~0x01000000; //stop AD konverzije val = AD0DR1 & 0x0000FFC0; rez = val >> 6; if(rez < 128) IOSET1 = 1 << 16; else if(rez > 128 && rez < 256) IOSET1 = 1 << 17; else if(rez > 256 && rez < 256+128) IOSET1 = 1 << 18; else if(rez > 256+128 && rez < 512) IOSET1 = 1 << 18; else if(rez > 512 && rez < 512+128) IOSET1 = 1 << 19; else if(rez > 512+128 && rez < 768) IOSET1 = 1 << 20; else if(rez > 768 && rez < 768+128) IOSET1 = 1 << 21; else if(rez > 896 && rez < 1024) IOSET1 = 1 << 22; else IOSET1 = 1 << 23; delay(10000); } }
What do you mean, it is not working? Does it go up in smoke? Does the code hang? Do any of the LEDs come on? What steps have you tried to debug?
Isolate the problem to either the LEDs or the ADC read, such as placing a IOSET1 = 0x00FF0000 just after the while(1) and before the IOCLR1. The breakpoint before the IOCLR1.
Did the Leds get bright? If they did, single step through the IOCLR code. Did the LEDs go OFF?
Breakpoint after the ADC stop code and enter a known pattern in val. Step through your code.
Did the shifts move the LED pattern as you expected?
Do you get the idea? You break the code into simple blocks and make that block of code work the way you expect then move to the next simple block of code.
Bradford
Well, I am not very good at debuging (but I did my best). I put a breakpoint before the if cases, and when I look at the values of rez and val it sais they are 0x00000000 both. This makes sense, because when I run the program only the first LED is on (which is from case rez < 128). Another interesting fact is that the AD0DR1 register is also 0x00000000 (which gives the value to rez and val). Why is it so, I wouldnt know... :/
Are my conversion steps right? 1. I start the conversion 2. Wait for it to finish 3. Stop it
And then I just read the results... It should work... :/
Any ideas?
I don't work with your specific processor, but have you verified that the ADC is powered before you start to initialize it? And have you verified the initialization? What differs compared to sample code available from Keil or NXP?
This line of code
AD0CR = 0x00200402; //ADC1: 10-bit AIN1 @ 3MHz
initializes the ADC (power up and everything needed). There is no sample code that does what I need. Its a slight variation (and I started from it, by modifying it).
I'm pretty sure you have a bit in PCONP that is important too. Just that I do believe it already defaults to the correct value.
But another thing - have you switched the input pin from digital function to analog function? I don't see you assign anything to any PINSELx register.
"But another thing - have you switched the input pin from digital function to analog function? I don't see you assign anything to any PINSELx register."
I dont understand this. The AD0CR controls which channel are you using (the value 0x02 setts this to AIN1). And AIN1 is connected to the potentiometer trough a jumper, so you dont have to initialize the input. Its already connected as default. If you want to take a look here is the schematic http://www.keil.com/mcb2140/mcb2140-schematics.pdf (go to second page)
Did you spend time with the manual, reading about the PINSELx registers?
Dod you read through the full chapter about the ADC in the user manual?
Did you specifically read the information in the paragraph 19.5.3 Accuracy vs. digital receiver?
The NXP user manual is the #1 document to read through when using the processor.
As I said earlier, I don't work with any LPC21xx chips. So I don't have a reason to invest the time to read up on all the details. I spend my time reading the documentation for the processors I use.
But you have a big reason to invest the time with the LPC214x user manual. www.nxp.com/.../UM10139.pdf
It worked, even tough I dont quite get it. I add this code
PINSEL1 = 0x01080000; // Select DAC (AOUT) & AIN1
to the source. Btw, I did read the manual many times... Tnx for your help, both!