We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi all,
Glad to have found this forum a little over a week ago. I've been referring to it frequently to help with writing my program, and found a lot of useful information in here. Thank you, contributing posters, for all the help you've already given me.
However, right now I'm stuck with another problem with my program, for which I've poured over the AT89S52 datasheet, Atmel 8051 Microcontrollers Hardware Manual, and Google results but so far to no avail.
I'm writing what should be a simple program. The program lights 30 LEDs with PWMs that updates each LED 30 times per second. Because each LED consists of a R, G, and B component, a total of 90 PWM output pins are necessary. I'm therefore using four AT89S52, with Port 0 being used with pull-ups/downs to distinguish among tasks assigned to the specific IC.
The basic algorithm is this:
(1) calculate (with the aid of a large look-up table) the amount of time that each color of each LED is to be lit during the next lighting; (2) turn on all colors of all LEDs (they're driven by a P-channel transistor); (3) start Timer 0 as 16-bit timer, to time 55,000 counts; (4) manually go through and check each LED's timing requirement against TH0 and TL0, and turn each one off as the Timer counts past it; (5) once all LEDs are turned off, jump back to (1).
The problem I'm running into is that during step (2), the ports do not turn on, and therefore the LEDs do not turn on. Just as a sanity check, I've put in a while(1){...} loop at the start of the program that turns on the LEDs on Port 1 and then switch them off one by one. This sanity checker uses the same syntax as that used by the later part of the program.
The sanity checker runs just fine when viewed under the oscilloscope. The real program, however, does not run properly, albeit compiling and logically functioning perfectly in the debugger.
Some things I've considered and tried but did not help:
(a) Program might be too large; however, I did not get the "auto segment too large" or any other similar-sounding errors; (b) Using Boolean to set the bits as well as directly assigning the desired value; (c) Setting the Code Optimization to 0: Constant folding; (d) Disabling the ALE (AUXR - 8Eh to 0x01); (e) Setting the ports using HEX values instead of #defined values; (f) Changing to a new AT89S52; (g) Checking for excessive noise on the connections; (h) Writing to the port twice in a row (different values, returning to 0x00), just to be sure;
... and a few other equally silly things that I nevertheless thought could've caused trouble.
The hardware is also excessively simple:
-> VCC and nEA/VPP to 5V (DC Source) -> GND to DC Source's GND -> ALE and nPSEN are NC -> XTAL1 & 2 are connected to a 24 MHz crystal with a pair of 30pF capacitors -> RST is connected to a floating wire that I use to touch 5V at the start for reset -> Port 1, bit 0 is connected to a P-channel transistor which is in turn connected to another voltage source and the Red component of an LED. -> Port 0 has 10K-Ohm pull-up resistors for chip identification. -> All remaining pins are port pins and have been left floating. They should be outputting, but are not.
Ports 0 and 2 have been observed under the oscilloscope to be actively switching, though judging by the pulse widths the activity has nothing to do with what the program intended.
I'm sure the solution is simple and obvious, but it is one that has so far eluded me. I was wondering if you gurus could please give me a hand here?
Because of the length of the code, I'm presenting a shortened version which I've compiled and run, with the exact same results. I've also marked out the sanity checker code that runs properly, as well as the tiny code block that doesn't seem to be doing what it's supposed to do.
Thanks in advance for any help you might have for me. The code will be included in the following post in response to this (since I've exceeded the message size limit).
Hi Erik,
Okay, I got what you meant. You meant to suggest that I check the states of the output pins by hanging the program as soon as the pins have been set to 0, because you suspected that the pins were switched to HIGH by the code below, right?
If indeed they were switched low by the code and then brought back up immediately by the code below, you'd think that I'd see the switching on the oscilloscope -- the downward pulses should have at least a 500ns width (since I'm using a 24MHz crystal), but I saw nothing, not even immediately after RESET.
But just for sanity checking I tried what you suggested. The pins still remained at a steady 5V.
Hi Hans,
Thank you for replying.
Unfortunately, I didn't forget to tie the nEA/VPP pin to HIGH. Unfortunate that it wasn't that simple. :P I mentioned this while describing how I connected the hardware, in an earlier post ...
In my continued investigations, I've discovered something new that I embarrassingly missed earlier. I realized that the Port 3 pins 6 & 7 were actually also switching. These are the nRD and nWR pins, which strobe external access read and write, respectively. The fact that there's activity on these pins correlates with the presence of activity on Ports 0 and 2, apparently indicating that the chip is indeed trying to access external memory.
But how is this possible?! nEA/VPP is tied to 5V! And my code isn't that large! When I compiled, here's the result:
Build target 'Target 1' assembling STARTUP.A51... compiling XmasTree.c... linking... Program Size: data=9.0 xdata=126 code=6058 creating hex file from "XmasTree"... "XmasTree" - 0 Error(s), 0 Warning(s).
Argh.
So far, we've managed to greatly reduce the suspicion on the following (arrow text shows what I did): (a) Program might be too large -----> No "auto segment too large" or other similar errors. -----> HOWEVER, when I changed the compiler's "Memory Model" option from "Large: variables in XDATA" to "Compact: variables in PDATA", as well as the "Code ROM Size" option from "Large: 64K program" to "Compact: 2K functions, 64K program", the code still compiled with no errors or warnings, but the program did not run properly in the debugger -- some variables did not get assigned when they were supposed to. (b) Using Boolean vs. using direct port assignment (c) My crappy code breaking in compiling/linking -----> Tried setting Code Optimization option to "0: Constant folding" (d) Disabling the ALE (AUXR - 8EH TO 0x01) (e) Using HEX values for assignment instead of #defined values(f) Chip issue -----> by trying a couple of other AT89S52 ICs (g) Signal noise -----> Maximum noise I found only had 0.7V amplitude on the power lines, and overshoot/undershoot were all around only 0.2~0.3V. (h) Port mode related: -----> Writing to the port twice in a row (different values, returning to 0x00), just to be sure (i) Chip ID pull-ups on Port 0 causing issues -----> Disabled the relevant code (j) Code beneath the "ports turn on" code that might turn off the ports -----> Erik's while(1) recommendation (k) Array bits vs. port bits (Erik's recommendation) -----> Assigning the port pins one at a time didn't help
---------------------------------- Currently we're still suspecting: Port 0 & 2 trying to access external memory?! -----> But nEA/VPP is tied to 5V -----> But program size is not too large
Any additional input greatly appreciated... thank you all in advance.
But how is this possible?! nEA/VPP is tied to 5V! !EA/Vpp refer to code memory. however p3.6/.7 should not move unless do a read/write via the dptr maybe Arghmel has that one wrong or are you runnong the large model? If I recall your chip does not have internal xdata.
Erik
But just for sanity checking I tried what you suggested. The pins still remained at a steady 5V. impossible
#define ON_PORT 0x00 .... // Turn on all LEDs P1 = ON_PORT; equivalent to P1 - 0;
did you do EXACTLY what I suggested? does the code even get there?
BTW since you have chosen a project that is likely to require quite a bit of debugging, why did you choose Arghmel chips, not SILabs, or do you have an ICE?
Hehe, "impossible" is right! But I know what I saw was correct because I literally took pictures of the board connections, and the oscilloscope waveform, and compared with my code.
All the pins should be at 0V, but they showed 5V on the 'scope.
This point, however, is now obsolete; please allow me to explain.
In a prior post you mentioned XDATA and the presence of it or lack thereof in the AT89S52. Because of the activities I saw on Port 0, Port 2, and the nRD and nWR pins, I concentrated my debugging on the topic of "external access". Looking at the disassembler, I found a lot of MOVX instructions, and suddenly remembered that I had turned on the XDATA compiler option.
I then went through my variables and fine-tuned the one called LEDs[][] which was an unsigned int. Well, 60% of that could have been just unsigned char, and so I broke it up into two.
Then I had enough space to fit all my variables inside DATA and static variables in CODE.
I ran the code on the chip again and, holy smoke, there was no activity on any of the nRD/nWR/P0/P2 pins at all!! And the LEDs worked! They dimmed up and down, changed color... albeit the 30 blinks / second being actually visible. I thought human eyes could perceive... nevermind, a little bit more research and some tuning on the frequency would be just the thing.
In the end, this painful bug was simply due to carelessness in declaring variables and adjusting compiler options.
But this painful experience was also a good learning experience.
As to your final question about why I chose Atmel... It was basically because I just have easy access to some. I was originally going to use a Cypress PSoC for their large number of I/O pins and good speed, but our lab and factory here do not have a programmer for the Cypress PSoC, and it was also difficult to actually get a hold of these chips where I am and the environment I'm in.
No, I do not have an ICE for the AT89S52. Also, this is the first time in 12 years that I've done any firmware programming or working with an embedded system. Debugging-wise, Keil works well enough once one gets used to it. But in any case, this project is more for fun than anything else; and if I accidentally started with a more difficult-to-work-with chip, then it'd only help when I switch to, as you mentioned, a C8051F36x.
That was the chip you were referring to, right? The hand-soldering's gonna be a bizzatch...
By the way, do you happen to have any recommendations for a solid MP3 decoder?
suddenly remembered that I had turned on the XDATA compiler option. as I guessed above: using 'large'. never use 'large', it is the lazy mans way out. It eats resources and time. The only 'excuse' would be a one-off throwaway code. If you run out of DATA selectively move stuff to XDATA.
if I accidentally started with a more difficult-to-work-with chip, then it'd only help when I switch to, as you mentioned, a C8051F36x. That was the chip you were referring to, right?
No, it is one of the chips I referred to. SILabs has JTAG debugging (which would have solved your quandry in about 2 minutes instead of 3 days communicating on a forum) and also has 8-porters(64 I/O pins) both seems to be a better choice for what you are doing.
By the way, do you happen to have any recommendations for a solid MP3 decoder? WHAT! this is a Keil forum ;) no, I do not
Hi Erik.
I actually thought that having the nEA pulled high meant that XDATA accesses would fail. Guess I guessed wrong, as shown by the 80C51 Family Architecture, which is part 1 of the "Bible" that you directed to me. Incidentally, I could only download the first PDF for some reason.
You mentioned selectively moving things to XDATA. However, this would entail the use of an external ROM device (if the main microcontroller doesn't have one in itself), right? In my case, it would mean fewer pins for lighting up the LEDs, and thereby forcing me to use more and more Arghmel 89S52 chips...
Well, thank you for your input. :) Though I didn't always interpret what you said in a manner that helped me as quickly as could have been, I do appreciate the virtual company as I trudged through this.
never use 'large', it is the lazy mans way out..
Erik, you really are an old dog!
See here: http://www.keil.com/forum/10196/
Remember it?
I stand by my opinion.
part 1 of the "Bible" that you directed to me. Incidentally, I could only download the first PDF for some reason.
te 'bible' chapters in order of 'value' ch3 ch2 ch1
you just managed to get the least valuable
PS if there is a link to he whole 'bible' do not use it
ch1, ch2 and ch3 are the only ones of value, the rest is datasheets for discontinued chips