This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Port outputs OK in loop, but not in another part of program...

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).

Parents
  • Hi Erik,

    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?

Reply
  • Hi Erik,

    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?

Children
  • 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

    Erik

  • 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?

  • 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

    Erik

    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