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).
//---------------------------------------------------------------------------- // C main line //---------------------------------------------------------------------------- #include <regx52.h> #define TOTAL_LEDS 8 #define TOTAL_COLORS 8 #define LRGB 4 #define LED_TRACK_INDEX 7 // 0=step; 1=start_color; 2=end_color; 3=r_time; 4=g_time; 5=b_time; 6=up or down #define WARM_YELLOW 7 #define TOTAL_COLOR_COMBOS 36 #define TOTAL_STEPS 50 #define ONE_RAND_COUNT 24 // After 25 counts in main(), we're ready to generate the next randLED. #define ON_BIT 0 #define OFF_BIT 1 #define ON_PORT 0x00 #define OFF_PORT 0xFF #define TIMER_SET 55000 // counting 57,600 cycles is equal to 22.8ms sfr AUXR = 0x8E; sbit LED_0_R = P1^0; sbit LED_0_G = P1^1; sbit LED_0_B = P1^2; sbit LED_1_R = P1^3; sbit LED_1_G = P1^4; sbit LED_1_B = P1^5; sbit LED_2_R = P1^6; sbit LED_2_G = P1^7; sbit LED_2_B = P2^0; ... sbit LED_7_R = P3^5; sbit LED_7_G = P3^6; sbit LED_7_B = P3^7; static code const char color[TOTAL_COLORS][3] = { {0,0,0}, {7,0,0}, {6,0,7}, {0,2,7}, {0,5,0}, {7,7,0}, {7,6,0}, {7,7,7} }; static code const unsigned int rgbTiming[TOTAL_COLOR_COMBOS][TOTAL_STEPS] = { { ... }, { ... }, ..., { ... } }; unsigned int LEDs[TOTAL_LEDS][LED_TRACK_INDEX]; char randomizedLEDs[TOTAL_LEDS]; char randLED; char stepNum; char randPeriod = 0; // increment this to get ready to generate next randLED static void Timers_Init (); /******************************* * void main (void) * *******************************/ void main (void) { char randCount = 4; char i; char chipID; char LEDs_remain = TOTAL_LEDS*3; AUXR = AUXR | 0x01; // Turn off all LEDs, enable global interrupts, enable timer interrupts P0 = OFF_PORT; P1 = OFF_PORT; P2 = OFF_PORT; P3 = OFF_PORT; EA = 1; ET0 = 1; // Initialize timers: run as 16-bit timers that start with TRx=1 TMOD = 0x11; // Have the chip identify itself by the pull-up resistors on P0 pins // Delay all actions by 1s * chipID chipID = 0xFF - P0; for ( i = 0 ; i < 1000*chipID ; ++i ) { } P0 = OFF_PORT; // Depending on the chipID, assign the chip its LEDs. if ( chipID == 0 ) { randomizedLEDs[0] = 6; randomizedLEDs[1] = 5; randomizedLEDs[2] = 1; randomizedLEDs[3] = 4; randomizedLEDs[4] = 7; randomizedLEDs[5] = 0; randomizedLEDs[6] = 2; randomizedLEDs[7] = 3; } if ( chipID == 1 ) { ... } if ( chipID == 2 ) { ... } if ( chipID == 3 ) { ... } while (1) { // set up all LEDs to have start from white and end with white for ( i=0 ; i<TOTAL_LEDS ; ++i ) { LEDs[i][0] = 0; LEDs[i][1] = 7; LEDs[i][2] = 7; LEDs[i][3] = 50000; LEDs[i][4] = 50000; LEDs[i][5] = 50000; LEDs[i][6] = 1; } /************************************************************************* * SANITY CHECKER * * -------------- * * This part of the code, when run, actually produced desired results!!! * ************************************************************************* while (1) { P1 = ON_PORT; LED_0_R = OFF_BIT; LED_0_G = OFF_BIT; LED_0_B = OFF_BIT; LED_1_R = OFF_BIT; LED_1_G = OFF_BIT; LED_1_B = OFF_BIT; LED_2_R = OFF_BIT; LED_2_G = OFF_BIT; } */ /********************************************************************* * This next small block, turning on the LEDs, is what doesn't work. * * The ports' bits do -not- get set to 0 but instead remain HIGH. * *********************************************************************/ // Turn on all LEDs P1 = ON_PORT; P2 = ON_PORT; P3 = ON_PORT; // Start Timers to know when to turn off LEDs Timers_Init(); // Wait for all LEDs to be off before returning to program... while ( LEDs_remain ) { if ( ( LEDs[0][3] != 0 ) & ( LEDs[0][3] < (TL0 | TH0 << 8) ) ) { P1 = P1 & 0xFE; LEDs[0][3] = 0; --LEDs_remain; } //LED_0_R = OFF_BIT;} if ( ( LEDs[0][4] != 0 ) & ( LEDs[0][4] < (TL0 | TH0 << 8) ) ) { P1 = P1 & 0xFD; LEDs[0][4] = 0; --LEDs_remain; } //LED_0_G = OFF_BIT;} if ( ( LEDs[0][5] != 0 ) & ( LEDs[0][5] < (TL0 | TH0 << 8) ) ) { P1 = P1 & 0xFB; LEDs[0][5] = 0; --LEDs_remain; } //LED_0_B = OFF_BIT;} ... ... ... if ( ( LEDs[7][3] != 0 ) & ( LEDs[7][3] < (TL0 | TH0 << 8) ) ) { P3 = P3 & 0xDF; LEDs[7][3] = 0; --LEDs_remain; } //LED_7_R = OFF_BIT;} if ( ( LEDs[7][4] != 0 ) & ( LEDs[7][4] < (TL0 | TH0 << 8) ) ) { P3 = P3 & 0xBF; LEDs[7][4] = 0; --LEDs_remain; } //LED_7_G = OFF_BIT;} if ( ( LEDs[7][5] != 0 ) & ( LEDs[7][5] < (TL0 | TH0 << 8) ) ) { P3 = P3 & 0x7F; LEDs[7][5] = 0; --LEDs_remain; } //LED_7_B = OFF_BIT;} } /* while ( LEDs_remain ) */ } /* while (1) */ } /* main () */ /*********************************************** * void Timers_Init (void) * ***********************************************/ void Timers_Init (void) { // set the initial values of the timers; counting 20,000 cycles is equal to 10ms TH0 = (0xFFFF - TIMER_SET) >> 8; TL0 = (0xFFFF - TIMER_SET) & 0x00FF; // Start the timers TR0 = 1; } /******************************************************** * void Timer0_ISR (void) interrupt 1 * ********************************************************/ void Timer0_ISR (void) interrupt 1 { TR0 = 0; TH0 = 0xFFFF; TL0 = 0xFFFF; }