[SOLVED] How to collect parallel data from one port of microcontroller and show to 7segments

Status
Not open for further replies.

davoud

Full Member level 2
Joined
Mar 10, 2005
Messages
146
Helped
39
Reputation
78
Reaction score
39
Trophy points
1,308
Activity points
2,119
Hello Everyone,
I am inexperienced in micro-controllers. I want read data from a "six-pin DIP switch" attached to the port A of PIC 16F876A and show data on two 7-segment display connected to port B and port C. I have a problem to read data.
Thanks.
My program :


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "Display_utils.h"
 
unsigned int digit_no, digit10, digit1, digit ;
 
 
void main() {
 
  PORTC       =    0;   //  clear PORTA (make sure both displays are off)
  TRISC       =    0;   //  designate PORTA pins as output
  PORTB       =    0;   //  clear PORTD (make sure LEDs are off)
  TRISB       =    0;   //  designate PORTD pins as output
  TRISA       =    1;     //  designate PORTA pins as input
  do {
 
      digit = PORTA ;
      digit1 = digit % 10;
      digit10 = (digit / 10) % 10   ;
      PORTC  = mask(digit1);           // prepare ones digit
      PORTB = mask(digit10);           // prepare tens digit
 
  } while (1);                         // endless loop
}

 
Last edited by a moderator:

Why two ports for two displays ? Why aren't you using multiplexing for displays ?

With multiplexing you need 7 + 2 pins in total for the 2 digit display.
 

Yes Dear Okada, I can do this but my problem is for read data! I think data at the port A is binary.
 

Please confirm this:

You have 6 input lines from a switch. Is it wired to ground with pull-up resistors or is it wired to VDD with pull-down resistors?
You have two LED displays. Are they common cathode (segments driven high to turn them on) or common anode (segments driven low to turn them on)?
The numeric input range is 0 to 63 in binary. Do you want to display this a '00'-'63' (decimal) or as '00'-'4F' (hexadecimal)?
Finally, what is in "Display_utils.h"?

Brian.
 

Which Compiler ? What is the Crystal frequency ? Which PIC ?
 

Thanks Brian,
1- Yes I pull-down them by resistor connected to ground.
2- Yes two 7-segent are common cathode.
3- I wanna display decimal (00-63)
4- Yes right I forgot that, the code is :

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//-------------- Returns mask for common cathode 7-seg. display
unsigned short mask(unsigned short num) {
  switch (num) {
    case 0 : return 0x3F;                                
    case 1 : return 0x06;
    case 2 : return 0x5B;
    case 3 : return 0x4F;
    case 4 : return 0x66;
    case 5 : return 0x6D;
    case 6 : return 0x7D;
    case 7 : return 0x07;
    case 8 : return 0x7F;
    case 9 : return 0x6F;
  } //case end
}//~


and the schematics is:


- - - Updated - - -

I work with Mikroc compiler.
 
Last edited by a moderator:

Capacitor vaue in the oscillator circuit is wrong. You have to use between 22pF and 33pF based on Crystal frequency. Can you use multiplexing for the displays. I will write a code for you.
 

You also need current limiting resistors in each segment connection, something like 330 Ohms should be fine.
Okada is correct, you need much smaller loading capacitors at the crystal and you also need to add capacitors across the VDD and VSS pins of the PIC.

Without testing it myself the code looks basically OK with one exception, PORTA defaults to being an anlog input when the PIC is reset so you need to reconfigure it to work in digital mode by adding the line:
Code:
ADCON1 = 0x07;
at the start of the main() code. See the data sheet for information on the ADCON1 register bits.

Indientally, you have commented the PORTB instructions as PORTD but it makes no difference to the running of the program.

Brian.
 
Reactions: davoud

    davoud

    Points: 2
    Helpful Answer Positive Rating
This is the new circuit I designed for your project. I will post the code soon.
 

Attachments

  • Reading DIP Switch.png
    33.8 KB · Views: 92
Dear Friends,
Yes, I have some mistake on schematic but I'm focused on program.
I add code for analog/digital (ADCON1 = 0x07 and now my program work perfectly.
Thanks for your help.
Dear Okada, do you have program for the schematic? I am very thankful for your help.
 

I don't have the code but I will write and post the code in another 2 hours.
 

I wanna add watch dog to my program. could you guide me?

- - - Updated - - -

I don't have the code but I will write and post the code in another 2 hours.
thanks for your kind attention
 

You have to use

Code:
asm clrwdt
OPTION_REG = 0x87;

as the initial lines in main() and then use

Code:
asm clrwdt

in while(1) loop as required.



Try this project.

Edit:

Updated file attached. Removed the leading zeroes from the display.


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#define DIP_SWITCH (PORTA & 0x3F)
#define SSD_DATA_PORT PORTB
#define SSD_CONTROL_PORT PORTC
 
const unsigned char cc_mask[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
unsigned char digit = 0, digits[2] = {0, 0};
 
//Timer1
//Prescaler 1:1; TMR1 Preload = 63536; Actual Interrupt Time : 2 ms
//Place/Copy this part in declaration section
void InitTimer1() {
    T1CON = 0x01;
    TMR1IF_bit = 0;
    TMR1H = 0xF8;
    TMR1L = 0x30;
    TMR1IE_bit = 1;
    INTCON = 0xC0;
}
 
void Interrupt() {
    if((TMR1IE_bit) && (TMR1IF_bit)) { 
        //Enter your code here
        SSD_CONTROL_PORT = (SSD_CONTROL_PORT & 0xFC);
        
        switch(digit) {
           case 0:
                SSD_DATA_PORT = digits[0];
                SSD_CONTROL_PORT = (SSD_CONTROL_PORT & 0xFC) | 0x01;
                break;
           case 1:
                SSD_DATA_PORT = digits[1];
                SSD_CONTROL_PORT = (SSD_CONTROL_PORT & 0xFC) | 0x02;
                break;
        
        };
        
        if(++digit > 1) {
            digit = 0;
        }        
        
        TMR1IF_bit = 0;
        TMR1H = 0xF8;
        TMR1L = 0x30;        
    }
}
 
void main() {
 
    asm clrwdt
    OPTION_REG = 0x87;
    
    CMCON = 0x07;    
    ADCON1 = 0x87;    
    TRISA = 0xFF;
    TRISB = 0x00;
    TRISC = 0x00;
    
    InitTimer1();
    
    while(1) {
    
          asm clrwdt
          digits[0] = cc_mask[(PORTA & 0x3F) / 10];
          digits[1] = cc_mask[(PORTA & 0x3F) % 10];
          
    }
}



Replace

Code:
digits[0] = cc_mask[(PORTA & 0x3F) / 10];
          digits[1] = cc_mask[(PORTA & 0x3F) % 10];

with

Code:
digits[0] = cc_mask[DIP_SWITCH / 10];
          digits[1] = cc_mask[DIP_SWITCH % 10];
 

Attachments

  • Reading DIP Switch.png
    41.2 KB · Views: 96
  • RDS.rar
    63.5 KB · Views: 83
  • RDS RevB.rar
    63.8 KB · Views: 71
Last edited:
This is the new circuit I designed for your project. I will post the code soon.

Your RN1 is pulling high with the dipsw also connected to high.
Your RN2 should be 330 ohm instead of 10k.

Still waiting for your program codes. Thanks.

Allen
 

Here is the new project. Proteus file and schematic as PDF is included. I had forgotten to change the value of RN2 to 330E. Also made changes to code. Now only if DIP switch port value doesn't match with its previous value the data is updated.
 

Attachments

  • RDS RevC.rar
    64 KB · Views: 70
Yes, I converted it to HiTech C. Now it works on my proteus 7.80 too. Thanks



Allen
 

In your circuit R2 and R5 should be 1k.
 
Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…