Tuesday, May 24, 2011
Controlling a nokia5110 lcd with software SPI on a pic16f84a
My newest project has been implementing a software SPI routine so that my pic (which lacks hardware SPI) can communicate with a cheap nokia 84x48 graphical lcd (later I will show how I wired it up). I've written subroutines in assembly for setting x,y address of the lcd's ram as well as sending data or commands for initialization (8bit, but could be easily modified to work with 9bit color lcd protocols I've seen). I plan on using a look up table to store standard character hex data so that I can make things easier for myself in upcoming projects. I know that my code is pretty inefficient so I plan on fixing it a little later (but not bad for just reading the datasheet and a few hours of coding). I just have the mcu writing "Hello World!" and drawing a video game character sprite at the bottom (I converted the image by hand, but I could easily write a program to do that for me). This is just the beginning, I plan on using this, as well as everything else I've been working on in my projects to come. I plan on adding the ability to animate/scroll text and images and will update the site with the code once I get the chance. I also plan on describing the SPI protocol and lcd commands in detail. For now I will post the code to just write "Hello World" and draw a sprite.
Start BSF 03h,5 ;switch from bank 0 to 1
MOVLW b'00000000' ;Out RB to output
MOVWF 06h
MOVLW b'00000' ;Out RA to output
MOVWF 05h
BCF 03h,5 ;switch from bank 1 to 0
;RB0=sclk
;RB1=sda
;RB2=D_C
;RB3=Sce
;RB4=reset
;RB5=disp pwr
Begin
bsf 06h,3 ;disable serial
bsf 06h,5 ;power on display
nop
bcf 06h,4 ;reset
nop
bsf 06h,4 ;release from reset
; sel extended instruction set (h=1)
movlw b'00100001'
movwf 0Ch
call spi_command
; set Vop (Contrast)
movlw b'10111001'
movwf 0Ch
call spi_command
; sel normal instruction set (h=0)
movlw b'00100000'
movwf 0Ch
call spi_command
; display normal mode
movlw b'00001100'
movwf 0Ch
call spi_command
;---------------------------
; draw H
movlw b'01111111'
movwf 0Ch
call spi_data
movlw b'00001000'
movwf 0Ch
call spi_data
movlw b'00001000'
movwf 0Ch
call spi_data
movlw b'00001000'
movwf 0Ch
call spi_data
movlw b'01111111'
movwf 0Ch
call spi_data
call _space
; draw e
movlw b'00001110'
movwf 0Ch
call spi_data
movlw b'00010101'
movwf 0Ch
call spi_data
movlw b'00010101'
movwf 0Ch
call spi_data
movlw b'00010101'
movwf 0Ch
call spi_data
movlw b'00001100'
movwf 0Ch
call spi_data
call _space
; draw l
movlw b'00000000'
movwf 0Ch
call spi_data
movlw b'01000001'
movwf 0Ch
call spi_data
movlw b'01111111'
movwf 0Ch
call spi_data
movlw b'00000001'
movwf 0Ch
call spi_data
movlw b'00000000'
movwf 0Ch
call spi_data
call _space
; draw l
movlw b'00000000'
movwf 0Ch
call spi_data
movlw b'01000001'
movwf 0Ch
call spi_data
movlw b'01111111'
movwf 0Ch
call spi_data
movlw b'00000001'
movwf 0Ch
call spi_data
movlw b'00000000'
movwf 0Ch
call spi_data
call _space
; draw o
movlw b'00001110'
movwf 0Ch
call spi_data
movlw b'00010001'
movwf 0Ch
call spi_data
movlw b'00010001'
movwf 0Ch
call spi_data
movlw b'00010001'
movwf 0Ch
call spi_data
movlw b'00001110'
movwf 0Ch
call spi_data
call _space
; goto y=1,x=0
movlw b'00000001'
movwf 0Ch
movlw b'00000000'
movwf 0Dh
call setxy
; draw W
movlw b'01111110'
movwf 0Ch
call spi_data
movlw b'00000001'
movwf 0Ch
call spi_data
movlw b'00001110'
movwf 0Ch
call spi_data
movlw b'00000001'
movwf 0Ch
call spi_data
movlw b'01111110'
movwf 0Ch
call spi_data
call _space
; draw o
movlw b'00001110'
movwf 0Ch
call spi_data
movlw b'00010001'
movwf 0Ch
call spi_data
movlw b'00010001'
movwf 0Ch
call spi_data
movlw b'00010001'
movwf 0Ch
call spi_data
movlw b'00001110'
movwf 0Ch
call spi_data
call _space
; draw r
movlw b'00011111'
movwf 0Ch
call spi_data
movlw b'00001000'
movwf 0Ch
call spi_data
movlw b'00010000'
movwf 0Ch
call spi_data
movlw b'00010000'
movwf 0Ch
call spi_data
movlw b'00001000'
movwf 0Ch
call spi_data
call _space
; draw l
movlw b'00000000'
movwf 0Ch
call spi_data
movlw b'01000001'
movwf 0Ch
call spi_data
movlw b'01111111'
movwf 0Ch
call spi_data
movlw b'00000001'
movwf 0Ch
call spi_data
movlw b'00000000'
movwf 0Ch
call spi_data
call _space
; draw d
movlw b'00001110'
movwf 0Ch
call spi_data
movlw b'00010001'
movwf 0Ch
call spi_data
movlw b'00010001'
movwf 0Ch
call spi_data
movlw b'00001001'
movwf 0Ch
call spi_data
movlw b'01111111'
movwf 0Ch
call spi_data
call _space
; draw !
movlw b'01111101'
movwf 0Ch
call spi_data
;---------------------------
; goto y=5,x=0
movlw b'00000101'
movwf 0Ch
movlw b'00000000'
movwf 0Dh
call setxy
;draw image block 4
movlw b'10000111';1
movwf 0Ch
call spi_data
movlw b'11111101';2
movwf 0Ch
call spi_data
movlw b'10000001';3
movwf 0Ch
call spi_data
movlw b'01100001';4
movwf 0Ch
call spi_data
movlw b'00010001';5
movwf 0Ch
call spi_data
movlw b'11001001';6
movwf 0Ch
call spi_data
movlw b'00100101';7
movwf 0Ch
call spi_data
movlw b'00100101';8
movwf 0Ch
call spi_data
movlw b'11100001';9
movwf 0Ch
call spi_data
movlw b'00011001';10
movwf 0Ch
call spi_data
movlw b'00000101';11
movwf 0Ch
call spi_data
movlw b'00000011';12
movwf 0Ch
call spi_data
movlw b'00000011';13
movwf 0Ch
call spi_data
movlw b'00000001';14
movwf 0Ch
call spi_data
movlw b'00111001';15
movwf 0Ch
call spi_data
movlw b'11101101';16
movwf 0Ch
call spi_data
movlw b'00000111';17
movwf 0Ch
call spi_data
; goto y=4,x=0
movlw b'00000100'
movwf 0Ch
movlw b'00000000'
movwf 0Dh
call setxy
;draw image block 3
movlw b'00000111';1
movwf 0Ch
call spi_data
movlw b'00111100';2
movwf 0Ch
call spi_data
movlw b'01100100';3
movwf 0Ch
call spi_data
movlw b'01010011';4
movwf 0Ch
call spi_data
movlw b'11110000';5
movwf 0Ch
call spi_data
movlw b'00111000';6
movwf 0Ch
call spi_data
movlw b'11111001';7
movwf 0Ch
call spi_data
movlw b'11111011';8
movwf 0Ch
call spi_data
movlw b'10010011';9
movwf 0Ch
call spi_data
movlw b'11110100';10
movwf 0Ch
call spi_data
movlw b'11110100';11
movwf 0Ch
call spi_data
movlw b'01110100';12
movwf 0Ch
call spi_data
movlw b'01110000';13
movwf 0Ch
call spi_data
movlw b'00010000';14
movwf 0Ch
call spi_data
movlw b'00100100';15
movwf 0Ch
call spi_data
movlw b'10011111';16
movwf 0Ch
call spi_data
movlw b'11010000';17
movwf 0Ch
call spi_data
movlw b'01110000';18
movwf 0Ch
call spi_data
; goto y=3,x=0
movlw b'00000011'
movwf 0Ch
movlw b'00000000'
movwf 0Dh
call setxy
;draw image block 2
movlw b'00011100';1
movwf 0Ch
call spi_data
movlw b'00010110';2
movwf 0Ch
call spi_data
movlw b'00010010';3
movwf 0Ch
call spi_data
movlw b'00010010';4
movwf 0Ch
call spi_data
movlw b'00010011';5
movwf 0Ch
call spi_data
movlw b'00010001';6
movwf 0Ch
call spi_data
movlw b'00110001';7
movwf 0Ch
call spi_data
movlw b'00100000';8
movwf 0Ch
call spi_data
movlw b'01100000';9
movwf 0Ch
call spi_data
movlw b'01000000';10
movwf 0Ch
call spi_data
movlw b'11000000';11
movwf 0Ch
call spi_data
movlw b'10000000';12
movwf 0Ch
call spi_data
movlw b'00000000';13
movwf 0Ch
call spi_data
movlw b'00000010';14
movwf 0Ch
call spi_data
movlw b'00011111';15
movwf 0Ch
call spi_data
movlw b'01110001';16
movwf 0Ch
call spi_data
movlw b'11000000';17
movwf 0Ch
call spi_data
; goto y=2,x=12
movlw b'00000010'
movwf 0Ch
movlw b'00001100'
movwf 0Dh
call setxy
;draw image block 1
movlw b'00000001';12
movwf 0Ch
call spi_data
movlw b'00000001';13
movwf 0Ch
call spi_data
movlw b'00000011';14
movwf 0Ch
call spi_data
movlw b'00000010';15
movwf 0Ch
call spi_data
movlw b'00000010';16
movwf 0Ch
call spi_data
movlw b'00000011';17
movwf 0Ch
call spi_data
a goto a
;----------------------------
spi_command
bcf 06h,3 ;start serial transmission
bcf 06h,2 ;D_C=0
btfss 0Ch,7
goto c1
call one
goto c1n
c1 call zero
c1n btfss 0Ch,6
goto c2
call one
goto c2n
c2 call zero
c2n btfss 0Ch,5
goto c3
call one
goto c3n
c3 call zero
c3n btfss 0Ch,4
goto c4
call one
goto c4n
c4 call zero
c4n btfss 0Ch,3
goto c5
call one
goto c5n
c5 call zero
c5n btfss 0Ch,2
goto c6
call one
goto c6n
c6 call zero
c6n btfss 0Ch,1
goto c7
call one
goto c7n
c7 call zero
c7n btfss 0Ch,0
goto cd
call one
goto cdn
cd call zero
cdn bcf 06h,0
bsf 06h,3 ;end serial transmission
return
spi_data
bcf 06h,3 ;start serial transmission
bsf 06h,2 ;D_C=1
btfss 0Ch,0
goto b1
call one
goto b1n
b1 call zero
b1n btfss 0Ch,1
goto b2
call one
goto b2n
b2 call zero
b2n btfss 0Ch,2
goto b3
call one
goto b3n
b3 call zero
b3n btfss 0Ch,3
goto b4
call one
goto b4n
b4 call zero
b4n btfss 0Ch,4
goto b5
call one
goto b5n
b5 call zero
b5n btfss 0Ch,5
goto b6
call one
goto b6n
b6 call zero
b6n btfss 0Ch,6
goto b7
call one
goto b7n
b7 call zero
b7n btfss 0Ch,7
goto d
call one
goto dn
d call zero
dn bcf 06h,0
bsf 06h,3 ;end serial transmission
return
zero
bcf 06h,0
bcf 06h,1 ;0
bsf 06h,0 ;sclk pulse
return
one
bcf 06h,0
bsf 06h,1 ;1
bsf 06h,0 ;sclk pulse
return
_space ;send byte='00000000', draw space
movlw b'00000000'
movwf 0Ch
call spi_data
return
setxy
bsf 0Ch,6
call spi_command
bsf 0Dh,7
movf 0Dh,0
movwf 0Ch
call spi_command
return
end
Tuesday, May 10, 2011
Capacitive Touch Sensor for pic16F84A (no special hardware required)
Here is my newest project I've been working on. I'll get more details up when I have the time. In the mean while enjoy the video.
//return current;
}
Update: Sorry its been awhile since my last update. I've been busy with work and my other projects. The capacitive sensing input is really simple because everything is done in software. Here's my hand drawn schematic for the input stage generalized so that any mcu can be used (For some reason I haven't yet installed a schematic program on my netbook and I don't feel like booting up my other laptop).
It's amazing that all you really need is a single gpio and a resistor (the capacitance is provided by the traces on the breadboard). The ten megaohm resistor allows the discharge rate for the stray capacitance to be slowed down enough for the uC to measure. The uC just continually charges up this capacitance, puts the pin into high impedance by making it an input, and then counts until it measures the "capacitor" is discharged. This count can then be analyzed to determine if the pin has been pressed or not (the count increases if the button is pressed because your finger adds to the stray capacitance in parallel which increases the discharge time). That's pretty much all that's necessary other than some fancy algorithms for error proofing detection.
Update 2: I've finally gotten around to porting my capacitive touch sensing code to C. The code should work for most PICs and can be easily modified to change pin assignments and whatnot to work on any other chip you might need. Below you will find the function freqcapsense. All you need to do is call it and it will sense whether RA0 is being touch or not. I've included averaging multiple samples and an adjustable threshold in order to tweak the sensitivity and accuracy for any given setup. You can have it return a 1 or 0 for touch status or by commenting out the if else statement at the end and uncommenting the return current statement it will return the raw period value it is reading from the pin. Enjoy.
int freqcapsense(){
unsigned int avg;
unsigned int current=0;
unsigned int thresh=29;
unsigned int avg;
unsigned int current=0;
unsigned int thresh=29;
unsigned int trials=10;
while(trials>0){
TRISA=0b0;
RA0=1;
delay();
TRISA=0b1;
while(RA0==1){current++;}
trials--;
avg=(avg+current)/2;
}
while(trials>0){
TRISA=0b0;
RA0=1;
delay();
TRISA=0b1;
while(RA0==1){current++;}
trials--;
avg=(avg+current)/2;
}
if((current-avg)>thresh){return 1;}
else{return 0;}
else{return 0;}
//return current;
}
Subscribe to:
Posts (Atom)