1

I have 2 circuits, both made up of a dual seven segment display and A pic16f684 (As shown below) the first circuit uses the code supplied to generate a random number 1-26. The letter portion is the same circuit, but with one of the transistor removed, to disable one side. circuit

/*
 * File:   main.c
 * Original Code Creator: dan1138
 * Target: PIC16F684
 * Compiler: XC8 v2.20
 * IDE: MPLABX v5.25
 * 
 * Description:
 *
 * Created on July 21, 2020, 3:45 PM
 * 
 *                            PIC16F684
 *                  +------------:_:------------+
 *         GND -> 1 : VDD                   VSS : 14 <- 5v0
 * SEG_a_DRIVE <> 2 : RA5/T1CKI     PGD/AN0/RA0 : 13 <> DIGIT_DRIVE_2
 *         SW2 <> 3 : RA4/AN3       PGC/AN1/RA1 : 12 <> DIGIT_DRIVE_1
 *         SW1 -> 4 : RA3/VPP           AN2/RA2 : 11 <> 
 * SEG_b_DRIVE <> 5 : RC5/CPP1          AN4/RC0 : 10 <> SEG_g_DRIVE
 * SEG_c_DRIVE <> 6 : RC4/C2OUT         AN5/RC1 : 9  <> SEG_f_DRIVE
 * SEG_d_DRIVE <> 7 : RC3/AN7           AN6 RC2 : 8  <> SEG_e_DRIVE
 *                  +---------------------------:
 *                             DIP-14
 */

// CONFIG --- Configuration Word --- START
#pragma config FOSC = INTOSCIO
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = OFF
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = OFF
#pragma config IESO = OFF
#pragma config FCMEN = OFF
// CONFIG --- Configuration Word --- END

#include <xc.h>
#include <stdlib.h>

/* Oscillator frequency we will select with the OSCCON register */
#define _XTAL_FREQ (4000000ul)
/*
 * Segment locations
 * of an LED display
 *      ---a---
 *     :       :
 *     f       b
 *     :       :
 *      ---g---
 *     :       :
 *     e       c
 *     :       :
 *      ---d---
 */
const unsigned char LEDDigit[] = {
//     abcdefg, Segment on = 0
    0b00000001, // "0"
    0b01001111, // "1"
    0b00010010, // "2"
    0b00000110, // "3"
    0b01001100, // "4"
    0b00100100, // "5"
    0b00100000, // "6"
    0b00001111, // "7"
    0b00000000, // "8"
    0b00001100, // "9"
    0b00001000, // "A"
    0b01100000, // "b"
    0b00110001, // "C"
    0b01000010, // "d"
    0b00110000, // "E"
    0b00111000  // "F"  
}; 



void main(void) 
{
    unsigned char DisplayValue, DisplayLED, DigitSegments;
    unsigned char LoopCount;
    unsigned int  Temp;
    
    PORTA = 0;
    PORTC = 0;
    CMCON0 = 7;                 // Turn off Comparators 
    ANSEL = 0;                  // Turn off ADC 
    
    __delay_ms(500);            // wait for ICD before making PGC and PGD outputs;
    TRISA = 0b011100;           // RA5, RA1, RA0 are outputs
    TRISC = 0b000000; 
    OPTION_REGbits.nRAPU = 0;   // Enable weak pull-up on PORTA
    WPUA = 0;                   // Turn off all pull-ups
    WPUAbits.WPUA4 = 1;         // Turn on RA4 pull-up
    
         
    DisplayValue = 0;           // Start Displaying at 0x00 
    DisplayLED = 0;             // Display the 1s first
    LoopCount = 0;
    srand(0x1234);
    
    for(;;)
    {
        PORTC = 0xFF;   // turn off all segment drivers
        PORTA = 0xFF;   // and digit drivers
        if (1 == (DisplayLED & 1))
        {
            DigitSegments = LEDDigit[(DisplayValue >> 4) & 0x0F];
            if(DigitSegments & 0b1000000)
                          {
                PORTA = 0b111110;   // turn on Digit driver 2
            } 
            else 
            {
                PORTA = 0b011110;   // turn on Digit driver 2 and SEG_a_DRIVER
            }
        }
        else
        {
            DigitSegments = LEDDigit[DisplayValue & 0x0F];
            if(DigitSegments & 0b1000000)
            {
                PORTA = 0b111101;   // turn on Digit driver 1
            } 
            else 
            {
                PORTA = 0b011101;   // turn on Digit driver 1 and SEG_a_DRIVER
            }
        }
        PORTC = DigitSegments;      // turn on segment drivers b to g
        DisplayLED++;               // select next digit

        __delay_ms(10);             // Show digit for 10 milliseconds
        
        if(0 == PORTAbits.RA3)      // is SW1 pressed?
        {
            LoopCount++;
            if(LoopCount == 1)
            {
                 // Display a new random value every 500 milliseconds
                Temp = rand() & 0xFFu;      // put random value in range of 0 to 255 and treat is as a fraction in range (0/256) <= value < (255/256)
                Temp = (Temp * 26u + 0x100u) >> 8; // Use tricky math to make a random number in the range from 1 to 56
                DisplayValue = (Temp / 10u) << 4;  // Extract the ten's digit
                DisplayValue = DisplayValue | (Temp % 10); // Extract the one's digit
            }
            if(LoopCount >= 50)
            {
                LoopCount = 0;
            }
        }
        else
        {
            LoopCount = 0;
        }

        if(0 == PORTAbits.RA4)      // is SW2 pressed?
        {
            DisplayValue = 0;       // Reset display value to zero
            LoopCount = 0;
        }
    }
}

My goal to is generate the corresponding letter on the second seven segment display using a modified alphabet. however, I cant figure out how to do this. My original thought was to output the temp value to the second pic16f684 with modified LEDDigits[];

const unsigned char LEDDigit[] = {
//     abcdefg, Segment on = 0
    0b01111110, //"-"
    0b00001000, // "A"
    0b01100000, // "b"
    0b00110001, // "C"
    0b01000010, // "d"
    0b00110000, // "E"
    0b00111000, // "F"  
    0b00100001, // "G"
    0b01001000, // "H"
    0b01111001, // "I"
    0b01000011, // "J"
    0b00101000, // "Modified K"
    0b01110001, // "L"
    0b00010101, // "Modified M"
    0b01101010, // "n"
    0b01100010, // "o"
    0b00011000, // "P"
    0b00001100, // "q"
    0b01111010, // "r"
    0b00100100, // "S"
    0b01110000, // "t"
    0b01100011, // "u"
    0b01010101, // "Modified V"
    0b01000000, // "Modified W"
    0b00110110, // "Modified X"
    0b01000100, // "y"
    0b00010010 // "Z"
        
}; 

But I dont believe I can just output that number. How can I display the number (1-26) on one dual display, and the corresponding letter on another display.

Could I potentially add the second seven segment display into the number circuit, set its transistor on RA2, and have it display the letter at the same time? how would this work?

