SPI Driver - PIC18F25K22 - Page 1
Forum section: electronics / general

author: aboodi
author_rank: Contributor
timestamp: May 26, 2014, 12:00:53 pm
content: Hello everyone,I am trying to build a header file to control SPI, but I started with a simple function within the main c file just to see if everything is good to start building the library, but unfortunately, I have been trying to get it working for 3 days (3 hours a day).I also tried this code another chip, but the problem remains, so the problem is definitely a software problem. ><Hopefully someone can spot the problem and help me.MCU: PIC18F25K22, datasheet:http://ww1.microchip.com/downloads/en/DeviceDoc/41412F.pdfCode:void main(void) {init_PIC();writeSPI(0b11001100);while(1);void writeSPI(unsigned char x){SSP1BUF = x; //while(!SSP1STATbits.BF);}and this is from picInititialization.cCode:#include <xc.h>#include "picInitializing.h"#define _XTAL_FREQ 16000000void init_PIC(){OSCCONbits.IRCF = 0x7; // 0x7: 16MHz, 0x5: 4MHzINTCONbits.GIE = 0; // global interrupts desabledPMD0 = 0xFF; // UART2 , UART1 & timers 1- 6 modules are disabledPMD1 = 0b10111111; // MSSP2, CCP5-1 modules are disabled, except MSSP1PMD2 = 0xFF; // CTMU, comparator C2, comparator C1, ADC modules are disabledRCONbits.IPEN = 0;RCONbits.SBOREN = 0;ANSELA = 0x00; // digital input, not analogANSELB = 0x00;ANSELC = 0x00;WPUB = 0; // weak pull ups are disabledIOCB = 0; // IOC is disabledSLRCON = 0x0F; // slew rate control, disabled for all portsT0CONbits.TMR0ON = 0; // timer0 module is disabledADCON0bits.ADON = 0; // ADC is disabledSRCON0bits.SRLEN = 0; // p. 340 // RS Latch is disabledVREFCON0bits.FVREN = 0; // (p.344) fixed voltage reference disabledVREFCON1bits.DACEN = 0; // (p.347) DAC disabledHLVDCONbits.HLVDEN = 0; // (p.349) high low voltage detect disabledTRISA = 0b11110000; // 0xF0TRISB = 0b11110011; // 0xF3TRISC = 0b11010100; //SSP1CON1 = 0x20;// no collision, no OverFLow, ssp1 enabled// clock polarity is low in idle state,// SSP mode is MASTER (clock = Fosc/4)SSP1STAT = 0x40;// spi sampling: middle, spi clock edge: idle>active (0x40)// least 6 bits are read onlySSP1ADD = 0x09; // baud generator ..return;}and from picInitialization.hCode:#include <xc.h>// #pragma config statements should precede project file includes.// Use project enums instead of #define for ON and OFF.// PIC18F25K22 Configuration Bit Settings// CONFIG1H#pragma config FOSC = INTIO67 // Oscillator Selection bits (Internal oscillator block)#pragma config PLLCFG = OFF // 4X PLL Enable (Oscillator used directly)#pragma config PRICLKEN = OFF // Primary clock enable bit (Primary clock can be disabled by software)#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled)#pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled)// CONFIG2L#pragma config PWRTEN = OFF // Power-up Timer Enable bit (Power up timer disabled)#pragma config BOREN = OFF // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)#pragma config BORV = 190 // Brown Out Reset Voltage bits (VBOR set to 1.90 V nominal)// CONFIG2H#pragma config WDTEN = OFF // Watchdog Timer Enable bits (Watch dog timer is always disabled. SWDTEN has no effect.)#pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768)// CONFIG3H#pragma config CCP2MX = PORTC1 // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)#pragma config PBADEN = OFF // PORTB A/D Enable bit (PORTB<5:0> pins are configured as digital I/O on Reset)#pragma config CCP3MX = PORTB5 // P3A/CCP3 Mux bit (P3A/CCP3 input/output is multiplexed with RB5)#pragma config HFOFST = OFF // HFINTOSC Fast Start-up (HFINTOSC output and ready status are delayed by the oscillator stable status)#pragma config T3CMX = PORTC0 // Timer3 Clock input mux bit (T3CKI is on RC0)#pragma config P2BMX = PORTB5 // ECCP2 B output mux bit (P2B is on RB5)#pragma config MCLRE = EXTMCLR // MCLR Pin Enable bit (MCLR pin enabled, RE3 input pin disabled)// CONFIG4L#pragma config STVREN = OFF // Stack Full/Underflow Reset Enable bit (Stack full/underflow will not cause Reset)#pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled)#pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))// CONFIG5L#pragma config CP0 = OFF // Code Protection Block 0 (Block 0 (000800-001FFFh) not code-protected)#pragma config CP1 = OFF // Code Protection Block 1 (Block 1 (002000-003FFFh) not code-protected)#pragma config CP2 = OFF // Code Protection Block 2 (Block 2 (004000-005FFFh) not code-protected)#pragma config CP3 = OFF // Code Protection Block 3 (Block 3 (006000-007FFFh) not code-protected)// CONFIG5H#pragma config CPB = OFF // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected)#pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected)// CONFIG6L#pragma config WRT0 = OFF // Write Protection Block 0 (Block 0 (000800-001FFFh) not write-protected)#pragma config WRT1 = OFF // Write Protection Block 1 (Block 1 (002000-003FFFh) not write-protected)#pragma config WRT2 = OFF // Write Protection Block 2 (Block 2 (004000-005FFFh) not write-protected)#pragma config WRT3 = OFF // Write Protection Block 3 (Block 3 (006000-007FFFh) not write-protected)// CONFIG6H#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected)#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot Block (000000-0007FFh) not write-protected)#pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected)// CONFIG7L#pragma config EBTR0 = OFF // Table Read Protection Block 0 (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks)#pragma config EBTR1 = OFF // Table Read Protection Block 1 (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)#pragma config EBTR2 = OFF // Table Read Protection Block 2 (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks)#pragma config EBTR3 = OFF // Table Read Protection Block 3 (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks)// CONFIG7H#pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot Block (000000-0007FFh) not protected from table reads executed in other blocks)#define _XTAL_FREQ 16000000// TRANSCEIVER SIGNALS // pinouts of cc2500 module#define MOSI LATCbits.LATC5 // pin 2#define SCLK LATCbits.LATC3 // pin 3#define MISO PORTCbits.RC4 // pin 4#define GD02_DCLK PORTBbits.RB1 // pin 5#define GDO0_DIO PORTBbits.RB0 // pin 7#define CC2500_module_CSN LATBbits.LATB3 // pin 8

author: dannyf
author_rank: Super Contributor
timestamp: May 26, 2014, 01:33:40 pm
content: Quote"the problem" is?

author: aboodi
author_rank: Contributor
timestamp: May 26, 2014, 02:41:50 pm
content: Aah my bad, sorry?The problem is that i cannot get any output from both of the clock and output data pins.Thanks.

author: dannyf
author_rank: Super Contributor
timestamp: May 26, 2014, 02:57:53 pm
content: QuoteAs in what? The output is floating / high / low?As written, the code will just send the data once. So if you measured the lines a little bit late, you would have missed.The code, for debugging purposes, makes no sense.

author: mariush
author_rank: Super Contributor
timestamp: May 26, 2014, 03:07:53 pm
content: Add a loop, put in the loop something for i = 32 to 126 , print character with ascii code i , wait 250ms or so. ascii table:http://commons.wikimedia.org/wiki/File:ASCII-Table-wide.svgSet your scope to trigger properly and you should see those bits coming up every 250ms or so if everything's right..

author: aboodi
author_rank: Contributor
timestamp: May 26, 2014, 03:39:27 pm
content: Im probing both signals, but i cannot catch any change. Both signals go low and that is all.From what I understood is that once I write to the SSP1BUF, data are copied to the shift register to be transferred with no need for the user to do anything.I will try to use a loop as mariush suggested.Abdullah

author: David_AVD
author_rank: Super Contributor
timestamp: May 26, 2014, 09:07:46 pm
content: Also remember that after each SPI write you need to do a dummy read. If you don't the next write will not work.

author: dannyf
author_rank: Super Contributor
timestamp: May 26, 2014, 09:59:22 pm
content: The code simulated just fine.I think the issue is that it is only run once so s/he like missed capturing it right after power on.Code:SSP1BUF = x; //while(!SSP1STATbits.BF);This is the most efficient approach in terms of code / coding, but least efficient in terms of time: It waits until the transmission is over, which negates the purpose of having the buffer.A more efficient approach is to use an interrupt; or to test the buffer full flag, load the buffer and exit. So the mcu can do other stuff when the spi module is shifting out the data. Very important if the spi transmission speed is low.Unfortunately the way the spi module is set up, that kind of approach is not as straight forward is it sounds, for this (family) of chips.The newer chips, like PIC24F, are much nicer in this regard: you can do seamless transmission there, via either interrupt or polling.

author: aboodi
author_rank: Contributor
timestamp: May 27, 2014, 04:00:29 am
content: David_AVD: thanks for the reminder, I will try it as soon as I get back home.dannyf: ( It's a "he").that's for the simulation. I tried to add a 1 sec delay, but I will try it again with more than a sec.An idea for the time efficiency, is to do something like:Code:void main(){...SPIwrite(x); // without checking the BF bit.... // continue doing other stuffif (!SSP1CON1bit.BF) { // check the BF bit}(a workaround that I have never tried, just had it as a thought)Thanks for the help guys, will get back with results.Abdullah

author: aboodi
author_rank: Contributor
timestamp: May 28, 2014, 03:38:38 am
content: still with the same issue ( that I can't see anything on the output), however, I noticed that the output data pin of the SPI module is trying to take the output HIGH, but it cannot, one it get's it high, something cancels that and it becomes LOW again. This happens every 4 secs. Strange!I tried to play with the settings of the module but with no luck, the problem remains.( also I have tried another chip on another circuit board but with no luck).what do you think guys, I'm out of idea? >.<

author: David_AVD
author_rank: Super Contributor
timestamp: May 28, 2014, 03:56:14 am
content: Is the watchdog timer disabled?

author: dannyf
author_rank: Super Contributor
timestamp: May 28, 2014, 10:44:16 am
content: QuoteThat's hard to understand - maybe it is a hardware / pcb / connection issue - in that case, no one can help you unfortunately.QuoteI would flip a pin in the main loop and see if you could see action on that pin.Also, post a complete but minimalist piece of code that exhibits the problem.

author: aboodi
author_rank: Contributor
timestamp: May 28, 2014, 05:09:39 pm
content: "The code tries to take the SPI output HIGH, but it cannot, once it gets it high, something interrupts and it takes it LOW again. This happens every 4 secs."***Yes the WDT is disabled.***I do have an LED indicator, but i deleted it from the code just to save your time ^_^

author: Vasi
author_rank: Regular Contributor
timestamp: June 01, 2014, 04:15:44 pm
content: @aboodi, takeFirewingfor a test. You will be pleasantly surprised (free and with good performance). It supports PIC18F25K22 out of the box and also have aboardfor it.