nuetron 64 Posted May 31, 2011 Share Posted May 31, 2011 Hello again, I've been working on a modification of RobG's code ( http://www.43oh.com/forum/viewtopic.php?f=9&t=540 ), for several chips to be controlled by a 'G2231, not just one LCD. When I have this program downloaded to the chip, I tell it to "go", nothing happens. The LEDs on bits 0 & 6 don't even flicker, as they have done with other projects. I'm using IAR kickstart with a launchpad, no errors. Tried another project on it, "Flashing The LED", works like it should. Here's the code: #include "msp430g2231.h" #include "msp430.h" #define sendData(data) send(data, 1); dataBus() #define sendInstruction(data) send(data, 0); dataBus() #define sendAddress(data) send(data, 0); addressBus() #define addressBus() P1OUT |= SELECTPIN2; __delay_cycles(100); P1OUT &= ~SELECTPIN2; __delay_cycles(100); P1OUT |= SELECTPIN2; #define dataBus() P1OUT |= SELECTPIN1; __delay_cycles(100); P1OUT &= ~SELECTPIN1; __delay_cycles(100); P1OUT |= SELECTPIN1; #define DATAPIN BIT7 #define CLOCKPIN BIT6 #define WRITEPIN BIT5 #define SELECTPIN2 BIT4 #define SELECTPIN1 BIT0 void send(char data, char registerSelect); void sendDataArray(char data[], char length); char charIndex = 0; char bitCounter = 0; void main(void) { WDTCTL = WDTPW + WDTHOLD; __delay_cycles(1000); P1OUT &= ~(CLOCKPIN + DATAPIN); P1OUT |= WRITEPIN; P1DIR |= WRITEPIN + CLOCKPIN + DATAPIN; } void sendDataArray(char data[], char length) { charIndex = 0; while(charIndex < length) { sendData(data[charIndex]); charIndex++; } } void send(char data, char registerSelect) { bitCounter = 0; while(bitCounter < 8) { (data & BIT7) ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN); data <<= 1; P1OUT |= CLOCKPIN; P1OUT &= ~CLOCKPIN; bitCounter++; } registerSelect ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN); P1OUT &= ~WRITEPIN; P1OUT |= WRITEPIN; } void testPorts(); void testPorts() { sendAddress(0x33); sendInstruction(0x55); sendData(0xAA); } EDIT: Changed the title to better describe the thread. Quote Link to post Share on other sites
nexusone1984 32 Posted June 3, 2011 Share Posted June 3, 2011 Going to have to think on it why your circuit/code is not working... Why not use two 74HC595 and not use the 4093? If you have a parallel device you will also need a control lines for the device. if it is in 8 bit mode, you would need more then 8 bits to control the device. I think you could get by with 4 lines: data clock latch Write. (maybe even three if you connect the 595's in series) You have to keep in mind timing and data race... you want to data and address information to be stable on the buss. First HC595 holds the 8 bit data, second HC595 holds Address, then latch the data to the output. Depending on how many devices you want to control, could be select a bit on the HC595 for that device. Or use an address to select using a address decoder like 74HC138/HC139. Once you have loaded the data and address, you just change the Write state to load the device. Devices that do not have an enable pin, would have to do something else... but if they have a enable pin, can tie them all in parallel. and select via the enable pin. Quote Link to post Share on other sites
nuetron 64 Posted June 4, 2011 Author Share Posted June 4, 2011 Going to have to think on it why your circuit/code is not working... I figured out what was going on... void main(void) { WDTCTL = WDTPW + WDTHOLD; __delay_cycles(1000); P1OUT &= ~(CLOCKPIN + DATAPIN); P1OUT |= WRITEPIN; P1DIR |= WRITEPIN + CLOCKPIN + DATAPIN; } This is from the script I posted earlier, notice anything peculiar? I forgot to add the "testports()" to it! Here I was, wracking my brain for several hours (and getting a headache in the process), trying to see what I was doing wrong... AND THE PROBLEM WAS RIGHT UNDER MY NOSE!!! :x And then I had to post my foolishness here... Sorry guys... :oops: Anyway, I got it working (properly), and tested a couple of projects on it, flawless. The first one was just writing an 8-bit value to either one of the registers, the second one was a little more complicated. It used two loops, one nested inside the other, to make a shifting LED go from one end of the first register to the other end of the second register, and return to start the loop over again. I did something neat with the magnitude comparator. When the LED reached the end of the first register, it would turn off before the first LED of the next register came on, therefore having a state when none of the LEDs were lit, and both registers had the same data. Put the LED from the mag. comp. between the two sets of eight, and presto! A 17 position ping-pong-ing LED! I had some fun with that for a while (including turning the speed up and changing it from hex 1 to hex 5, two LEDs with a space in between). Here's the code, (modified it from something I found online, don't remember where I got it) it uses the schematic above : //*************************************************************************************** // MSP430 Driver for 74HC595 Shift Register // // Description; Drives 16 LED's with 4 digital pins of the MSP430, via a shift register // // MSP430x2xx // //*************************************************************************************** #include //Define our pins #define DATA BIT7 // DS -> 1.7 #define CLOCK BIT6 // SH_CP -> 1.6 #define LATCH BIT5 // ST_CP -> 1.5 #define LATCH2 BIT4 // ST_CP2 -> 1.4 // Declare functions void delay ( unsigned int ); void pulseClock ( void ); void shiftOut ( unsigned char ); void shiftOut2 ( unsigned char ); void init ( void ); void pinWrite ( unsigned int, unsigned char ); int main( void ) { // Stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; P1DIR |= (DATA + CLOCK + LATCH + LATCH2); // Setup pins as outputs int i, j; //Do a "ping-pong" effect back and forth for(;{ for ( j = 0 ; j < 9 ; j++ ){ shiftOut2(5 << j); delay(25); } for ( i = 0 ; i < 8 ; i++ ){ shiftOut(5 << i); delay(25); } for ( i = 7 ; i >= -1 ; i-- ){ shiftOut(5 << i); delay(25); } for ( j = 7 ; j >= 0 ; j-- ){ shiftOut2(5 << j); delay(25); } } } // Delays by the specified Milliseconds // thanks to: // http://www.threadabort.com/archive/2010/09/05/msp430-delay-function-like-the-arduino.aspx void delay(unsigned int ms) { while (ms--) { __delay_cycles(1000); // set for 16Mhz change it to 1000 for 1 Mhz } } // Writes a value to the specified bitmask/pin. Use built in defines // when calling this, as the shiftOut() function does. // All nonzero values are treated as "high" and zero is "low" void pinWrite( unsigned int bit, unsigned char val ) { if (val){ P1OUT |= bit; } else { P1OUT &= ~bit; } } // Pulse the clock pin void pulseClock( void ) { P1OUT |= CLOCK; P1OUT ^= CLOCK; } // Take the given 8-bit value and shift it out, LSB to MSB void shiftOut(unsigned char val) { //Set latch to low (should be already) P1OUT &= ~LATCH; char i; // Iterate over each bit, set data pin, and pulse the clock to send it // to the shift register for (i = 0; i < 8; i++) { pinWrite(DATA, (val & (1 << i))); pulseClock(); } // Pulse the latch pin to write the values into the storage register P1OUT |= LATCH; P1OUT &= ~LATCH; } // Take the given 8-bit value and shift it out, LSB to MSB void shiftOut2(unsigned char val) { //Set latch to low (should be already) P1OUT &= ~LATCH2; char j; // Iterate over each bit, set data pin, and pulse the clock to send it // to the shift register for (j = 0; j < 8; j++) { pinWrite(DATA, (val & (1 << j))); pulseClock(); } // Pulse the latch pin to write the values into the storage register P1OUT |= LATCH2; P1OUT &= ~LATCH2; } Quote Link to post Share on other sites
nuetron 64 Posted June 4, 2011 Author Share Posted June 4, 2011 Why not use two 74HC595 and not use the 4093? I had only one 74HC595 and two 4094s, couldn't find the other 4094, used the 595 instead. I thought it was convenient though, for anyone who wanted to use this, they didn't have to do much changing to use two 595s or 4094s. If you have a parallel device you will also need a control lines for the device. if it is in 8 bit mode, you would need more then 8 bits to control the device. I think you could get by with 4 lines: data clock latch Write. (maybe even three if you connect the 595's in series) You have to keep in mind timing and data race... you want to data and address information to be stable on the buss. First HC595 holds the 8 bit data, second HC595 holds Address, then latch the data to the output. Depending on how many devices you want to control, could be select a bit on the HC595 for that device. Or use an address to select using a address decoder like 74HC138/HC139. Once you have loaded the data and address, you just change the Write state to load the device. Devices that do not have an enable pin, would have to do something else... but if they have a enable pin, can tie them all in parallel. and select via the enable pin. My thoughts exactly. Here's what I've been working on the past two days: The code I'm still building: #include "msp430g2231.h" #include "msp430.h" //LCD data bus: port A //LCD RS pins: bit 0, port C //LCD1 enable pin: bit 1, port C //LCD2 enable pin: bit 2, port C #define sendDataPA(data) send(data, 0, 0) //send data to port A of the 8255 #define sendDataPB(data) send(data, 0, 1) //send data to port B of the 8255 #define sendDataPC(data) send(data, 1, 0) //send data to port C of the 8255 #define sendInstruction(data) send(data, 1, 1); //send an instruction to the 8255 control register //For LCD No.1 #define PulseLCD1(); sendInstruction(0x02); sendInstruction(0x00); #define sendData1(data) send(data, 0, 0); sendInstruction(0x01); PulseLCD1() #define sendInstruction1(data) send(data, 0, 0); sendInstruction(0x00); PulseLCD1() #define clearDisplay1(); sendData1(0x01); __delay_cycles(2000) //For LCD No.2 #define PulseLCD2(); sendInstruction(0x04); sendInstruction(0x00); #define sendData2(data) send(data, 0, 0); sendInstruction(0x01); PulseLCD2() #define sendInstruction2(data) send(data, 0, 0); sendInstruction(0x00); PulseLCD2() #define clearDisplay2(); sendData2(0x01); __delay_cycles(2000) //For both LCDs #define PulseLCDs(); sendDataPC(0x07); sendDataPC(0x01) #define initDisplays(); sendInstruction1(0x38); sendInstruction2(0x30); sendDataPA(0x0C); PulseLCDs(); sendDataPA(0x01); PulseLCDs(); sendDataPA(0x06); PulseLCDs() #define DATAPIN BIT7 #define CLOCKPIN BIT6 #define WRITEPIN BIT5 #define ADDRPIN BIT4 void send(char data, char A0, char A1); void testports(); char charIndex = 0; char bitCounter = 0; void main(void) { WDTCTL = WDTPW + WDTHOLD; __delay_cycles(1000); P1OUT &= ~(CLOCKPIN + DATAPIN); P1OUT |= WRITEPIN; P1DIR |= WRITEPIN + CLOCKPIN + DATAPIN + ADDRPIN; testports(); //Here now, ha ha } void send(char data, char A0, char A1) { bitCounter = 0; while(bitCounter < 8) { (data & BIT7) ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN); data <<= 1; P1OUT |= CLOCKPIN; P1OUT &= ~CLOCKPIN; bitCounter++; } A0 ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN); A1 ? (P1OUT |= ADDRPIN) : (P1OUT &= ~ADDRPIN); __delay_cycles(100); P1OUT &= ~WRITEPIN; __delay_cycles(400); P1OUT |= WRITEPIN; } void testports() { sendInstruction(0x80); //initialize 8255, Mode 0 initDisplays(); sendDataPC(0x00); //3 LEDs on bits 7, 6, and 5 of port C to test __delay_cycles(50000); sendDataPC(0x20); __delay_cycles(50000); sendDataPC(0x40); __delay_cycles(50000); sendDataPC(0x60); __delay_cycles(50000); sendDataPC(0x80); __delay_cycles(50000); sendDataPC(0xA0); __delay_cycles(50000); sendDataPC(0xC0); __delay_cycles(50000); sendDataPC(0xE0); } An 8255? I like old chips (three 8-bit ports too!). I used the 4094 here because I could just tie the strobe pin high (makes it act like a 74HC164), and not have to worry about latching the data into IT too... As it is I'm already using over 1/4 of the '2231s memory (need to clean it up don't I?). RobG 1 Quote Link to post Share on other sites
nexusone1984 32 Posted June 4, 2011 Share Posted June 4, 2011 I have maxed out code space on the 2231, you have to watch what C library functions you use. Depends on what your trying to do with that chip, you may have to go to another MSP430 with more memory. So far I have just re-written code to save memory space, but in the future maybe will have to go to a larger MSP430. I picked up a 20 pin MSP430 for when I need more I/O and memory, maybe start playing with it soon. I am also old school..... my first computer 1Mhz 8-bit, 16K ram..... Just after learning BASIC, started look at ways to make it do other things. Building custom hardware for it. An 8255? I like old chips (three 8-bit ports too!). I used the 4094 here because I could just tie the strobe pin high (makes it act like a 74HC164), and not have to worry about latching the data into IT too... As it is I'm already using over 1/4 of the '2231s memory (need to clean it up don't I?). Quote Link to post Share on other sites
RobG 1,892 Posted June 4, 2011 Share Posted June 4, 2011 Wow! 8255, the blast from the past. I still have few of those and some from the Z80 series. Quote Link to post Share on other sites
nuetron 64 Posted June 5, 2011 Author Share Posted June 5, 2011 Wow! 8255, the blast from the past. I still have few of those and some from the Z80 series. Cool! I have a lot of old chips I've scavenged from outdated computers, etc. I'll list a few that I didn't have to de-solder: Flash memories: 1 W29C020 512kb x 8 5 128kb x 8; 2 29F010 2 P28F001 1 W29EE011 EEPROMs: 1 XLS28C16AP 2kb x 8 1 28C16A 2kb x 8 1 DS12887A RTC UV-EPROMs: 1 NMC27C32BQ 2kb x 8 1 M5M27C101K 128kb x 8 1 HN27C1024HG 64k-word x 16-bit E-EPROM: 1 W27E512 64kb x 8 8051-family micros, 1 ea.: P87C52EBPN, windowless P8748N, windowless M80C31F SCN8048A P8039AHL A few 32kb x 8 static rams, somewhere... I/O: 2 8155H 256-bytes x 8, 2 8-bit i/o ports //Z80 series? has ALE 2 8255A 3 8-bit i/o ports 3 8755A 2kb x 8 UV-EPROM, 2 8-bit i/o ports //Z80 series? has ALE PS/2 keyboard/mouse controller: W83C43, (IDEAS??!! :twisted: ) These are all the ones I have handy at the moment. If y'all need info on a chip, enter the number into one of these sites' search boxes: http://datasheetcatalog.com/ http://www.datasheetarchive.com/ (edit) I also have these two interesting chips: YM3812 YM3814, DAC for YM3812 oscilator These two are really cool! The 3812 has all kinds of tones, so with a little software control, can play any tune! Quote Link to post Share on other sites
nuetron 64 Posted June 5, 2011 Author Share Posted June 5, 2011 Added two LCDs. #include "msp430g2231.h" #include "msp430.h" #define sendDataPA(data) send(data, 0, 0) //send data to port A of the 8255 #define sendDataPB(data) send(data, 0, 1) //send data to port B of the 8255 #define sendDataPC(data) send(data, 1, 0) //send data to port C of the 8255 #define sendInstruction(data) send(data, 1, 1); //send an instruction to the 8255 control register //For LCD No.1 #define PulseLCD1(); sendInstruction(0x03); sendInstruction(0x02); #define sendData1(data) send(data, 0, 0); sendInstruction(0x01); PulseLCD1() #define sendInstruction1(data) send(data, 0, 0); sendInstruction(0x00); PulseLCD1() #define clearDisplay1(); sendData1(0x01); __delay_cycles(2000) //For LCD No.2 #define PulseLCD2(); sendInstruction(0x05); sendInstruction(0x04); #define sendData2(data) send(data, 0, 0); sendInstruction(0x01); PulseLCD2() #define sendInstruction2(data) send(data, 0, 0); sendInstruction(0x00); PulseLCD2() #define clearDisplay2(); sendData2(0x01); __delay_cycles(2000) //For both LCDs #define PulseLCDs(); PulseLCD1(); PulseLCD2(); #define initDisplays(); sendDataPA(0x38); PulseLCDs(); sendDataPA(0x0E); PulseLCDs(); sendDataPA(0x01); PulseLCDs(); sendDataPA(0x06); PulseLCDs() #define DATAPIN BIT7 #define CLOCKPIN BIT6 #define WRITEPIN BIT5 #define ADDRPIN BIT4 #define CSPIN BIT0 //just for fun, pin 6 of 8255 void send(char data, char A0, char A1); void testports(); void PrintStr1(char *Text); void PrintStr2(char *Text); char charIndex = 0; char bitCounter = 0; void main(void) { WDTCTL = WDTPW + WDTHOLD; __delay_cycles(1000); P1OUT &= ~(CLOCKPIN + DATAPIN); P1OUT |= WRITEPIN; P1DIR |= WRITEPIN + CLOCKPIN + DATAPIN + ADDRPIN + CSPIN; P1OUT &= ~CSPIN; __delay_cycles(100000); testports(); //Here now, ha ha P1OUT |= CSPIN; } void send(char data, char A0, char A1) { bitCounter = 0; while(bitCounter < 8) { (data & BIT7) ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN); data <<= 1; P1OUT |= CLOCKPIN; P1OUT &= ~CLOCKPIN; bitCounter++; } A0 ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN); A1 ? (P1OUT |= ADDRPIN) : (P1OUT &= ~ADDRPIN); __delay_cycles(400); P1OUT &= ~WRITEPIN; __delay_cycles(400); P1OUT |= WRITEPIN; } void testports() { sendInstruction(0xA0); initDisplays(); PrintStr1("Hello Ibby!"); // my little sister sendInstruction1(0xC0); //DDRAM address 64 (next line) PrintStr1("Hello Mom!"); PrintStr2("Hello Da"); //I did this because LCD#2 is an 8x2, but looks like 16x1 sendInstruction2(0xC0); //DDRAM address 64 (next line) PrintStr2("d!"); } void PrintStr1(char *Text) { //print a string on lcd1 char *c; c = Text; while ((c != 0) && (*c != 0)) { sendData1(*c); c++; } } void PrintStr2(char *Text) { //print a string on lcd2 char *c; c = Text; while ((c != 0) && (*c != 0)) { sendData2(*c); c++; } } Quote Link to post Share on other sites
nexusone1984 32 Posted June 6, 2011 Share Posted June 6, 2011 I have some Z80 boards hanging around also..... Even the remains of a old arcade machine motherboards. Wow! 8255, the blast from the past. I still have few of those and some from the Z80 series. Quote Link to post Share on other sites
nuetron 64 Posted June 11, 2011 Author Share Posted June 11, 2011 I'm having trouble with a 35-bit shift register and my micro. I tell my 'g2231 to send a 36-bit value to the M5451 (one start bit), but it's only displaying the first 8 bits. I tested the M5451 by hand, it does what it should. I'm still using variations of RobG's code for the LCD. My code: //*************************************************************************************** // MSP430 Driver for 2 Shift Registers // // Description; Drives 35 LEDs and one LCD with 4 digital pins of the MSP430, via two shift registers // // MSP430x2xx // //*************************************************************************************** #include #define sendLCDData(data) send(data, 1); #define sendLCDcmd(data) send(data, 0); #define clearDisplay(); sendLCDcmd(0x01); __delay_cycles(2000) #define initDisplay(); sendLCDcmd(0x38); sendLCDcmd(0x0C); clearDisplay(); sendLCDcmd(0x06); //Define our pins #define DATAPIN BIT7 #define CLOCKPIN BIT6 #define ENABLEPIN BIT5 #define LEDCLOCKPIN BIT4 // Declare functions void delay ( unsigned int ); void pulseClock ( void ); void shiftOut (unsigned char ); void pinWrite (unsigned int, unsigned char ); char bitCounter = 0; void send(char data, char RegisterSelect); void PrintStr(char *Text); int main( void ) { // Stop watchdog timer to prevent time out reset WDTCTL = WDTPW + WDTHOLD; P1DIR |= (DATAPIN + CLOCKPIN + ENABLEPIN + LEDCLOCKPIN); // Setup pins as outputs __delay_cycles(100000); initDisplay(); __delay_cycles(100000); sendLCDcmd(0x80); PrintStr("Hello, 43oh.com!"); sendLCDcmd(0xC0); PrintStr("This is a 35LED "); __delay_cycles(3000000); sendLCDcmd(0x80); PrintStr("ping-pong, with "); sendLCDcmd(0xC0); PrintStr("an LCD display. "); __delay_cycles(3000000); int i; //Do a "ping-pong" effect back and forth for(;{ for ( i = 0 ; i < 35 ; i++ ){ shiftOut(1 << i); delay(25); } for ( i = 34 ; i >= 0 ; i-- ){ shiftOut(1 << i); delay(25); } } } void send(char data, char RegisterSelect) { //For LCD on 8255 bitCounter = 0; while(bitCounter < 8) { (data & BIT7) ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN); data <<= 1; P1OUT |= CLOCKPIN; P1OUT &= ~CLOCKPIN; bitCounter++; } RegisterSelect ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN); P1OUT |= ENABLEPIN; P1OUT &= ~ENABLEPIN; } void PrintStr(char *Text) { //For LCD on 8255 char *c; c = Text; while ((c != 0) && (*c != 0)) { sendLCDData(*c); c++; } } // Delays by the specified Milliseconds // thanks to: // http://www.threadabort.com/archive/2010/09/05/msp430-delay-function-like-the-arduino.aspx void delay(unsigned int ms) { while (ms--) { __delay_cycles(1000); // set for 16Mhz change it to 1000 for 1 Mhz } } // Writes a value to the specified bitmask/pin. Use built in defines // when calling this, as the shiftOut() function does. // All nonzero values are treated as "high" and zero is "low" void pinWrite(unsigned int bit, unsigned char val ) { if (val){ P1OUT |= bit; } else { P1OUT &= ~bit; } } // Pulse the clock pin void pulseClock( void ) { P1OUT |= LEDCLOCKPIN; __delay_cycles(10); P1OUT ^= LEDCLOCKPIN; } // Take the given 8-bit value and shift it out, LSB to MSB void shiftOut(unsigned char val) { P1OUT |= DATAPIN; pulseClock(); char i; // Iterate over each bit, set data pin, and pulse the clock to send it // to the shift register for (i = 0; i < 36; i++) { pinWrite(DATAPIN, (val & (1 << i))); pulseClock(); } } I've attached the datasheet for the M5451, hopefully y'all can view it. PS: I stayed up a quarter past midnight last night, trying to figure this out... :x M5451B7.PDF Quote Link to post Share on other sites
oPossum 1,083 Posted June 11, 2011 Share Posted June 11, 2011 This would have to be an unsigned long long to do 35 bits. CCS doesn't support long long, so the best you can do is use unsigned long for 32 bits. void shiftOut(unsigned char val) { nuetron 1 Quote Link to post Share on other sites
nuetron 64 Posted June 11, 2011 Author Share Posted June 11, 2011 Well, I'm using IAR kickstart. I used unsigned long, gave me only 16 bits. Long long next, no errors, still 16. I was planning to enter this in the POM contest, if I could get it working. Quote Link to post Share on other sites
nuetron 64 Posted June 14, 2011 Author Share Posted June 14, 2011 Got it going, entered in the POTM. Quote Link to post Share on other sites
bluehash 1,581 Posted June 14, 2011 Share Posted June 14, 2011 Looking good. Edited your potm post to also point to your build thread. Also, do you have a pic,video or a demo of it. It helps to visualize your project. Thanks! nuetron 1 Quote Link to post Share on other sites
nuetron 64 Posted June 15, 2011 Author Share Posted June 15, 2011 Thank you! I had tried to, but it messed up. I think it was my slow internet connection, will try again. Do I need a Youtube account to post videos? Thanks again, Nate Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.