Other Parts Discussed in Thread: CD74HC4511, MSP-FET
Good Day,
Have a bit of a dilemma retrofitting an older machine that has been plaguing me for a couple of weeks .
Can't see a glitch in my code so possibly looking at something in the MSP-FET430UIF interface app notes that I missed .
Simple a2d converson to a three block of 7-seg common cathode led displays.
MSP430F2132 through CD74HC4511 (one / 7 segment).
No multiplexing, simple toggling decoder enable.
MSP-FET430UIF interface for in-target debug.
A2D input from a 3.3V supplied 10k potentiomter with a 1k resistor on the pot wiper at A4 input pin.
All unused MSP430F2132 I/O pins grounded.
Target cct power supplied from a bench top regulated supply, with additional filtered regulators (5V & 3.3V) on target board.
Oscilloscope shows flat DC voltage waveforms .
CD74HC4511 enable signals are 3.3V direct from the MSP430F2132 with all CD74HC4511's 5V suppied at their mains.
Cct brd is clean and free of shorts with all leads intact and going to where they should.
Situation is code works smoothly when initiated and run from the PC through the MSP-FET430UIF to the target.
7 seg digits are stable other than random jitter on bit one (0 to 1 to 0) as expected from standard potentiometer input device.
When the cct is run standalone the a2d values are anything less than stable with differences of up to 100+ in displayed values.
Stand alone = disconnected from PC and MSP-FET430UIF interface, MSP430F2132 pin 7 (RST) tied hi, all cct devices active through bench top supply
Thought it was a timing or possibly noise issue.
Have tried:
-diodes on the pot + and -
-various zener diodes across the +/- of the input pot to stabilize readings
-high precision 10 turn 10K pots
-ADC10SC, SMCLK, MCLK clock parameters and all clocking dividers for a2d conversion
-raw a2d value direct to CD74HC4511's
-scaled a2d value direct to CD74HC4511's
-overly simplified decoding of a2d value into separate digits for transport to CD74HC4511
-multitude of delay sequences to slow/speed up the display and a2d processes
-delays progressively down to 1 second per digit illumination still produced irratic displays during stand alone operation
-isolated grounds to negate ground loops
-separate 5V & ground benchtop power supply to run the CD74HC4511 devices
-different pc's
An off /off switch incorporated into the system (not part of the attached code) allowed stopping the a2d and recording the display O/P.
Although values appeared initially random, once enough were recorded a pattern of a 4 or 5 count between displays was evident.
A spacial difference of 4 was more predominant that 5 (i.e. 687, 691, 696, 680, 684)
I'm at a loss and don't have much hair left to pull out.
Any suggestions would be greatly appreciated.
L.
#include "io430.h" #include "in430.h" #include "intrinsics.h" // libraries #include "stdint.h" #include "stdio.h" // Firmware Variables unsigned int a2d_result = 0; // binary result from a to d conversion unsigned int cnt_val = 0; // LED_Display() value unsigned int delay_val = 5; // delay routine count unsigned int display_val = 0; // value sent to individual 7 segment displays unsigned int old_a2d = 0; // holds current a2d value unsigned int save_num = 0; // holder variable in LED_Display() unsigned int x = 0; // general delay counter variable // PORT 1 - Digital I/O #define DISPLAY_FET_ON P1OUT |= BIT4 // power to 7 segment displays on #define BEEP_OFF P1OUT &= ~BIT6 // system alarm off // PORT 3 Digital I/O #define O_ENABLE_HI P3OUT |= BIT6 // CD74HC4511 enable/disable signals (x3) #define O_ENABLE_LO P3OUT &= ~BIT6 #define T_ENABLE_HI P3OUT |= BIT5 #define T_ENABLE_LO P3OUT &= ~BIT5 #define H_ENABLE_HI P3OUT |= BIT4 #define H_ENABLE_LO P3OUT &= ~BIT4 void Delay (void) // general delay {for (x = delay_val; x > 0; --x) {while (!(TA0CCTL0 & CCIFG)) {;} TA0CCTL0 &= ~CCIFG; // Clear timer overflow flag } } void A2D_Sample (void) {old_a2d = a2d_result; // previous a2d value saved for comparison in main section ADC10CTL0 &= ~ENC; // Reset ADC10XTL0 register ADC10CTL0 = ADC10SHT_2 + ADC10ON; // sample & hold time 16 clock cycles, ADC10 active while (ADC10CTL1 & ADC10BUSY); // Wait if ADC10 core is already active ADC10SA = (unsigned int) &a2d_result; // a2d value auto-transfers to a2d_result from ADC10MEM ADC10CTL0 |= ENC + ADC10SC; // start sampling routine delay_val = 5; Delay(); // a2d process settle delay cnt_val = ((int)(a2d_result * 0.977)); // scale a2d value to 3 digits - utilized in LED_Dispaly() } void Cnt_Send (void) {switch (display_val) {case 0: P1OUT |= 0x00; break; // "0" value to be sent to BCD data buss case 1: P1OUT |= 0x01; break; // "1" value to be sent to BCD data buss case 2: P1OUT |= 0x02; break; // "2" value to be sent to BCD data buss case 3: P1OUT |= 0x03; break; // "3" value to be sent to BCD data buss case 4: P1OUT |= 0x04; break; // "4" value to be sent to BCD data buss case 5: P1OUT |= 0x05; break; // "5" value to be sent to BCD data buss case 6: P1OUT |= 0x06; break; // "6" value to be sent to BCD data buss case 7: P1OUT |= 0x07; break; // "7" value to be sent to BCD data buss case 8: P1OUT |= 0x08; break; // "8" value to be sent to BCD data buss case 9: P1OUT |= 0x09; break; // "9" value to be sent to BCD data buss }} void LED_Display (void) // break down a2d value to individual numbers (100's, 10's 1's) {display_val = (cnt_val / 100); // hundreds display value save_num = (display_val * 100); // save hundreds value (integer form) to be used in 10`s calculation P1OUT &= 0xF0; // reset port 1, bits 1 thru 3 - BCD data buss Cnt_Send(); // port 1 bits 0 to 3 data buss preparation routine H_ENABLE_LO; // 100's digit CD74HC4511 enable signal on delay_val = 10; Delay(); H_ENABLE_HI; // 100's digit CD74HC4511 enable signal off delay_val = 10; Delay(); display_val = (((cnt_val - (save_num)) / 10)); // tens display value save_num = ((save_num) + (display_val * 10)); // save hundreds value (integer form) to be used in 10`s calculation P1OUT &= 0xF0; // reset port 1, bits 1 thru 3 - BCD data buss Cnt_Send(); // port 1 bits 0 to 3 data buss preparation routine T_ENABLE_LO; // 10's digit CD74HC4511 enable signal on delay_val = 10; Delay(); T_ENABLE_HI; // 10's digit CD74HC4511 enable signal off delay_val = 10; Delay(); display_val = (cnt_val - (save_num)); // ones display value P1OUT &= 0xF0; // reset port 1, bits 1 thru 3 - BCD data buss Cnt_Send(); // port 1 bits 0 to 3 data buss preparation routine O_ENABLE_LO; // 1's digit CD74HC4511 enable signal on delay_val = 10; Delay(); O_ENABLE_HI; // 1's digit CD74HC4511 enable signal off delay_val = 10; Delay(); P1OUT &= 0xF0; // ensure all CD74HC4511 enable signals are off cnt_val = 0; // reset cnt_val to 0000 (debug tool to ensure new value in cnt_val for each pass thru) } #pragma vector=TIMER0_A0_VECTOR // timer_a interrupt __interrupt void Timer0_A0 (void) { } void main (void) {WDTCTL = WDTPW + WDTHOLD; // stop watchdog timer BCSCTL1 = XT2OFF; // oscill2 off P1DIR = 0xFF; // port 1: all outputs P1SEL = 0x00; // port 1: digital I/O P1REN = 0x00; // port 1: pull up resistors off P1OUT = 0x20; // port 1: all outputs in low state except P1.5 LED off(1), P1.6 beeper off(0) P3DIR = 0xFF; // port 3: all output P3SEL = 0x00; // port 3: all digital I/O P3REN = 0x00; // port 3: pull up resistors off P3OUT = 0xFF; // port 3: pins 1-6 hi (bcd to 7 seg chip enables off) (1111 1111) __enable_interrupt(); // enable all interrupts // TA0 - alarm & Delay() timers TA0CCR0 |= 990; // material counter & delay timers TA0CCTL0 |= CCIE; // enable TA0CCR0 interrupt flag at count overflow TA0CTL = TASSEL_2 + MC_1 + ID_0 + TACLR; // smclk source, up mode, /1, clear counter ADC10CTL0 = SREF_0 + ADC10SHT_2 + ADC10ON; // *16,ADC10 register active ADC10CTL1 = INCH_4 + ADC10DIV_0 + ADC10SSEL_0 + CONSEQ_0; // A4,ADC10SC bit, ADC10AE0 |= 0x04; // enable control register - analog input A4 enabled ADC10DTC1 = 0x001; // enable data transfer control register, 1 block transfer DISPLAY_FET_ON; // turn 7 segment display power delay_val = 5; // 7 segment display settle delay Delay(); LED_Display(); // initial speed display - required to illuminate display while (1) {A2D_Sample(); // a2d sample if (((a2d_result + 3) < old_a2d) || ((a2d_result - 3) > old_a2d)) // a2d value change > 3 count LED_Display(); } }