Hi. I am quite new to PIC programming (as well as this forum ^_^), and so naturally I stumble across issues that I seem to be unable to figure out, and so I would like to ask for your assistance with something. Jumping into multiplexing, working on 3 7-segment displays, I seem to have trouble even getting the PIC to run my code. So let me start with that issue.
The PIC seems to not like to just run. With a prior program, which simply went through a list of pre-programmed outputs, it would require me to remove Vss, reset several times (using a direct link of +5 volts to ground (which is how this Velleman programmer does it, so why not)), and then it would run. Then I would re-attach Vss. Now, this is odd, but I guess the CPU is able to run without Vss connected via other routes to ground (through the LCD itself). This is in contrast with example programs, which ran fine on the board, however this program I wrote would not at all. The difference here is that I am running the chip off of the internal RC oscillator, which could have possibly been damaged or something, as I haven't always been so nice with inputting power. (Indeed, adding a fresh 9-volt battery to the circuit actually caused the LM7805 VRM to get quite hot; since then, added 100ohm resister in-line with the +9volts to it).
In terms of how the circuit is actually set up, it is as follows:
470uF capacitor in parallel from power input
100 ohm resistor connected to the LM7805 input; of course ground to ground and;
+5 volts leading to Vdd and through 1000 ohm resistor to MCLR
Momentary switch connected from the Vdd rail directly to ground for reset
470 ohm resistor connected from ground to all 3 collectors of NPN transistors (series)
Each base goes to pins A0-A2 on the PIC. The emitters, of course, are to the LCD's grounds.
Each positive terminal of all LCDs are wired together, with each respective pin connected from pins B0-B6. B7 is not wired for the period.
The point of this setup is that the PIC will use the transistors to turn on and off each display in order, and once it is changed, display what is needed. Obviously since the others will be turned off, this will allow for each character to be displayed over a shard bus, thus limiting pins used (as you know).
And please hold back criticism of how I wired it. I know not a lot about actual electronics, as now a primary interest is knowing how CPU's work. Programming a small computer in assembly is kind of cool, and the PIC makes this simple. But any addition to how I should set it up for more effectiveness, let me know.
A picture of the breadboard is as an attached picture. Not the random characters of the display; I did not program any character like that, and also each display is to output different characters. Sometimes LCD's 1 and 3 are lit, sometimes just 1. Prior to the newest revision of the code, ONLY LCD 3 would light up. So something must be working, but now as fully as it should.
In terms of the software, I am going about it by calling an interrupt using timer 0. In the interrupt, it basically should decide based on a counter register which display to output next, set up the output in a subroutine, reset the interrupt, then exit the interrupt routine. Each LCD output is assigned to a register, so basically setting up the output involves moving the contents of this register to the B output pins, and setting the appropriate transistor to display it. This allows me to build main programs that simply place whatever needs to be shown into a register, and the interrupt takes care of outputting it and multiplexing. This leaves me a problem of how I can make a simple counter (as I am also using a table of the proper outputs to make the right decimal character), but to that when it actually works.
To stop rambling, here is the entire program. This is a PIC 16F627, BTW:
Any suggestions or comments, feel free to post. I will possibly try getting a crystal on here, as it seems to be the difference between working without issue and working with issue, and so perhaps that is just the problem. Not sure if I should run timer 0 on an external source either.
EDIT: Trying it with a 4MHz oscillator did not work either, nor did an external resistor. This has me stumped..
The PIC seems to not like to just run. With a prior program, which simply went through a list of pre-programmed outputs, it would require me to remove Vss, reset several times (using a direct link of +5 volts to ground (which is how this Velleman programmer does it, so why not)), and then it would run. Then I would re-attach Vss. Now, this is odd, but I guess the CPU is able to run without Vss connected via other routes to ground (through the LCD itself). This is in contrast with example programs, which ran fine on the board, however this program I wrote would not at all. The difference here is that I am running the chip off of the internal RC oscillator, which could have possibly been damaged or something, as I haven't always been so nice with inputting power. (Indeed, adding a fresh 9-volt battery to the circuit actually caused the LM7805 VRM to get quite hot; since then, added 100ohm resister in-line with the +9volts to it).
In terms of how the circuit is actually set up, it is as follows:
470uF capacitor in parallel from power input
100 ohm resistor connected to the LM7805 input; of course ground to ground and;
+5 volts leading to Vdd and through 1000 ohm resistor to MCLR
Momentary switch connected from the Vdd rail directly to ground for reset
470 ohm resistor connected from ground to all 3 collectors of NPN transistors (series)
Each base goes to pins A0-A2 on the PIC. The emitters, of course, are to the LCD's grounds.
Each positive terminal of all LCDs are wired together, with each respective pin connected from pins B0-B6. B7 is not wired for the period.
The point of this setup is that the PIC will use the transistors to turn on and off each display in order, and once it is changed, display what is needed. Obviously since the others will be turned off, this will allow for each character to be displayed over a shard bus, thus limiting pins used (as you know).
And please hold back criticism of how I wired it. I know not a lot about actual electronics, as now a primary interest is knowing how CPU's work. Programming a small computer in assembly is kind of cool, and the PIC makes this simple. But any addition to how I should set it up for more effectiveness, let me know.
A picture of the breadboard is as an attached picture. Not the random characters of the display; I did not program any character like that, and also each display is to output different characters. Sometimes LCD's 1 and 3 are lit, sometimes just 1. Prior to the newest revision of the code, ONLY LCD 3 would light up. So something must be working, but now as fully as it should.
In terms of the software, I am going about it by calling an interrupt using timer 0. In the interrupt, it basically should decide based on a counter register which display to output next, set up the output in a subroutine, reset the interrupt, then exit the interrupt routine. Each LCD output is assigned to a register, so basically setting up the output involves moving the contents of this register to the B output pins, and setting the appropriate transistor to display it. This allows me to build main programs that simply place whatever needs to be shown into a register, and the interrupt takes care of outputting it and multiplexing. This leaves me a problem of how I can make a simple counter (as I am also using a table of the proper outputs to make the right decimal character), but to that when it actually works.
To stop rambling, here is the entire program. This is a PIC 16F627, BTW:
Code:
ORG 0x04
call LCD_INT
#include <Z:\P16F627.inc>
OPTION EQU 0x81 ;Some assembler issue; not even used anyway :(
__CONFIG _BODEN_OFF & _CP_OFF & _DATA_CP_OFF & _PWRTE_OFF & _WDT_OFF & _LVP_OFF & _MCLRE_ON & _INTRC_OSC_NOCLKOUT
;Table of LCD outs; each will be loaded into the approprate LCD out register when needed, to be displayed during interrupt
RESET
bcf STATUS,RP0
ZERO equ 0x20
movlw b'01111101'
movwf ZERO
ONE equ 0x21
movlw b'00110000'
movwf ONE
TWO equ 0x22
movlw b'01101110'
movwf TWO
THREE equ 0x23
movlw b'01111010'
movwf THREE
FOUR equ 0x24
movlw b'00110011'
movwf FOUR
FIVE equ 0x25
movlw b'01011011'
movwf FIVE
SIX equ 0x26
movlw b'01011111'
movwf SIX
SEVEN equ 0x27
movlw b'01110000'
movwf SEVEN
EIGHT equ 0x28
movlw b'01111111'
movwf EIGHT
NINE equ 0x29
movlw b'01111011'
movwf NINE
DOT equ 0x2A
movlw b'10000000'
movwf DOT
;Set all B pins output
bsf STATUS,RP0
movlw 0x00
movwf TRISB
;Set first 3 A pins output=
movlw b'11111000'
movwf TRISA
bcf STATUS,RP0
;Declare LCD registers
LCD_1 equ 0x70
LCD_2 equ 0x71
LCD_3 equ 0x72
;Set up timer0 and interrupt
LCD_STATUS equ 0x7F ;Status of which LCD to ouput on next interrupt
clrf TMR0
bsf STATUS,RP0
bcf 0x81,5 ;Set timer0 to timer mode
bcf 0x81,3 ;enable prescalar
bsf 0x81,0 ;prescalar options
bsf 0x81,1
bsf 0x81,2
bcf INTCON,7 ;Setting up the interrupts, clearing GIE
bcf INTCON,5 ;Then T0IE
bcf INTCON,2 ;And finally T0IF to enable countdown
Start
;Main Program
DELAY_ROUTINE
LOOP equ 0x73 ;Define a register for the countdown
movlw 0xFF ;Set W to FF
movwf LOOP ;Set LOOP to FF
DEL_INCRIM
incfsz LOOP ;Incriment until overflow; if overflowed, skip to return, else repeat decriment
goto DEL_INCRIM
RETLW 0
movf EIGHT,W ;Set a value from the chart to LCD output registers. Will be replaced with counter
movwf LCD_1
movf ZERO,W
movwf LCD_2
movf ONE ,W
movwf LCD_3
LCD_INT ;LCD Interrupt Routine
bcf STATUS,RP0 ;Make sure were on bank 0
btfss LCD_STATUS,0 ;Is the first bit of LCD_STATUS set? If not, go to LCD_1_INIT, else check next bit
goto LCD_1_INIT
btfss LCD_STATUS,1 ;Is the second bit of LCD_STATUS set? If not, go to LCD_2_INIT, else go to LCD_3_INIT
goto LCD_2_INIT
goto LCD_3_INIT
LCD_1_INIT
incf LCD_STATUS ;Incriment LCD_STATUS
movf LCD_1,W ;Move whatever was put in LCD_1 to W
movwf PORTA ;Then to PORTA
movlw 0x01 ;Next, load the appropriate output
movlw PORTB ;And apply it
call DELAY_ROUTINE ;A breif pause...
bsf STATUS,RP0 ;Move to bank 1
bcf INTCON,7 ;Re-enable interrupts
bcf INTCON,5
bcf INTCON,2
RETFIE;Return; each for delay
LCD_2_INIT
incf LCD_STATUS
movf LCD_2,W
movwf PORTA
movlw 0x02
movlw PORTB
call DELAY_ROUTINE
bsf STATUS,RP0
bcf INTCON,7
bcf INTCON,5
bcf INTCON,2
RETFIE
LCD_3_INIT
movf LCD_3,W
movwf PORTA
movlw 0x03
movlw PORTB
call DELAY_ROUTINE
movlw 0x00 ;clear counter, as it needs to repeat
movwf LCD_STATUS
bsf STATUS,RP0
bcf INTCON,7
bcf INTCON,5
bcf INTCON,2
RETFIE
goto Start ;Go back to where the program gets nasty
end
Any suggestions or comments, feel free to post. I will possibly try getting a crystal on here, as it seems to be the difference between working without issue and working with issue, and so perhaps that is just the problem. Not sure if I should run timer 0 on an external source either.
EDIT: Trying it with a 4MHz oscillator did not work either, nor did an external resistor. This has me stumped..
Attachments
Last edited: