Pages: [1] 2   Go Down
Author Topic: Problems with parallel sram  (Read 2467 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

I'm trying to interface an 32k x 8 sram chip with shift registers but somehow it just won't write or read anything. I've tested the shift registers output which seems to be fine.

I've tried the advice given here: http://arduino.cc/forum/index.php/topic,50633.0.html

I've added decoupling capacitors and simplified the reading and writing routine but to no avail.

I've based the shift register setup on this tutorial: http://www.arduino.cc/en/Tutorial/ShiftOut

Here's the code:

Code:
//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;
int bytePins[8] = {2,3,4,5,6,7,9,10};
int CE = A2;
int OE = A1;
int WE = A0;

#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))

/* mode: INPUT or OUTPUT
OUTPUT: for writing out to memory
INPUT: for reading from memory
*/
void setBytePins(int mode){
for(int i=0 ; i < 8 ; i++){
pinMode(bytePins[i], mode);
}
}

void readBytes(unsigned char * buffer, unsigned short addr, int len){
unsigned char b;
setBytePins(INPUT);
digitalWrite(CE, LOW);
digitalWrite(OE, LOW);
digitalWrite(WE, HIGH);
for( int i=0 ; i < len ; i++){
b = readByte((int)addr+i);
buffer[i] = b;
}
}

unsigned char readByte(unsigned short addr){
setAddr(addr);
return getByte();
}

unsigned char getByte(){
unsigned char b=0;
int state;
for( int i=0 ; i < 8 ; i++ ){
state = digitalRead(bytePins[i]);
if( state == HIGH ){
b |= 1 << i;
}else{
b &= ~(1 << i);
}
}
return b;
}

void writeBytes(unsigned char * b, unsigned short addr, int len){
setBytePins(OUTPUT);
digitalWrite(CE, LOW);
digitalWrite(WE, LOW);
for( int i=0 ; i < len ; i++){
writeByte(b[i],(int)addr+i);
}
}

void writeByte(unsigned char b, unsigned short addr){
setAddr(addr);
setByte(b);
writePulse();
}

void setAddr(unsigned short addr){
doubleShiftOut(addr);
}

void setByte(unsigned char b){

for(int i=0 ; i < 8 ; i++){
if( bytePins[i] & (0x1 << i) ){
digitalWrite(bytePins[7-i], HIGH);
}else{
digitalWrite(bytePins[7-i], LOW);
}
}
}

void writePulse(){
digitalWrite(WE, LOW);
delay(10);
digitalWrite(WE, HIGH);
}

void setup() {
  //set pins to output so you can control the shift register
  Serial.begin(9600);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(CE, OUTPUT);
  pinMode(OE, OUTPUT);
  pinMode(WE, OUTPUT);
  setBytePins(OUTPUT);
}

void loop() {

unsigned char in_byte[4] = { 0xf0, 0x42, 0x43, 0xf };
unsigned char out_byte[4] = { 0,0,0,0 };

writeBytes(in_byte, 0x0, 4);
readBytes(out_byte, 0x0, 4);

Serial.print(out_byte[0], BIN);
Serial.print(" ");
Serial.print(out_byte[1], BIN);
Serial.print(" ");
Serial.print(out_byte[2], BIN);
Serial.print(" ");
Serial.println(out_byte[3], BIN);

delay(500);
}

void doubleShiftOut(unsigned short b){
unsigned char b1 = (b & 0xff00) >> 8;
unsigned char b2 = b & 0xff;
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, b1);
shiftOut(dataPin, clockPin, MSBFIRST, b2);
digitalWrite(latchPin, HIGH);
}

This prints the following to the serial line (which should be what I've written to sram):

1100000 1100000 1100000 1100000
1100000 1100000 1100000 1100000
1100000 1100000 1100000 1100000
1100000 1100000 1100000 1100000
1100000 1100000 1100000 1100000
...

The schematic is attached.


* ram-schematic.png (21.65 KB, 1469x1018 - viewed 31 times.)
Logged

nr Bundaberg, Australia
Offline Offline
Tesla Member
***
Karma: 121
Posts: 8461
Scattered showers my arse -- Noah, 2348BC.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Without looking at the code yet, I would remove ALL those caps and put them in the right places. Most of them go from 5v to VCC ! others go from GND to GND, and some are on data and clock lines.

All you need are caps from VCC to GND near each chip.

______
Rob
« Last Edit: July 15, 2011, 07:46:40 pm by Graynomad » Logged

Rob Gray aka the GRAYnomad www.robgray.com

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 180
Posts: 8108
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think part of the problem is that writeBytes() is leaving WE set to LOW (WRITING!).  Keep WE set to HIGH except in writePulse() or you risk writing to  other parts of your memory.

The 10 millisecond delay in writePulse() is probably WAY overkill.  That's like 160,000 instruction cycles for a memory write!
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've removed all the caps and added ones between every VCC and GND pin of the IC's.

I've made sure WE is set to HIGH except for during writepulse (HIGH, LOW, HIGH).

I've removed the 10ms delay.

Now it gives:
0 0 0 0
0 0 0 0
0 0 0 0
...

Anything else it could be?
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 180
Posts: 8108
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Another mistake:

Code:
void setByte(unsigned char b){

for(int i=0 ; i < 8 ; i++){
if( bytePins[i] & (0x1 << i) ) {   /////// That should be 'b' and not 'bytePins[i]'
digitalWrite(bytePins[7-i], HIGH);
}else{
digitalWrite(bytePins[7-i], LOW);
}
}
}


Because digitalRead() returns 0 or 1 and digitalWrite() takes 0 for LOW and anything else for HIGH and 0==false and anything else == true you can simplify the code somewhat:

Code:
void setByte(unsigned char b)
        {
for(int i=0 ; i < 8 ; i++)
digitalWrite(bytePins[7-i], b && (1<<i) );
}

unsigned char getByte()
        {
unsigned char b=0;

for( int i=0 ; i < 8 ; i++ )
b |= digitalRead(bytePins[i] << i;

return b;
}
[code]
[/code]
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Code:
if( bytePins[i] & (0x1 << i) ) {   /////// That should be 'b' and not 'bytePins[i]'

Oh wow, totally missed that.

Quote
Because digitalRead() returns 0 or 1 and digitalWrite() takes 0 for LOW and anything else for HIGH and 0==false and anything else == true you can simplify the code somewhat

Nice, changed it out.

What I get now is:
1 1 1 1
1 1 1 1
1 1 1 1
...

When I put the voltmeter on the 5v bus (at the top) I'm only reading around 3.73v when it's operating. When the Arduino powers on it's at 4.8v but quickly falls to 3.73v when the code starts to execute.

Isn't this way too little to properly operate the IC's?

Am I drawing too much power from the Arduino? It's powered by usb.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I forgot I had taken out the caps for tests.

With caps it still only shows around 4.36v while operating.
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 180
Posts: 8108
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think it's time to post your code again.  I've lost track of what changes you've made.

Also, looks like I missed a ')':

Code:
unsigned char getByte()
        {
unsigned char b=0;

for( int i=0 ; i < 8 ; i++ )
b |= digitalRead(bytePins[i]) << i;
//////////////////////////////////   ^--  This one was missing

return b;
}
[code]
[/code]
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Global Moderator
Boston area, metrowest
Online Online
Brattain Member
*****
Karma: 446
Posts: 23868
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Post the schematic again too.
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Global Moderator
Boston area, metrowest
Online Online
Brattain Member
*****
Karma: 446
Posts: 23868
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If you had 4 of these to make a 16 counter, it could be preloaded from your shift register, and then just clocked once for the next address to quickly access sequential addresses with having to shift out the address every time.

http://focus.ti.com/lit/ds/sdls198/sdls198.pdf

Am looking for more modern version, or a comparable 8-bit preloadable counter.
This perhaps, use one shift register to load both, one at a time.
http://focus.ti.com/lit/ds/symlink/sn54as867.pdf
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Looks good. I'll see if I can get that for the finished prototype for the thing it's going to be a part of (a gameboy classic rom loader/interface).

Here's the updated code:

Code:
//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;
int bytePins[8] = {2,3,4,5,6,7,9,10};
int CE = A2;
int OE = A1;
int WE = A0;

#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))

/* mode: INPUT or OUTPUT
OUTPUT: for writing out to memory
INPUT: for reading from memory
*/
void setBytePins(int mode){
for(int i=0 ; i < 8 ; i++){
pinMode(bytePins[i], mode);
}
}

void readBytes(unsigned char * buffer, unsigned short addr, int len){
unsigned char b;
setBytePins(INPUT);
digitalWrite(CE, LOW);
digitalWrite(OE, LOW);
for( int i=0 ; i < len ; i++){
b = readByte((int)addr+i);
buffer[i] = b;
}
}

unsigned char readByte(unsigned short addr){
setAddr(addr);
return getByte();
}

unsigned char getByte(){
unsigned char b=0;

for( int i=0 ; i < 8 ; i++ ){
b |= digitalRead(bytePins[i] << i);
}

return b;
}

void writeBytes(unsigned char * b, unsigned short addr, int len){
setBytePins(OUTPUT);
digitalWrite(CE, LOW);
for( int i=0 ; i < len ; i++){
writeByte(b[i],(int)addr+i);
}
}

void writeByte(unsigned char b, unsigned short addr){
setAddr(addr);
setByte(b);
writePulse();
}

void setAddr(unsigned short addr){
doubleShiftOut(addr);
}

void setByte(unsigned char b){
for(int i=0 ; i < 8 ; i++)
digitalWrite(bytePins[7-i], b && (1<<i) );
}

void writePulse(){
digitalWrite(WE, LOW);
digitalWrite(WE, HIGH);
}

void setup() {
  //set pins to output so you can control the shift register
  Serial.begin(9600);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(CE, OUTPUT);
  pinMode(OE, OUTPUT);
  pinMode(WE, OUTPUT);
  setBytePins(OUTPUT);
 
  digitalWrite(WE, HIGH);
}

void loop() {

unsigned char in_byte[4] = { 0xf1, 0x40, 0x41, 0xf0 };
unsigned char out_byte[4] = { 1,2,3,4 };

writeBytes(in_byte, 0x0, 4);
readBytes(out_byte, 0x0, 4);

Serial.print(out_byte[0], BIN);
Serial.print(" ");
Serial.print(out_byte[1], BIN);
Serial.print(" ");
Serial.print(out_byte[2], BIN);
Serial.print(" ");
Serial.println(out_byte[3], BIN);

delay(500);
}

void doubleShiftOut(unsigned short b){
unsigned char b1 = (b & 0xff00) >> 8;
unsigned char b2 = b & 0xff;
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, b1);
shiftOut(dataPin, clockPin, MSBFIRST, b2);
digitalWrite(latchPin, HIGH);
}

Attached is the updated schematic.


* ram-schematic-v2.png (19.28 KB, 1174x964 - viewed 12 times.)
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 180
Posts: 8108
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If OE was left LOW by something when writeBytes() is running then the memory chip output drivers will be fighting with the Arduino output drivers.  This could cause undue power consumption.   You should probably minimize the amount of time that CE and/or OE are LOW:

Code:
void setup() {
  //set pins to output so you can control the shift register
  Serial.begin(9600);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);

  pinMode(CE, OUTPUT);    ///  Might want to put a pull-up resistor on this pin to make sure chip stays disabled during reset,
  digitalWrite(CE, HIGH);   /// Add this

  pinMode(OE, OUTPUT);
  digitalWrite(OE, HIGH);  /// Add this

  pinMode(WE, OUTPUT);
  digitalWrite(WE, HIGH);  /// Add this

  setBytePins(OUTPUT);   // Don't really need this  readBytes() and writeBytes() both set them properly  
}


void readBytes(unsigned char * buffer, unsigned short addr, int len){
unsigned char b;
setBytePins(INPUT);
digitalWrite(CE, LOW);
digitalWrite(OE, LOW);
for( int i=0 ; i < len ; i++){
b = readByte((int)addr+i);
buffer[i] = b;
}
digitalWrite(OE, HIGH);    // Add this
digitalWrite(CE, LOW);     // Add this
}


void writeBytes(unsigned char * b, unsigned short addr, int len){
setBytePins(OUTPUT);
digitalWrite(CE, LOW);
for( int i=0 ; i < len ; i++){
writeByte(b[i],(int)addr+i);
}
digitalWrite(CE, HIGH);    /// Add this
}

Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 241
Posts: 24480
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
digitalWrite(bytePins[7-i], b && (1<<i) )

I think just one ampersand.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Global Moderator
Boston area, metrowest
Online Online
Brattain Member
*****
Karma: 446
Posts: 23868
Author of "Arduino for Teens". Available for Design & Build services. Now with Unlimited Eagle board sizes!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

On the top '595, is RCK really connected to Gnd? That's not going to work too well.

Why is writePulse seperated from writeByte?  Where else would you use it?
Logged

Designing & building electrical circuits for over 25 years. Check out the ATMega1284P based Bobuino and other '328P & '1284P creations & offerings at  www.crossroadsfencing.com/BobuinoRev17.
Arduino for Teens available at Amazon.com.

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
On the top '595, is RCK really connected to Gnd? That's not going to work too well.
I think it was connected through a cap before. I've removed the connection. Updated schematic is attached.

I've removed the extra ampersand.

I've added Johns suggestions to the code:

Code:
//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 12;
////Pin connected to DS of 74HC595
int dataPin = 11;
int bytePins[8] = {2,3,4,5,6,7,9,10};
int CE = A2;
int OE = A1;
int WE = A0;

#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))

/* mode: INPUT or OUTPUT
OUTPUT: for writing out to memory
INPUT: for reading from memory
*/
void setBytePins(int mode){
for(int i=0 ; i < 8 ; i++){
pinMode(bytePins[i], mode);
}
}

void readBytes(unsigned char * buffer, unsigned short addr, int len){
unsigned char b;
setBytePins(INPUT);
digitalWrite(CE, LOW);
digitalWrite(OE, LOW);
for( int i=0 ; i < len ; i++){
b = readByte((int)addr+i);
buffer[i] = b;
}
digitalWrite(OE, HIGH);    // Add this
digitalWrite(CE, LOW);     // Add this
}

unsigned char readByte(unsigned short addr){
setAddr(addr);
return getByte();
}

unsigned char getByte(){
unsigned char b=0;

for( int i=0 ; i < 8 ; i++ ){
b |= digitalRead(bytePins[i] << i);
}

return b;
}

void writeBytes(unsigned char * b, unsigned short addr, int len){
setBytePins(OUTPUT);
digitalWrite(CE, LOW);
for( int i=0 ; i < len ; i++){
writeByte(b[i],(int)addr+i);
}
digitalWrite(CE, HIGH);    /// Add this
}

void writeByte(unsigned char b, unsigned short addr){
setAddr(addr);
setByte(b);
digitalWrite(WE, LOW);
digitalWrite(WE, HIGH);
}

void setAddr(unsigned short addr){
doubleShiftOut(addr);
}

void setByte(unsigned char b){
for(int i=0 ; i < 8 ; i++)
digitalWrite(bytePins[7-i], b & (1<<i) );
}

void setup() {
 //set pins to output so you can control the shift register
 Serial.begin(9600);
 pinMode(latchPin, OUTPUT);
 pinMode(clockPin, OUTPUT);
 pinMode(dataPin, OUTPUT);
 
 pinMode(CE, OUTPUT);
 digitalWrite(CE, HIGH);   /// Add this
 
 pinMode(OE, OUTPUT);
 digitalWrite(OE, HIGH);  /// Add this
 
 pinMode(WE, OUTPUT);
 digitalWrite(WE, HIGH);
 
 //setBytePins(OUTPUT);
}

void loop() {

unsigned char in_byte[4] = { 0xf1, 0x40, 0x41, 0xf0 };
unsigned char out_byte[4] = { 1,2,3,4 };

writeBytes(in_byte, 0x0, 4);
readBytes(out_byte, 0x0, 4);

Serial.print(out_byte[0], BIN);
Serial.print(" ");
Serial.print(out_byte[1], BIN);
Serial.print(" ");
Serial.print(out_byte[2], BIN);
Serial.print(" ");
Serial.println(out_byte[3], BIN);

delay(500);
}

void doubleShiftOut(unsigned short b){
unsigned char b1 = (b & 0xff00) >> 8;
unsigned char b2 = b & 0xff;
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, MSBFIRST, b1);
shiftOut(dataPin, clockPin, MSBFIRST, b2);
digitalWrite(latchPin, HIGH);
}

Still outputs 1 1 1 1 though smiley-sad


* ram-schematic-v3.png (19.26 KB, 1174x964 - viewed 11 times.)
Logged

Pages: [1] 2   Go Up
Jump to: