NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.
Microcontroller Programming » Reprogramming LCD pins
May 23, 2009 by andy_b1986 |
Hello Im trying to reprogramme the chips lcd functions in order to move one pin 'PD3'. This is so that i can use the lcd whilst using this pin number for the RC Car project. I tried just unplugging it to see what this particular pin did (hoping that it wouldnt be needed) but it seems to be the pin which updates or refeshes the screen as the screen freezes when PD3 is unplugged. I have had a look at the datasheet and cross referenced with the header file lcd.h and the lcd.c files in the library. To be honest all i could do was to find the pin number as i have no idea what to look for. Has anyone got an idea, or has done the recoding in order for whatever information is coming out of that pin, to be output on a different pin? |
---|---|
May 23, 2009 by wayward |
Hello, in the NerdKits setup, PD3 is second-lowest bit of the command/data bus between the microcontroller and the LCD driver. That means: if you detach it, LCD driver will not be getting valid commands to initialize, clear screen, move the cursor, etc. nor will it be receiving any valid data to print. There are ways to free the pin(s) that you need, but they all require you to modify the lcd.c file. Commands and data are sent by directly changing the corresponding pins' values, so if you want to shift the pins around, you will have to modify the code so that outgoing bits are mapped to appropriate pins. If you have an 74 series 174 flip-flop lying around, you can use it to build a two-wire interface to the uC (see my Vicious Alarm Clock thread). Otherwise, you'll have to play with the pins and bits. Good luck, and keep us posted! |
May 24, 2009 by andy_b1986 |
when you say pins and bits do you mean the '0xfc' address name for the group of pins and then the bit number so PD3 would be bit number 3? i was up late last night reading the datasheet so I might have confused something. How would I then tell this specific pin to be output on say pin number PB3/OC2A? in the lcd.c file there is a piece of code
is this the section which i need to change? do i need to do anything else to the existing lcd.c file? Unfortunately i dont have any flip flops and i am running out of time for my project any help would be much appreciated! Im quite new to this and so there are still a lot of walls to climb! cheers |
May 24, 2009 by wayward |
Yes, that is one part of what you need to change. Since you want PD3 free, first you need to skip setting its data direction to 1 (which sets it as output). The line in the code
is just a shorthand for: DDRD |= (1<<PD7)|(1<<PD6)|(1<<PD5)|(1<<PD4)|(1<<PD3)|(1<<PD2) (the comment above is wrong, it should read "output on PD7, PD6, and PD2-5"). This sets all the aforementioned pins to output. If you're a stranger to bitwise operations and shifting, a quick explanation: PD0..7 are numbers from 0 to 7. Bits in a byte are also ordered from 0 to 7, but we can't access them directly; we have to get to them using AND/OR (& and | in C) bitwise operations. Another important operation is binary shift, << and >>, which shifts all the bits in a variable a certain number of positions to the left or to the right. So:
So DDRD bits will be ORed with ones, except for the last two. This turns the highest six bits on. Of course, we could have written: DDRD = 0xfc; and that would've worked -- but the reason why we don't is because we might be using PD1 and PD0 somewhere else, and this would force their data direction to change to zero (input). So instead we OR the value of DDRD with ones and zeroes, where 1 will turn a bit on, and 0 will leave it as it was, 0 or 1, regardless. If you drop PD3 from this, your magic value is 252-8, or 0xf4. So that's the first thing you need to do in order to free PD3 for your own nefarious purposes. But that is just the beginning. You also need to select one pin to replace PD3: say, PB3. Then, you will need to add this to the initialization:
And you also need to comb the code and find all references to DDRD and PORTD; examine if the operation on them touches PD3; if it does, make it NOT touch it and instead divert the corresponding bit to DDRB/PORTB, pin PB3. For example, from lcd_write_nibble(char c):
This ANDs PORTD with the complement of 0x0f shifted to the left by two. 0x0f is 00001111; shift by two gives 00111100; complement is 11000011; ANDing a port with 11000011 has the effect of clearing its pins Px2, Px3, Px4 and Px5. Since we don't want to touch PD3, we have to throw it out of the clearing mask: 11000011 becomes 11001011. You can substitute this value directly using its decimal (203) or hexadecimal (0xcb) notation, but it's better to write the bitmask clearly in the code and use those bitwise operations which illustrate your intent. So:
Make a backup of lcd.c, do this through the rest of the code, and try it out! Cheers, Zoran |
May 24, 2009 by mcai8sh4 |
@wayward - Thanks for the explanation, really helped me to grasp this idea!! I've re-read the explanation in the Nerdkits guide a few times, whilst it makes sense, it hadn't fully sunk in. Just a quick question... from what I see here... [quote]So DDRD bits will be ORed with ones, except for the last two. This turns the highest six bits on. Of course, we could have written: DDRD = 0xfc; and that would've worked -- but the reason why we don't is because we might be using PD1 and PD0 somewhere else, and this would force their data direction to change to zero (input). So instead we OR the value of DDRD with ones and zeroes, where 1 will turn a bit on, and 0 will leave it as it was, 0 or 1, regardless.[/quote] I would be better using "PORTC |= t.minutes;" in my binary clock program - I don't think it matters for what I'm doing, but it sounds like it would be good practice. If you get a chance, please have a quick review of my code HERE Also why use hex opposed to base10 - is that just a tradition or are there deeper reasonings? Thanks once again |
May 24, 2009 by andy_b1986 |
thanks a lot guys i will have a go at this tonight really starting to make sense cheers |
May 24, 2009 by wayward |
Sure, you can use PORTC |= t.minutes; but you have to erase the bits first, or else whatever was already there will get ORed with the new value -- not what you want. When we are assigning a value to all bits in a port, we simply do:
instead of functionally equivalent, but in this case more contrived:
As a rule of thumb, use "AND with zeroes; OR with bits" when you only want to turn a number of bits on a port, but leave the other bits unchanged. If you are simply outputting (or reading) a full 8-bit value, just use the assignment, or read from the port: PORTC = byte or byte = PINC. Why hex vs. decimal notation? It's just a matter of convenience, really -- after a while, you learn the hexadecimal digits, which have a superconvenient property that one digit fully maps to 4 bits, so any 8-bit value can be written using two hex digits. When you see "0xfc", for example, you can immediately think of "f c = 1111 1100", because those 16 groups of bits tend to etch themselves in your mind, so after a while, reading a hex number becomes almost the same as seeing the bits typed out. :) I didn't have the stamina to go through your entire program, but do try it out and write us if something doesn't work, then we can see how to fix it. |
May 24, 2009 by mcai8sh4 |
All makes sense now, thanks. I'll play around with different methods until it becomes second nature. Thanks again |
May 24, 2009 by andy_b1986 |
thanks a lot wayward!! it worked!! I tried it without checking the rest of my code and it didnt work first time (nothing ever does ive come to realise). i was testing by using the servo squirter tutorial to update the screen when a command was sent. This code had two lines of code which i just took out as they were being sent to PB3 these were
i just took these two lines out and now the screen is updating to this pin. I can now put the chip and all the other bits into a permanent circuit which will be nicer than the breadboard with all the wires coming out the lcd thanks again! |
May 24, 2009 by andy_b1986 |
"i just took these two lines out and now the screen is updating to this pin" meant to say screen is refreshing with PB3 set to the output that PD3 used to be |
May 25, 2009 by andy_b1986 |
Hello again It all worked well until i put it into a circuit i made. The chip is still controllable through terminal and when I GND pin 14 the screen still does its original function with blocks across line one. However when trying to run the chip normally the same blocks appear on the first line of the LCD and i have checked my wiring loads. The lcd is the HD44780 type, Here is a list of what I have connected each pin to, LCD Pin 1 = GND Rail LCD Pin 2 = +5v Rail LCD Pin 3 = GND Rail LCD Pin 4 = MCU Pin 13 'PD7' LCD Pin 5 = GND Rail LCD Pin 6 = MCU Pin 12 'PD6' LCD Pin 11 = MCU Pin 4 'PD2' LCD Pin 12 = MCU Pin 17 'PB3' LCD Pin 13 = MCU Pin 6 'PD4' LCD Pin 14 = MCU Pin 11 'PD5' Any ideas? |
May 25, 2009 by andy_b1986 |
apologies for previous layout
|
May 25, 2009 by andy_b1986 |
ok ive jsut put everything back onto the breadboard and everything works fine there must be a short happening somewhere in my circuit |
May 25, 2009 by wayward |
Yeah, that sounds like an issue with wiring. |
May 25, 2009 by andy_b1986 |
These are the voltage readings coming out of the chip when on the breadboard;
... and these are the voltage readings coming out of the chip when in my circuit;
does this mean i have a grounding issue somewhere? |
May 25, 2009 by wayward |
Well, this is all well within the measuring tolerance, plus the circuit you have is probably adding a little skew. If the LCD works outside of your circuit, then the software controlling it is correct, there's no two ways about it. If it stops working when you put it in a circuit, as far as my knowledge goes, it can be caused by one or several issues:
If all else fails, you can always use the tried-and-true method of printf()-style debugging, only adjusted for embedded electronics :) Simply add one resistor-LCD pair to your circuit, connect it to GND and one pin on the MCU, then just below the lcd_init() call, set that pin to source current (appropriate DDR and PORT bits on). If the LED stays off, you'll know that the MCU isn't running your program at all, and that's a start. |
May 26, 2009 by andy_b1986 |
the software is correctly working as i can communicate with the kit from laptop. I have had a look on the entire circuit and have tried resoldering some joins everthing looks ok to me and none of the solder is crossing tracks. I have buzzed through a lot of it with ease. What would the capacitor do? would it reduce noise? |
May 26, 2009 by wayward |
Yes, the capacitor that connects across pins 7 and 8 in all of our designs serves to filter out a good portion of the AC component in the power supply to the microcontroller unit. Capacitors serving that purpose are called "bypass capacitors". What kind of a capacitor and what capacitance to use depends on the nature of the circuit and the characteristics of the noise, but 0.1 uF ceramic capacitor seems to be a popular choice for 5V circuits. Here's a rather informative text about them. I really have very little experience with electronics — all I can recommend at this point is to make sure you're using a bypass capacitor, doubly so if you're powering from a transformer, and also beware of radio interference (best to test with a battery first). |
Please log in to post a reply.
Did you know that you can connect a pushbutton to a microcontroller with only one wire? Learn more...
|