Using 16f690 pic / interfasing key pad and 2 x 7 segment displays , problem

Thread Starter

Cristian Cox

Joined May 13, 2017
18
, good afternoon.

I need some help please or ideas.

The code below Works well for 1 7 segment display. I press the number in the key pad and the number is shown without problem.

I am adding a second 7 segment display, and the idea is to control both (multiplexing port C) with 2 transistors (see below)
I have not implemented yet the circuit since I want to have a clear idea how the software should work for the multiplexing and graving the right binary patern to light each display.

In general the code for displaying just one digit, works scanning the keypad, then looking in a table the patern of the leds in the display that need to be turned on.

I dont have a problem to turn on the right transistor, for each display in a secuence, for example if we want to display number 17.

My problem is that W (accumulator) is all the time with a value (even if the key pad was not pushed).

for example, if I want to write the number 17

I think that ideally I would like to pass this number to 2 registers, one for 1 and one for 7.
and from there I could créate a loop with the transistors (on or off according to what display wants to be shown) for showing the information of port C either with the value for 1 or for 7.


The problem is that I have all the time W with a value that repeats on time (since it is a loop), since for example I press 1, the value is shown in the display, but after I reléase the button, the value in W still there, so I dont know how to diferentiate when a real new value is coming, to put it in the other display and turn the right transistor.

If you have a better way how to display a 2 digit number using one port and 2 transistors I would apreciate if you can help me.

regards

Cristian Cox



upload_2018-7-6_18-36-36.png


upload_2018-7-6_18-37-21.png


The following code is made for just one 7 segment display (for 2 x7 segment display should be modified)


Code:
;17/05/2018
;
;
;
#include <p16F690.inc>
    __config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)


PC equ h'02'                    ;    The program counter will be refered to as PC - The program counter is
                                ;    a little counter within the microcontroller to let itself know what line number
                                ;    it is upto when running a program. We can make the microcontroller jump to a certain
                                ;    line number by changing the value stored in PC. (we will do this in a later tutorial)


