Jump to content

16F876

EstablishedMember
  • Content Count

    10
  • Joined

  • Last visited

Community Reputation

0 Neutral

About 16F876

  • Rank
    Newbrie

Contact Methods

  • Website URL
    http://
  • ICQ
    0
  1. From the PIC16F87X datasheet: Flag bit TXIF is set when enable bit TXEN is set. TXIF is cleared by loading TXREG.
  2. Finally got this thing to work. Problem is threefold. 1) The AD7706 needs a reset in the beginning. RB2 is tied to the reset and kept low for a while(reset) and then brought high to activate the chip again. 2) Polling the DRDY bit I could not get to work. So finally I polled the DRDY pin on the AD7706 and that worked. This I thought would work, but it did not: void DRDYX(void) //Data from ADC Ready? { delay_ms(1); SpiSend(0x08); //08h, Write to Comm register to read(poll) DRDY(Bit7)in comm register SpiSend(0x0); while(sspbuf&0x80) //Constantly poll com reg to see when write done(bit 7=0) {SpiSend(0x08); //08h, Next operation a read from COM register SpiSend(0x0); } } This did work by polling the actual pin and not reading the registry. void DRDY(void) //Data from ADC Ready? { delay_ms(1); while (portb&0x02) //portb,1 as input, DRDY goes low when ready ; } 3) It seems like the channel that is to be enquired needs to be calibrated before every enquiry. void serial (void) //RS232's 'send' of a character- used by outserial() { while( pir1&0x10==0 ) //Test bit 4 { nop();} txreg=send; break; } void outserial (void) //RS232 Serial out { unsigned char zz; for ( zz=0; zz<7;zz++ ) {send=out[zz]; serial(); } } void CheckBF (void) //Check if data was sent and answer received(Buffer Full) {while(sspstat&0x01==0) //BF bit(0) is set once data was sent and new data received ; } void SpiSend (unsigned char SendA) //Send SPI command and get answer-8 bit { sspbuf=SendA; //Send command CheckBF(); //Check buffer full } void DRDY(void) //Data from ADC Ready? { delay_ms(1); while (portb&0x02) //portb,1 as input, DRDY goes low when ready ; } void SetupAD77061(void) {SpiSend(00100000b); //(20h)(32 dec) Write to Clock Register, Chan0 SpiSend(00000100b); //(04h)(4 dec)-0,0,0,0,CLK=1(bit2), rest zero,50HZ filter SpiSend(00010000b); //(10h)(32 dec)Write operation to setup register,Channel 1 SpiSend(01000100b); //(46h)(70 dec)(0,1)Self Calibration, (0,0,0)gain=1, (1)Unipolar, UNbuffered DRDY(); //Test to see when calibration complete } void SetupAD77062(void) {SpiSend(00100001b); //(21h)(33 dec) Write to Clock Register, Chan1 SpiSend(00000100b); //(04h)(4 dec)-0,0,0,0,CLK=1(bit2), rest zero,50HZ filter SpiSend(00010001b); //(11h)(33 dec)Write operation to setup register,Channel 2 SpiSend(01000100b); //(46h)(70 dec) (0,1)Self Calibration, (0,0,0)gain=1, (1)Unipolar, UNbuffered DRDY(); //Test to see when calibration complete } void SetupAD77063(void) {SpiSend(00100011b); //(23h)(35 dec) Write to Clock Register SpiSend(00000100b); //(04h)(4 dec)-0,0,0,0,CLK=1(bit2), rest zero,50HZ filter SpiSend(00010011b); //(13h)(35 dec)Write operation to setup register,Channel 3 SpiSend(01000100b); //(46h)(70 dec) (0,1)Self Calibration, (0,0,0)gain=1, (1)Unipolar, UNbuffered DRDY(); //Test to see when calibration complete } void ADC (void) //Send SPI command and get answer-8 bit { SpiSend(0x0); out[3]=sspbuf; SpiSend(0x0); out[4]=sspbuf; } void Whatisthevalue (void) // { SetupAD77061(); SpiSend(0x38); ADC(); outserial(); SetupAD77062(); SpiSend(0x39); ADC(); outserial(); SetupAD77063(); SpiSend(0x3B); ADC(); outserial(); } void main (void) { setup (); Whatisthevalue(); sleep(); }
  3. I am getting there slowly. Because the SPI is hardware driven I was under the impression that the chip would know when to receive answers or that the slave chip would tell the main chip to receive data. Well it does not work that way. After the chip is asked a question of which you want an answer, the data has to be "clocked out" of the chip being interrogated. This can be done by sending a dummy data to the chip. By sending a zero(0) by hardware SPI, clock cycles will be provided in exactly the same way to the slave chip, as it would if you where to "clock out"(bit bang) an answer in software. Previously I did not notice that the SPI clock was working because the burst of the clock is so quick. Not until I put the SPI in a loop did I see on the scope that the clock signal is operating. The code is still not working, but I am getting closer I think. If anybody can give me a clue as to what I am doing wrong it will be great. Thank you. Louis void SerialReset(void) //This part is supposed to reset the AD7706- provides 32 clock cycles {set_bit(portc,3); //Clock High set_bit(portc,5); //SDO high unsigned char j; for ( j=0; j<64;j++ ) { clear_bit(portc,3); set_bit(portc,3); } clear_bit(portc,5); } {set_bit(portc,3); //Clock High set_bit(portc,5); //SDO high unsigned char j; for ( j=0; j<64;j++ ) { clear_bit(portc,3); set_bit(portc,3); } clear_bit(portc,5); } void CheckBF (void) //Check if data was sent and answer received(Buffer Full) {while(sspstat&0x01==0) //BF bit(0) is set once data was sent and new data received ; } void SpiA (unsigned char SAnsw) //Send SPI command and get answer-8 bit { dummy=sspbuf; //Clear trash WCOL=0; //Clear Write collision sspbuf=SAnsw; CheckBF(); //Check buffer full sspbuf=0; //Dummy data clocks out answer CheckBF(); } void DRDY(void) //Data from ADC Ready? { SpiA(0x08); //08h, Write to Comm register to read(poll) DRDY(Bit7)in comm register while(sspbuf&0x80) //Constantly poll com reg to see when write done(bit 7=0) {SpiA(0x08); //08h, Next operation a read from COM register } } void SpiCommand (unsigned char SAnsw) //Send SPI command and expect no answer { dummy=sspbuf; //Clear trash WCOL=0; //Clear Write collision sspbuf=SAnsw; CheckBF(); } void SpiChan (unsigned char SAnsw) //Send SPI command for channel and clock out 16bit answer { dummy=sspbuf; //Clear trash WCOL=0; //Clear Write collision sspbuf=SAnsw; //Write channel number to Data register CheckBF(); //Check buffer full after channel selected? DRDY(); // Is data ready? sspbuf=0; //Dummy data clocks out first 8 bits CheckBF(); out[3]=sspbuf; //MSB sspbuf=0; //Provides clock cycles to clock out last 8 bits CheckBF(); //Check buffer full out[4]=sspbuf; //LSB } void SetupAD7706(void) {SpiCommand(00100000b); //(20h) Write to Clock Register SpiCommand(00000100b); //(04h)-0,0,0,0,CLK=1(bit2), rest zero,50HZ filter SpiCommand(00010000b); //(10h)Write operation to setup register,Channel 1 SpiCommand(01000110b); //(44h) (0,1)Self Calibration, (0,0,0)gain=1, (1)Unipolar, buffered DRDY(); //Test to see when calibration complete } void SPIADC (void) //Read Data from channel x { SpiChan(0x38); //00111000b 38h, Bit3=1(read), data register outserial(); //Data sent to PC via RS232 } void GoMeasure (void) //Normal display { while (1) {SPIADC(); } void main (void) { setup (); //Setup PIC SerialReset(); //Routine to reset chip SetupAD7706(); GoMeasure(); sleep(); }
  4. Hi I disabled the RS232 before the use of SPI with no success. At http://forum.microchip.com/tm.asp?m=48978&...32&anchor#48978 is says "The I2C/SPI interface, and the USART are totally seperate, and do not affect each other." So far I have not found any other reference to disabling the RS232 before SPI use, but then there is very little information on using both at the same time. What did you mean by ? The Slave Select(SS) method is not used because the slave chip is hardwired as being selected. Thank you for your help I appreciate it.
  5. Hi there I am having trouble getting ADC values from an external AD7706( very similar to AD7705) IC to a PIC16F876 via SPI. The PIC is running at 4MHZ and the AD7706 is running at 2.4578 MHZ. I want to use the hardware SPI function(no bit banging) of the PIC and no interupts. I am trying to communicate to the external IC via SPI and want to report back to the computer via RS232. At the moment all the readings I get is zero and with my picoscope scope there seems to be no SPI data coming from the 16F876. void setup (void) { /* Setup*/ trisa=101111b; //make all portA input except RA4 output trisb=0; //All output trisc=10010000b; // make just RC7 input for RS232, RC5(SDO)=0,RC4(SS)=1,RC3(SCK)=0 and RC4 for SDI clear_bit (option_reg,NOT_RBPU); // portb pullups enabled - normally set clear_bit (pie1,7); // Disables AD convert interupt adcon1=10000000b; //Justify right,FOSC/8(0),(00), Set all to analogue input /*SetBaud for RS232*/ clear_bit (intcon, GIE); //disables global interupt clear_bit (intcon, PEIE); // disables peripheral interupts clear_bit (intcon, INTE); // disables all external interupts clear_bit (intcon, RBIE); // disables all RB port interupts clear_bit (pie1,TXIE); // clears interupt bit portb=0; //Clear port B outputs portc=0; //clear portc spbrg=25; txsta=00000100b; //Sync=0(bit4), brgh=1(bit2) rcsta=10010000b; /*enables serial port, SPEN bit set-enables reception */ set_bit (txsta, TXEN); /* enables transmission */ temp=rcreg; //Clear receive register /* Setup SPI */ pie1=0; //Just to make sure all interupts are off intcon=0; //Just to make sure all interupts are off sspcon=00110000b; //SSPEN(5)=1,CKP(4) =1,Fosc/4(0001) sspstat=00000000b; //CKE=0 dummy=sspbuf; //Clear buffer } That was the setup part of the deal. Here follows the SPI nitty gritty. void CheckBF (void) //Check if data was sent and answer received(Buffer Full) { while ((sspstat&0x01)==0) //BF bit(0) is set once data was sent and new data received {;} } void SendSpiA (unsigned char SAnsw) //Send SPI command, keep answer { WCOL=0; //Clear Write collision sspbuf=SAnsw; //Put command in sspbuf and send CheckBF(); //Check buffer full } void DRDY(void) //AD7706 stuff -Data from ADC Ready? { SendSpiA(00001000b); //08h, Write to Comm register to read(poll) DRDY(Bit7)in comm register while(sspbuf&0x80) //Constantly poll communication register to see when write done(bit 7=0) {SendSpiA(00001000b); //08h, Next operation a read from COM register } } void SPIADC (void) //Read Data from channel one { DRDY(); // Data ready? SendSpiA(00111000b); //00111000b 38h, Bit3=1(read), data register out[3]=sspbuf; out[4]=sspbuf; } void SetupAD7706(void) //AD7706 setup stuff which does not seem to be sent {SendSpiA(00100000b); //(20h) Write to Clock Register SendSpiA(00000100b); //(04h)-0,0,0,0,CLK=1(bit2), rest zero,50HZ filter SendSpiA(00010000b); //(10h)Write operation to setup register,Channel 1 SendSpiA(01000100b); //(44h) (0,1)Self Calibration, (0,0,0)gain=1, (1)Unipolar Alive4(); //LED routine to confirm that we got this far } Void Testing(void) {//Code here that calls SPIADC and sends data via RS232 } void main (void) { setup (); SetupAD7706(); Testing(); } The RS232 part works fine, but the SPI does not seem to work. Any help and clues will be appreciated.
  6. Dear nic_steph Data can be read when a command was written to read data ie you send the command to read something, and right after it was sent the answer should be available. uchar SpiRead(uchar value){ uchar tmp; sspbuf = readcom; /*you put in here the command to read from certain register*/ while(bf == 0); /*wait for transmission completed and answer received*/ tmp = sspbuf; /*answer goes into tmp*/ } Depending on the device you might have to send quite a few commands before a read, but as soon as the final read command was sent and BF is set then the answer should be in sspbuf and can be read, I am struggling with something similar so I hope that at least this little of what think I know is right.
  7. Hi There is a very nice tutorial at www.epemag.wimborne.co.uk/pictutorial.pdf
  8. You could multiply by 44, then divide by 9 to get a value that's roughly 0-5000 mV. <{POST_SNAPBACK}> My solution is so complicated that I would have gone with Steve's solution, but here goes: I get the ADC value in int multi. I multiply the value by 4.882 ( comes from 5000/1024, therefor 1023(+1) will be 5000) as follows: void Voltage (void) { multi=multi+1; // add one temp=multi*4; temp0=(multi*8)/10; temp1=(multi*8)/100; temp2=(multi*2)/1000; multi=temp+temp0+temp1+temp2; } Then I do the BCD extraction: void bcdext (void) { thou=multi/1000; multi=multi%1000; hund =(multi/100); multi=multi%100; tens=(multi/10); ones=(multi%10); thou=thou+48; //the 48 gets added to get the LCD value hund=hund+48; tens=tens+48; ones=ones+48; } Then I do rounding of the value so a ADC value of 1023 will show 5000 while a value of zero will still show 0. void roundd (void) {if (ones>(4+48)) //ie ones +48(to get LCD value)>4 {tens=tens+1; /*if the LCD value for 9 increases by one it becomes the value for character ':' */ if (tens>(9+48)) {tens=(0+48); hund=hund+1; if (hund>(9+48)) {hund=(0+48); thou=thou+1;}}}} This gives an adc value of 1023 a value of 5000.
  9. The device is the PIC16F876. You advice worked thank you very very much. I was working on this problem for a long time so thank you very very much.
  10. This following program does not compile with Sourceboost C2C Plus 5.3. It gives the error : Error: General error in function definition on line 72 which is exacltly the same as the code on line 78 namely, clear_bit (portc,RS) ; I have tried, output_low_port_c (RS); and clear_bit (portc,5); with no success. In general the code may be wrong for what I am trying to do, but it is the syntax that seems to be the problem. I have tried using hex instead of my prefered binary in some statements, but with no success. Please help me get this going. /* Trying to get to grips with this */ #include <system.h> #define ebit 00010000b /*bit4*/ #define RS 00100000b /*bit5*/ #define rsmask 00110000b #define lcdstart_delay 1 /* 2500 */ #define stndwrite_delay 1 /* 100 */ #define clrlcd_delay 1 /*2000 */ unsigned int place, celsius, ones, tens, hund, thou, tenk, temp0, temp1; unsigned int temp2, temp3, temp4, progno, ahi, amd, alo, bhi, bmd, blo, a1hi; unsigned int a1lo, b1hi, b1lo, multi0, multi1, h0, h1, h2; unsigned int sign, rscom, aargb2, aargb1, aargb0, factor, divide2; unsigned int divide3, product, product1, product2, product3, product4, product5; unsigned int zoom0, zoom1, loopcount, bargb0, bargb1, multipland, multipland1; unsigned int multipland2, multi2, c1hi, c1lo, d1lhi, d1lo, cntr1, x, y; unsigned int Zero, answer, Ba, avg ; unsigned char temp, disp; const unsigned char lcd_init [5] = { /* Display off */ 0x08, /* Display clear */ 0x01, /* Entry mode set */ 0x06, /* Display on/underline off-Blink off */ 0x0C, /* Function set big display */ 0x2C }; const unsigned char message [5] = { 'H', 'E', 'L', 'L', 'O' } ; void E (void) { portc=portc^0x08; stndwrite_delay(); portc=portc^0xEF; } void IN (void) { temp=disp; /* move display to temporary */ asm swapf(temp); temp= temp&0x0f; portc=temp; portc=portc^11100000b ; E(); temp=disp; temp=temp&0x0F; portc =portc^0xE0; E(); } void lcdstart (void) { clear_bit (portc,ebit); /* Clear Ebit */ output_high_port_c (0x01); /* Function set--4 bits */ E(); /* call E */ stndwrite_delay(); unsigned char i ; for ( i=0 ; i<5 ;i++ ) { disp=lcd_init; IN(); stndwrite_delay(); } clear_bit (portc,RS) ; /* !!!!! Line 72 !!!!!! */ } void display (void) { clear_bit (portc,RS); /* !!!!! Line 78 !!!!!!!!*/ disp=0xC0; /* Display address 40 */ IN(); set_bit (portc,RS); unsigned char j ; for ( j=0 ; j<5 ;j++ ) { disp=message[j]; IN(); stndwrite_delay(); } output_low_port_c(RS); } void setup (void) { /* Setup*/ trisa=0x17 ; /* make all port a except TA4 input*/ trisb=0x1F ; clear_bit (option_reg,RBPU); /* portb pullups enabled - normally set */ clear_bit (pie1,PSPIE); /* Disables AD convert interupt */ trisc=0x80; /* make just RC7 input for RS232 */ /*SetBaud*/ clear_bit (intcon, gie); /*disables global interupt*/ clear_bit (intcon, t0ie); /* disables peripheral interupts */ clear_bit (intcon, inte) ; /* disables all external interupts*/ clear_bit (intcon, rbie); /* disables all RB port interupts */ portc=0; /*clear portc*/ spbrg=0x19 ; txsta=0x04 ; clear_bit (pie1,txie) ; /* clears interupt bit */ rcsta=0x90; /*enables serial port, SPEN bit set-enables reception */ set_bit (txsta, txen); /* enables transmission */ } void main (void) { setup () ; lcdstart (); display(); }
×
×
  • Create New...