PIC16F887 with RS232 and 32K external RAM

Thread Starter

egg-400

Joined Oct 14, 2009
4
Hi!
I'm just starting out wit PIC microcontrollers programming in C code. My objective was to interface the PIC with an external 32K paralell RAM (I used three ports for this) and send data through RS232 to a computer. My execution goes like this. First the PIC reads from ADC a 10bit value, puts it to two addresses in the RAM (RAM is 8-bit) and when we have read the specified amount of data the PIC reads the data from RAM and sends it to a computer via RS232. So, everything is working fine except for one detail, every 32:nd word gets corrupted when sent to the computer and I just can't find any reason for that? Can anyone with greater knowledge perhaphs find the problem? I've narrowed it down that the read_adc() function always reads a value < 1024 so there's no problem with that one. The corrupted word is also always in relation to the words just before and after. Example adc reads a value of 10, 1000times and every 32 word is now about 4000 but all the 10's are correct. The value 350 is read 1000 times and every 32 is now about 21300. Maybe my code could enlighten things.

#include <16F887.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP,NODEBUG
#device ADC=10
#use delay(clock=16000000)
#use rs232(baud=38400, xmit=PIN_A2, rcv=PIN_A1,INVERT,LONG_DATA)
#include <stdlib.h>

void send(int16 amount);
void read(int16 size);
int16 data=0,n=2,lowword=0,highword=0,sendword,i;
int j,k,l,m;
char* str[5];

void main() {

setup_adc(ADC_CLOCK_DIV_32);
setup_adc_ports(sAN0);
set_adc_channel(0);


while(1){

output_high(PIN_A3); //LED

if(input_state(PIN_A4)){
read(1000);
delay_ms(500);
send(1000);
}
}
}



void read(int16 size){

output_high(PIN_E0); //LED

output_low(PIN_E1); // write enable for RAM
output_low(PIN_E2); //

for(i = 0; i < size; i++){

j = i>>8;
k = i & 0xFF;
OUTPUT_B(k); //Address
OUTPUT_C(j);

if(n != 2){
m = data & 0xFF;
OUTPUT_D(m);
}
else{
data = read_adc();
l = data >> 8;
OUTPUT_D(l);
n=0;
}
n++;
}
output_low(PIN_E0);
}

void send(int16 amount){

output_high(PIN_A5); //LED
output_low(PIN_E2); // Read enable for RAM
output_high(PIN_E1); //

for(i = 0; i < amount; i++){

j = i>>8;
k = i & 0xFF;
OUTPUT_B(k); //address
OUTPUT_C(j);

if(n != 2){
lowword = INPUT_D();
sendword = lowword | highword;

//if(sendword < 1025){
itoa(sendword,10,str);
puts(str);
//}

}
else{
highword = INPUT_D();
highword = highword << 8;
n=0;
}
n++;

}
output_low(PIN_A5); //LED
}





A very easy but BAD solution would be to interpolate every 32:nd word from previous and next before sending it.
 

Thread Starter

egg-400

Joined Oct 14, 2009
4
Yep, I can believe that it is easier to cooperate with an serial memory =). But I just happened to have this memory type available, so I gave it a try =) I got a sampling speed of about 20Ksamples/s with my memory and the code above, not very fast but as you can see every 10-bit adc value occupies two words of RAM witch slows things down a lot. The only thing is that weird error every 32 word.
 

n9352527

Joined Oct 14, 2005
1,198
Check your physical address line, especially A6. The 32nd word corresponds to the 64th byte, which is selected by the address line A6.

Code a small test program, write around 100 test pattern bytes to the RAM and read them back again. Check the value against the original. Good values to try for are 0x55 and then 0xAA.
 

Thread Starter

egg-400

Joined Oct 14, 2009
4
Thanks for the link and advice, but I got some help with the issue and finally solved it. There was a logical error in the code, I had to set down the write enable while providing the address to the RAM because when using two ports for addressing, my program wrote a byte to the wrong address always while the first address port was set and the second address port was not set. That means that the unintended RAM writing happened between the lines: Output_B(k) and Output_C(j)
 
Top