Author Topic: Atmega32U4 PORTD refuses to read inputs  (Read 1692 times)

0 Members and 1 Guest are viewing this topic.

Offline trini8edTopic starter

  • Newbie
  • Posts: 8
  • Country: us
Atmega32U4 PORTD refuses to read inputs
« on: December 04, 2020, 01:57:48 pm »
Hello, been working on a propagation delay testing circuit and am having more problems with this atemga32u4 chip |O. I have setup PORTD in whichever way floating and with input pull-up but cannot seem to get it to detect any change. I have a button on my board to get me in the main while loop in the delay_test() function. Here it spins its wheels just outputting the values on PORTD to the segment but it just always seems to stay at C7 never changes PD1 regardless if I externally apply 5v to that pin. I feel that i'm missing something small here but I appreciate the help thanks.


Code:
Code: [Select]
// propagation.c
// Bradley Heenk
// For Rev 1.0 Board
// 11/16/2020

// HARDWARE SETUP:

// Segments are hooked up
// PORTA -------------------------------------------------------------------------------------------------------
// PORTA0-7 are connected to the segments of the LED display.

// PORTB -------------------------------------------------------------------------------------------------------
// PORTB6 goes to the A selector on our 74LVC1G139 decoder for our units LED's
// PORTB7 goes to the B selector on our 74LVC1G139 decoder for our units LED's

// PORTD -------------------------------------------------------------------------------------------------------
// PORTD0 is used as an interrupt to detect when the output signal has propagated through to stop the timer
// PORTD1 is used as an interrupt to detect when the relay is latched and starts the timer
// PORTD2 is used as an interrupt to detect a button press and turn on the relay
// PORTD6 goes to the A selector on our 74LVC1G139 decoder for our segment digit select
// PORTD7 goes to the B selector on our 74LVC1G139 decoder for our segment digit select

// PORTF & PORTC -----------------------------------------------------------------------------------------------
// PORTF0 is used as an output for our segment for A
// PORTF1 is used as an output for our segment for B
// PORTC6 is used as an output for our segment for C
// PORTC7  is used as an output for our segment for D
// PORTF4 is used as an output for our segment for E
// PORTF5 is used as an output for our segment for F
// PORTF6 is used as an output for our segment for G
// PORTF7 is used as an output for our segment for DP

// pseudo code
// 1) Setup the interrupts and port setups
// 2) Calibrate the device using SSR2 to get time delay between the two using interrupts
// 3) Latch SSR1 to send input signals to external board compare PD0 and PD2 differences
// 4) Once latch interrupt is triggered from PD1 stop the timer
// 5) Record the time it took for the signal to propagate through
// 6) Reset the timer and prepare to disconnect the signal
// 7) Start the timer when the relay goes low
// 8) Time how long it takes for the signal to drop active low

// define statements for booleans
#define TRUE 1
#define FALSE 0

// define statements to decode the segment locations easier
#define BLANK 17
#define DIGIT_1 3
#define DIGIT_2 2
#define DIGIT_3 1
#define DIGIT_4 0
#define DELAY 0
#define HOLD 0

// define our port locations for our unit and digits
#define UNIT_A 6
#define UNIT_B 7
#define DIG_A 6
#define DIG_B 7
#define DIG_SEL 6
#define DELAY_PIN 5
#define HOLD_PIN 4
#define TEST_SEL 5

// define our custom wire locations
#define INT0_PIN 0
#define INT1_PIN 1
#define INT2_PIN 2
#define SSR_PIN 3

// define timings of our button presses
#define BTN_TIMING 1

// library includes
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

// decimal to 7-segment LED display encodings, logic "0" turns on segment
const uint8_t dec_to_7seg[18] = {
    0xC0, //0:      8'b1100_0000
    0xF9, //1:      8'b1111_1001
    0xA4, //2:      8'b1010_0100
    0xB0, //3:      8'b1011_0000
    0x99, //4:      8'b1001_1001
    0x92, //5:      8'b1001_0010
    0x82, //6:      8'b1000_0010
    0xF8, //7:      8'b1111_1000
    0x80, //8:      8'b1000_0000
    0x98, //9:      8'b1001_1000
    0x88, //A:      8'b1000_1000
    0x83, //B:      8'b1000_0011
    0xC6, //C:      8'b1100_0110
    0xA1, //D:      8'b1010_0001
    0x86, //E:      8'b1000_0110
    0x8E, //F:      8'b1000_1110
    0xC7, //L:      8'b1100_0111
    0xFF, //off:    8'b1111_1111
};

// holds data to be sent to the segments. logic zero turns segment on
uint8_t segment_data[4] = {
    0xFF, //off
    0xFF, //off
    0xFF, //off
    0xFF, //off
};

// define our button press value
uint8_t button = FALSE;
uint8_t start = TRUE;
uint8_t sel = DELAY;

// global counting variable
uint32_t countDelay = 0;
uint32_t countHold = 0;
uint16_t count = 0;

//******************************************************************************
//                            chk_buttons
// Checks the state of the button number passed to it. It shifts in ones till
// the button is pushed. Function returns a 1 only once per debounced button
// push so a debounce and toggle function can be implemented at the same time.
// Adapted to check all buttons from Ganssel's "Guide to Debouncing"
// Expects active low pushbuttons on PINA port.  Debounce time is determined by
// external loop delay times 12.
uint8_t chk_buttons()
{
    // setup our static sates values for button sates
    static uint16_t btnState = 0;
    const uint8_t status = (!bit_is_clear(PINB, TEST_SEL)); // checks to see if the bit is cleared
    btnState = (btnState << 1) | status | 0xE000;           // update the state
    if (btnState == 0xF000)                                 // check if valid press
    {
        // tell main a valid keypress has occurred
        return TRUE;
    }
    // check to see which button was pressed return 1 if its the button
    return FALSE;
}

// /*************************************************************************/
// //                           int0 ISR
// // When an interrupt is triggered on interrupt 0
// /*************************************************************************/
// ISR(INT0_vect)
// {
// } // ISR

// /*************************************************************************/
// //                           int1 ISR
// // When an interrupt is triggered on interrupt 1
// /*************************************************************************/
// ISR(INT1_vect)
// {
// } // ISR

// /*************************************************************************/
// //                           int2 ISR
// // When an interrupt is triggered on interrupt 2
// /*************************************************************************/
// ISR(INT2_vect)
// {
// } // ISR

//***********************************************************************************
//                                   segment_sum
// takes a 16-bit binary input value and places the appropriate equivalent 4 digit
// BCD segment code in the array segment_data for display.
// array is loaded at exit as:  |digit3|digit2|colon|digit1|digit0|
void segment_sum(uint16_t sum)
{
    // base ten display
    uint8_t FACTOR = 16;

    // do our math to get each of our digits
    const uint8_t ones = sum % FACTOR;                                               // sum % (10 or 16)
    const uint8_t tens = (sum % (FACTOR * FACTOR)) / FACTOR;                         // sum % (100 or 256) / (10 or 16)
    const uint8_t hundreds = (sum % (FACTOR * FACTOR * FACTOR)) / (FACTOR * FACTOR); // sum % (1000 or 4096) / (100 or 256)
    const uint8_t thosands = sum / (FACTOR * FACTOR * FACTOR);                       // sum / (1000 or 4096)

    // segment cases check statements
    const uint8_t four_digits = (sum >= (FACTOR * FACTOR * FACTOR)); // sum >= (1000 or 4096)
    const uint8_t three_digits = (sum >= (FACTOR * FACTOR));         // sum >= (100 or 256)
    const uint8_t two_digits = (sum >= FACTOR);                      // sum >= (10 or 16)

    // break up decimal sum into 4 digit-segments
    segment_data[DIGIT_1] = dec_to_7seg[ones];

    if (four_digits)
    {
        // we are using all 4 digits
        segment_data[DIGIT_1] = dec_to_7seg[ones];
        segment_data[DIGIT_2] = dec_to_7seg[tens];
        segment_data[DIGIT_3] = dec_to_7seg[hundreds];
        segment_data[DIGIT_4] = dec_to_7seg[thosands];
    }
    else if (three_digits)
    {
        // we are using 2 digits
        segment_data[DIGIT_1] = dec_to_7seg[ones];
        segment_data[DIGIT_2] = dec_to_7seg[tens];
        segment_data[DIGIT_3] = dec_to_7seg[hundreds];
        segment_data[DIGIT_4] = dec_to_7seg[BLANK];
    }
    else if (two_digits)
    {
        // we are using 3 digits
        segment_data[DIGIT_1] = dec_to_7seg[ones];
        segment_data[DIGIT_2] = dec_to_7seg[tens];
        segment_data[DIGIT_3] = dec_to_7seg[BLANK];
        segment_data[DIGIT_4] = dec_to_7seg[BLANK];
    }
    else
    {
        // we are using 2 digits
        segment_data[DIGIT_1] = dec_to_7seg[ones];
        segment_data[DIGIT_2] = dec_to_7seg[BLANK];
        segment_data[DIGIT_3] = dec_to_7seg[BLANK];
        segment_data[DIGIT_4] = dec_to_7seg[BLANK];
    }
} // segment_sum
//***********************************************************************************

//***********************************************************************************
//
// calculates the hold time before the signal latches off again
void update_segments()
{
    // bound a counter (0-4) to keep track of digit to display
    uint8_t index;
    for (index = 0x00; index < 4; index++)
    {
        PORTF = dec_to_7seg[BLANK];
        PORTC = dec_to_7seg[BLANK];

        // save state of port b
        uint8_t tempB = PORTB;

        // clear the S0, S1, S2 selector bits and keep temp
        tempB &= !((1 << DIG_A) | (1 << DIG_B));

        // save our new digit to our combined temp variable
        tempB |= (index << DIG_SEL);

        // overwrite portb with our new variable
        PORTB = tempB;
        PORTB = tempB;

        // send 7 segment code to LED segments
        PORTF = segment_data[index];
        PORTC = (segment_data[index] << 4);

        // delay to have the screen get enough power
        _delay_us(20);
    }
} // calibrate_ssr
//***********************************************************************************

//***********************************************************************************
//
// takes in no arguments and compares the difference in startup times between
// manufacturing tolerances of the solid state relays being used.
void delay_test()
{
    // reset our calibration variables to zero
    //countDelay = 0;

    // turn on the solid state relay
    //PORTD &= ~(1 << SSR_PIN);

    // spin our wheels until our interrupts are triggered
    while (TRUE)
    {
        segment_sum(PORTD);
        update_segments();
    }
} // calibrate_ssr
//***********************************************************************************

//***********************************************************************************
//
// calculates the hold time before the signal latches off again
void hold_test()
{
    // reset our calibration variables to zero
    countHold = 0;

    // turn off the solid state relay
    PORTD |= (1 << SSR_PIN);

    // spin our wheels until we see the signal propagate through
    while ((PORTD & (1 << PD1)) >> PD1 == 1)
    {
        countHold++;
    }
} // calibrate_ssr
//***********************************************************************************

//***********************************************************************************
//
// calculates the hold time before the signal latches off again
uint16_t convert(uint32_t timingCount)
{
    return timingCount >> 16;
} // calibrate_ssr
//***********************************************************************************

//***********************************************************************************
int main()
{
    // Disable JTAG interface
    MCUCR |= (1 << JTD);
    MCUCR |= (1 << JTD);

    // setup our PORTC and PORTF
    // --------------------------------------
    // setup PORTF as outputs
    DDRF = 0xFF;
    // setup PORTC as outputs
    DDRC = 0xFF;

    // setup PORTB
    // --------------------------------------
    // select the first digit for our decoder
    DDRB |= (1 << DIG_A) | (1 << DIG_B);
    PORTB |= (1 << DIG_A) | (1 << DIG_B);

    // setup PORTD
    // --------------------------------------
    // setup the DDRD for output mode
    DDRD |= (1 << SSR_PIN) | (1 << HOLD_PIN) | (1 << DELAY_PIN) | (1 << UNIT_A) | (1 << UNIT_B);
    // setup the interrupt pins in pull-up mode
    PORTD |= (1 << INT0_PIN) | (1 << INT1_PIN) | (1 << INT2_PIN);
    // setup the pins to select default state of the SSR and unit selector
    PORTD |= (1 << UNIT_A) | (1 << UNIT_B) | (1 << SSR_PIN);

    // setup the interrupt masking
    //EICRA |= (1 << ISC00) | (1 << ISC01) | (1 << ISC10) | (1 << ISC11) | (1 << ISC20) | (1 << ISC21);
    //EIMSK |= (1 << INT0) | (1 << INT1) | (1 << INT2);

    //sei(); // enable interrupts before entering loop

    while (1)
    {
        uint8_t btnPressed = chk_buttons();
        // only if the button was pressed overwrite our global variable
        // this prevents overwritting a successfully button press with a zero
        // if we do not preform this hard check!
        if (chk_buttons())
        {
            // check to see if we are doing the first test procedure
            if (start)
            {
                // update the segments to be blank
                segment_data[0] = dec_to_7seg[BLANK];
                segment_data[1] = dec_to_7seg[BLANK];
                segment_data[2] = dec_to_7seg[BLANK];
                segment_data[3] = dec_to_7seg[BLANK];
                update_segments();

                // turn on the relays and wait until the signal propagates through
                delay_test();

                // turn off the relays and get the hold time
                //hold_test();
            }
            else
            {
                if (sel == DELAY)
                {
                    sel = HOLD;
                    count = convert(countHold);
                }
                else if (sel == HOLD)
                {
                    sel = DELAY;
                    count = convert(countDelay);
                }
            }
        }

        // break up the disp_value to 4, BCD digits in the array: call (segsum)
        if (start)
        {
            segment_data[0] = dec_to_7seg[BLANK];
            segment_data[1] = dec_to_7seg[5];
            segment_data[2] = dec_to_7seg[14];
            segment_data[3] = dec_to_7seg[16];
        }
        else
        {
            segment_sum(count);
        }

        update_segments();
    } // while

    return 0;
} // main
« Last Edit: December 04, 2020, 01:59:24 pm by trini8ed »
 