tjpplay
  • 45
  • 4
  • 1
    You need to **understand** how multiplexed display work, then you will know what to do. Go ahead and try it. -- Having said this, you can add a third seven segment display to the existing two and control it by RA2, yes. – the busybee Jul 25 '20 at 13:18
  • How would I go about adding a 3rd Segment on RA2. I tried to add another statement to the if else, but it just disturbed the code, someone help please – tjpplay Jul 25 '20 at 19:04
  • 1
    @tjpplay, You copied my code example from [here](https://stackoverflow.com/questions/63006839/pic16f684-dual-seven-seg-display-program-random-number-generator-in-c) , removed my name, not even an up vote. There is not much incentive to provide more help. – Dan1138 Jul 25 '20 at 21:26
  • Sorry. I didn't even think about it. I do appreciate the solution – tjpplay Jul 25 '20 at 23:06

1 Answers1

1

Ok, so here is a solution for your homework:

/*
 * File:   main.c
 * Author: dan1138
 * Target: PIC16F684
 * Compiler: XC8 v2.20
 * IDE: MPLABX v5.25
 * 
 * Description:
 * 
 * This code is the homework solution for Stack Overflow posts:
 *  https://stackoverflow.com/questions/63086495/random-number-generator-with-corresponding-letter
 *  https://stackoverflow.com/questions/63006839/pic16f684-dual-seven-seg-display-program-random-number-generator-in-c
 * 
 *
 * Created on July 21, 2020, 3:45 PM
 * 
 *                            PIC16F684
 *                  +------------:_:------------+
 *         GND -> 1 : VDD                   VSS : 14 <- 5v0
 * SEG_a_DRIVE <> 2 : RA5/T1CKI     PGD/AN0/RA0 : 13 <> DIGIT_DRIVE_2
 *         SW2 <> 3 : RA4/AN3       PGC/AN1/RA1 : 12 <> DIGIT_DRIVE_1
 *         SW1 -> 4 : RA3/VPP           AN2/RA2 : 11 <> DIGIT/ALPHAn mode
 * SEG_b_DRIVE <> 5 : RC5/CPP1          AN4/RC0 : 10 <> SEG_g_DRIVE
 * SEG_c_DRIVE <> 6 : RC4/C2OUT         AN5/RC1 : 9  <> SEG_f_DRIVE
 * SEG_d_DRIVE <> 7 : RC3/AN7           AN6 RC2 : 8  <> SEG_e_DRIVE
 *                  +---------------------------:
 *                             DIP-14
 */

// CONFIG --- Configuration Word --- START
#pragma config FOSC = INTOSCIO
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = OFF
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = OFF
#pragma config IESO = OFF
#pragma config FCMEN = OFF
// CONFIG --- Configuration Word --- END

#include <xc.h>
#include <stdlib.h>

/* Oscillator frequency we will select with the OSCCON register */
#define _XTAL_FREQ (4000000ul)
/*
 * Segment locations
 * of an LED display
 *      ---a---
 *     :       :
 *     f       b
 *     :       :
 *      ---g---
 *     :       :
 *     e       c
 *     :       :
 *      ---d---
 */
const unsigned char LEDDigitSegs[] = {
//     abcdefg, Segment on = 0
    0b00000001, // "0"
    0b01001111, // "1"
    0b00010010, // "2"
    0b00000110, // "3"
    0b01001100, // "4"
    0b00100100, // "5"
    0b00100000, // "6"
    0b00001111, // "7"
    0b00000000, // "8"
    0b00001100, // "9"
    0b00001000, // "A"
    0b01100000, // "b"
    0b00110001, // "C"
    0b01000010, // "d"
    0b00110000, // "E"
    0b00111000  // "F"  
}; 

const unsigned char LEDAlphaSegs[] = {
//     abcdefg, Segment on = 0
    0b01111110, // "-"
    0b00001000, // "A"
    0b01100000, // "b"
    0b00110001, // "C"
    0b01000010, // "d"
    0b00110000, // "E"
    0b00111000, // "F"  
    0b00100001, // "G"
    0b01001000, // "H"
    0b01111001, // "I"
    0b01000011, // "J"
    0b00101000, // "Modified K"
    0b01110001, // "L"
    0b00010101, // "Modified M"
    0b01101010, // "n"
    0b01100010, // "o"
    0b00011000, // "P"
    0b00001100, // "q"
    0b01111010, // "r"
    0b00100100, // "S"
    0b01110000, // "t"
    0b01100011, // "u"
    0b01010101, // "Modified V"
    0b01000000, // "Modified W"
    0b00110110, // "Modified X"
    0b01000100, // "y"
    0b00010010  // "Z"
}; 

void main(void) 
{
    unsigned char Digit1_Segments, Digit2_Segments;
    unsigned char LoopCount;
    unsigned int  Temp;

    PORTA = 0xFF;
    PORTC = 0xFF;
    CMCON0 = 7;                 // Turn off Comparators 
    ANSEL = 0;                  // Turn off ADC 

    __delay_ms(500);            // wait for ICD before making PGC and PGD outputs;
    TRISA = 0b011111;           // RA5, RA1, RA0 are outputs
    TRISC = 0b000000; 
    OPTION_REGbits.nRAPU = 0;   // Enable weak pull-up on PORTA
    WPUA = 0;                   // Turn off all pull-ups
    WPUAbits.WPUA4 = 1;         // Turn on RA4 pull-up
    WPUAbits.WPUA2 = 1;         // Turn on RA2 pull-up

    Digit1_Segments = 0xFF;     // Turn off digit segments
    Digit2_Segments = 0xFF;     // Turn off digit segments
    LoopCount = 0;
    srand(0x1234);              // Seed the pseudo random number generator

    for(;;)
    {
        PORTC = 0xFF;   // turn off all segment drivers
        PORTA = 0xFF;   // and digit drivers
        if (TRISAbits.TRISA1 == 0)
        {
            TRISAbits.TRISA1 = 1;
            TRISAbits.TRISA0 = 1;
            if(0 == (Digit2_Segments & 0b1000000))
            {
                PORTA = 0b011110;   // turn on Digit driver 2 and SEG_a_DRIVER
            }
            else
            {
                PORTA = 0b111110;   // turn on Digit driver 2
            }
            PORTC = Digit2_Segments;      // turn on segment drivers b to g
            TRISAbits.TRISA0 = 0;;
        }
        else
        {
            TRISAbits.TRISA1 = 1;
            TRISAbits.TRISA0 = 1;
            if(0 == (Digit1_Segments & 0b1000000))
            {
                PORTA = 0b011101;   // turn on Digit driver 1 and SEG_a_DRIVER
            }
            else
            {
                PORTA = 0b111101;   // turn on Digit driver 1
            }
            PORTC = Digit1_Segments;      // turn on segment drivers b to g
            TRISAbits.TRISA1 = 0;;
        }

        __delay_ms(10);             // Show digit for 10 milliseconds

        if(0 == PORTAbits.RA3)      // is SW1 pressed?
        {
            LoopCount++;
            if(LoopCount == 1)
            {
                // Display a new random value every 500 milliseconds
                Temp = rand() & 0xFFu;      // put random value in range of 0 to 255 and treat is as a fraction in range (0/256) <= value < (255/256)
                if(0 == PORTAbits.RA2)      // Choose between alpha and digits mode
                {
                    // Show random character "A" to "Z" in digit 1, show dash "-" in digit 2
                    Temp = (Temp * 26u + 0x100u) >> 8; // Use tricky math to make a random number in the range from 1 to 26
                    Digit2_Segments = LEDAlphaSegs[0];    // Display a dash "-"
                    Digit1_Segments = LEDAlphaSegs[Temp]; // Display character segments (A-Z)
                }
                else
                {
                    // Show two digit random number from 1 to 56
                    Temp = (Temp * 56u + 0x100u) >> 8; // Use tricky math to make a random number in the range from 1 to 56
                    Digit2_Segments = LEDDigitSegs[(Temp / 10)]; // Display the ten's digit segments
                    Digit1_Segments = LEDDigitSegs[(Temp % 10)]; // Display the one's digit segments
                }
            }
            if(LoopCount >= 50)
            {
                LoopCount = 0;
            }
        }
        else
        {
            LoopCount = 0;
        }

        if(0 == PORTAbits.RA4)      // is SW2 pressed?
        {
            Digit1_Segments = 0xFF;     // Turn off digit segments
            Digit2_Segments = 0xFF;     // Turn off digit segments
            LoopCount = 0;
        }
    }
}

If you instructor likes this please let me know what marks you received.

Dan1138
  • 1,150
  • 8
  • 11
  • 1
    Im sorry i didnt give you the recognition before. This was for a project, but I took a different route for my submission, instead of trying anything to get it working, explain in detail my thought process and were I could benefit from not achieving my goal output. I really just wanted to see how someone doing it properly would write the code. Thank you for you help. Anyone who can properly code and understand in impressive to me. I'll actually be listing you as a reference in my final report. – tjpplay Jul 26 '20 at 00:18
  • @tjpplay, It seems to me that the instruction and advice you've received did little to prepare you to comprehend the techniques required to complete this type of project. I would like to say to your administrators for instruction that event if the students are paid to take this course they are being cheated. – Dan1138 Jul 26 '20 at 00:34
  • I 100% agree with you, programming is only 10% of my total major. I really just want it as light background knowledge, hardware is my main focus. It also doesnt help that its an online course because of covid. – tjpplay Jul 26 '20 at 00:39
  • I have been doing embedded hardware design for a long long time. It use to be relays, motors, logic circuits and ladder diagrams. Today it's almost all coding of some kind. High level languages (C, C++, Rust etc.), assembly language, even Verilog and VHDL, Almost nobody does discrete gates anymore. Everything is about integration. – Dan1138 Jul 26 '20 at 00:48
  • Clearly my school isn't benefiting me to well. Any recommendations to would actually be useful in learning? – tjpplay Jul 26 '20 at 00:53
  • 1
    It all depends on what motivates you. With passion for the subject nothing can stop you from learning. So know yourself and know what will drive you then find a way to align that with your goals. That will get you where you want to go. If it takes someone to hammer the stuff into your brain it will not stick. --- The short answer is to read a lot of crap code. --- This is so you can know good from bad. – Dan1138 Jul 26 '20 at 01:20