cblock h'20'            ;    Within this cblock and endc, we can define our variables. More info on this, later.
    delay_1                        ;    set aside 1 byte for a variable called delay_1
    delay_2                        ;    set aside 1 byte for a variable called delay_1
    what_button                    ;    this variable is used in identifying which button we have pressed.
    conmutador                                      ;       variable que contiene direccion de primer y segundo diplay
    endc                        ;    that's the end of defining our variables


                                                        ;      

    org h'0000'                        ;    This line just tells the microcontroller what address to start running our program from.
                                ;    It will always be 0000 hex for all the tutorials.
        bsf STATUS, RP1
    bcf STATUS, RP0
                                   
    clrf ANSEL                                     ; I/o
    clrf ANSELH
   
   
    clrf CM1CON0
    clrf CM2CON0                           
   
    bcf STATUS, RP1
    bcf STATUS, RP0

   

    bsf STATUS, RP0             ;    select bank 1 (to enable us to change the Input / Output status of our ports)
    movlw b'11000000'             ;    set PORTB all outputs (A '0' means output, A '1' means input. We can set each (se cambio bit 7 a input)
    movwf TRISB                    ;    We can set each bit individualy. Each port having 8-bits or 8 pins.
        movlw b'00000000'
        movwf TRISC
    movlw b'00011000'             ;    set PORTA pins 0, 1, and 2 outputs (col1 col2 col3). pins 3 raw1, 4 raw2, 5 raw3, 6 raw4 (RB7) and 7 inputs
    movwf TRISA                 ;    remember PORTA pin 5 cannot be an input.
    bcf STATUS, RP0             ;    select bank 0


    goto setup                    ;    Now skip straight to setup.


digit_data                    ;    This routine holds all the data for our various digits.
    movf what_button, w            ;    before we get here, the what_button variable will contain
                                ;    a certain number that we copy into the w register.
    addwf PC                    ;    We then add this number to our program counter which will jump
                                ;    us straight to a certain retlw statement which will correspond
                                ;    to the number that we pressed on the keypad.
    retlw b'11000000'            ;    this is the data for the number 0
    retlw b'11110011'            ;    this is the data for the number 1   
    retlw b'10100100'            ;    this is the data for the number 2
    retlw b'10100001'            ;    this is the data for the number 3
    retlw b'10010011'            ;    this is the data for the number 4
    retlw b'10001001'            ;    this is the data for the number 5
    retlw b'10001000'            ;    this is the data for the number 6
    retlw b'11100011'            ;    this is the data for the number 7
    retlw b'10000000'            ;    this is the data for the number 8
    retlw b'10000001'            ;    this is the data for the number 9
    retlw b'11010010'            ;    this is the data for *
    retlw b'10101101'            ;    this is the data for #



setup                            ;    I always have a title labeled 'setup' this is where we set everything up
        clrf what_button        ;    this ensures that we will display '0' on the display at startup
        clrf PORTA
        clrf PORTB                          ;    we are not scanning for any keypresses yet, so make PORTA all zero's
                bcf PORTA, 0            ;    turn OFF the first display (by disconnecting +5v from the anodes)
        bcf PORTA, 1            ;    turn OFF the second display (by disconnecting +5v from the anodes)


begin                            ;    and here is our main program
    call check_keypad            ;    call the check_keypad sub-routine and then return
    call display_digit            ;    call the display_digit routine and then return
    goto begin                    ;    go back to the beginning and do it all again.



check_keypad                ;    This routine will scan the keypad for any key presses.

        movf what_button, w        ;    we want to copy our last digit that was pressed into w
                                ;    so just in case we DON'T press a key in this keypad scan
                                ;    because at the end of this sub-routine, we will automatically
                                ;    w back into what_button variable. This ensures that we keep the
                                ;    last digit pressed on the display.

        bsf PORTA, RA0            ;    lets scan the first column of keys       
        btfsc PORTA, RA3            ;    has the 1 key been pressed? if yes then
        movlw d'01'                ;    copy decimal number 01 into w. but if not then continue on.
        btfsc PORTA, RA4            ;    has the 4 key been pressed? if yes then
        movlw d'04'                ;    copy decimal number 04 into w. but if not then continue on.
        btfsc PORTB, RB7            ;    has the 7 key been pressed? if yes then
        movlw d'07'                ;    copy decimal number 07 into w. but if not then continue on.
        btfsc PORTB, RB6            ;    has the * key been pressed? if yes then, aqui se cambio portA por port B
        movlw d'10'                ;    copy decimal number 10 into w. but if not then continue on.
        bcf PORTA, RA0            ;    now we have finished scanning the first column of keys
           
        bsf PORTA, RA1            ;    lets scan the middle column of keys
        btfsc PORTA, RA3            ;    has the 2 key been pressed? if yes then
        movlw d'02'                ;    copy decimal number 02 into w. but if not then continue on.
        btfsc PORTA, RA4            ;    has the 5 key been pressed? if yes then
        movlw d'05'                ;    copy decimal number 05 into w. but if not then continue on.
        btfsc PORTB, RB7            ;    has the 8 key been pressed? if yes then
        movlw d'08'                ;    copy decimal number 08 into w. but if not then continue on.
        btfsc PORTB, RB6            ;    has the 0 key been pressed? if yes then
        movlw d'00'                ;    copy decimal number 00 into w. but if not then continue on.
        bcf PORTA, RA1            ;    now we have finished scanning the middle column of keys
           
        bsf PORTA, RA2            ;    lets scan the last column of keys
        btfsc PORTA, RA3            ;    has the 3 key been pressed? if yes then
        movlw d'03'                ;    copy decimal number 03 into w. but if not then continue on.
        btfsc PORTA, RA4            ;    has the 6 key been pressed? if yes then
        movlw d'06'                ;    copy decimal number 06 into w. but if not then continue on.
        btfsc PORTB, RB7            ;    has the 9 key been pressed? if yes then
        movlw d'09'                ;    copy decimal number 09 into w. but if not then continue on.
        btfsc PORTB, RB6            ;    has the # key been pressed? if yes then
        movlw d'11'                ;    copy decimal number 11 into w. but if not then continue on.
        bcf PORTA, RA2            ;    now we have finished scanning the last column of keys

        movwf what_button        ;    When we get here, we will have a certain number in our w register,
                                ;    we then copy it from w into what_button so we can use it to jump
                                ;    to a certain retlw instruction to grab the relevant data to display
                                ;    the digit that we pressed.
            return                        ;    and now return to the main routine



display_digit                    ;    This sub-routine will show the digit on the display
    call digit_data                ;    call digit_data to grab our relevent 8-bits of info
                                ;    for whatever button we had pressed.
    movwf PORTC                    ;    and move this 8-bits of data to PORTC for display on the display
    return                        ;    and then return to our main program


   
   
   
   
   
   
    delay                            ;    here is a nice and simple delay routine
    movlw d'255'                ;    copy the maximum number to our working register (decimal 255)
    movwf delay_1                ;    and now copy it from the w register to delay_1 and delay_2
    movwf delay_2                ;    Now the rest of the routine will focus on counting down to zero.
delay_loop                        ;    We come back to this label when we have not yet reached zero.
    decfsz delay_1, f            ;    decrement whatever is in delay_1 by 1 and store the answer back in delay_1
        goto delay_loop            ;    if the answer is not zero, then go back to the delay_loop label. but if the
    decfsz delay_2, f            ;    answer is zero then decrement delay_2 by one and store the answer in delay_2
        goto delay_loop            ;    if the answer is not zero, then go back to delay_loop label. but if the answer
    return                        ;    is zero, then we have completed our delay and now we can return to our main program!



    end                            ;    We always need to have end at the end, even if we don't want the program
                                ;    to actually end, it still must be here!
 

Attachments

jpanhalt

Joined Jan 18, 2008
7,893
The problem is that I have all the time W with a value that repeats on time (since it is a loop), since for example I press 1, the value is shown in the display, but after I reléase the button, the value in W still there, so I dont know how to diferentiate when a real new value is coming, to put it in the other display and turn the right transistor.
I have not gone though your entire code nor tried to simulate it. But, using just your statement of the problem, you are trying to base a response on a previous response/result . For example, where did the value in WREG come from, was it a ones or a tens? One way is to set a flag, e.g., flag0,0 clear = ones , flag0,0 set = tens source. I do not like doing that, but it works. Another way is to write loops and calls. Thus, when in the ones loop, a call to putchar routine with "chip select" low (done in the loop), the ones are turned on. When in the tens loop, a call to the same putchar routine with with a "chip select" bit high lights the tens digit. If your call involves less than an 8-bit register (as ascii characters do), then your chip select can be part of what you send to your "putchar" routine. It is just like a flag, but without the extra register.

I do not think you want to "erase" WREG. There is no such thing.
 

Thread Starter

Cristian Cox

Joined May 13, 2017
18
I have not gone though your entire code nor tried to simulate it. But, using just your statement of the problem, you are trying to base a response on a previous response/result . For example, where did the value in WREG come from, was it a ones or a tens? One way is to set a flag, e.g., flag0,0 clear = ones , flag0,0 set = tens source. I do not like doing that, but it works. Another way is to write loops and calls. Thus, when in the ones loop, a call to putchar routine with "chip select" low (done in the loop), the ones are turned on. When in the tens loop, a call to the same putchar routine with with a "chip select" bit high lights the tens digit. If your call involves less than an 8-bit register (as ascii characters do), then your chip select can be part of what you send to your "putchar" routine. It is just like a flag, but without the extra register.

I do not think you want to "erase" WREG. There is no such thing.

Thanks for the info, I Will check it
 

Thread Starter

Cristian Cox

Joined May 13, 2017
18
Top