Offline Alti

  • Frequent Contributor
  • **
  • Posts: 404
  • Country: 00
 

Offline trini8edTopic starter

  • Newbie
  • Posts: 8
  • Country: us
Re: Atmega32U4 PORTD refuses to read inputs
« Reply #2 on: December 04, 2020, 03:16:27 pm »
That post is a separate issue regarding PORTF with JTAG fuses being set. This is a separate issue I'm experiencing regarding PORTD not wanting to take in inputs. JTAG has already been disabled nor shouldn't be related to why PORTD isn't working with inputs.
« Last Edit: December 04, 2020, 03:23:58 pm by trini8ed »
 

Online MarkF

  • Super Contributor
  • ***
  • Posts: 2856
  • Country: us
Re: Atmega32U4 PORTD refuses to read inputs
« Reply #3 on: December 04, 2020, 04:35:55 pm »
I would suggest you first determine if it is a hardware or software problem.
Run a much simpler test program to test the hardware.  For example:

Code: [Select]
void main()
{
   while (1) {
      PORTF = PORTD;  // Tie each seven segment to a Port D bit.
                      // Enable Port D pull-ups and jump each bit to GND
                      // then watch for segment to turn ON/OFF.
   }
}

 

Offline trini8edTopic starter

  • Newbie
  • Posts: 8
  • Country: us
Re: Atmega32U4 PORTD refuses to read inputs
« Reply #4 on: December 04, 2020, 06:31:26 pm »
Yeah I'm thinking its either hardware or another special register I'm missing in the datasheet. I just replaced the Atmega32U4 chip thinking it was that but it did the same thing as always  :clap:. It always shows FF on the segments as everything is held high but even if I GND any of PORTD it seems to just do nothing still shows FF. I know my segment driver codes work flawless as its been tested and is known working. This means we are left to hardware, schematic wiring, and some magic register that disable PORTD based on some default fuses I missed again :horse:

Code: [Select]
int main() {
    while (1) {
        DDRD = 0x00;                    // set portd as inputs
        PORTD = 0xFF;                   // setup portd as pullups
        segment_sum(PORTD);       // output values of portd to segemnts
        update_segments();           // update the segments
    } // while
} // main
 

Offline georges80

  • Frequent Contributor
  • **
  • Posts: 932
  • Country: us
Re: Atmega32U4 PORTD refuses to read inputs
« Reply #5 on: December 04, 2020, 08:33:26 pm »
PIND is the INPUT pins of port D. Reading PORTD just gives you what you wrote to PORTD (pullup/output register)... FF...

cheers,
george.
 
The following users thanked this post: I wanted a rude username, trini8ed

Offline trini8edTopic starter

  • Newbie
  • Posts: 8
  • Country: us
Re: Atmega32U4 PORTD refuses to read inputs
« Reply #6 on: December 04, 2020, 08:40:00 pm »
 :palm:  Bahahahaha yeah oh man figured it was something dumb like that I missed late at night... Yeah go ahead and configure the ports and grab the value I just wrote to you not the inputs of the pins totally intentional  :-DD
 
The following users thanked this post: georges80


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf