En primer lugar, han pasado 2 años desde que toqué cualquier cosa excepto mbed o ardunio, así que hay una gran posibilidad de que haya hecho algo tonto para causar los problemas que estoy viendo.
Tengo un PIC16F886 en una placa de pruebas con una tapa de 1nF en Vdd y GND. Conectado al SPI hay un NRF24l01 + en una placa de conexiones, tengo un adaptador serie a USB en el EUSART y el PICkit2 conectado a los puertos ICSP. Estoy usando una versión modificada de la biblioteca nrf de la serie de tutoriales diyembedded.com.
El PIC se está ejecutando desde INTOSC a 4MHz y SPI es 4Mhz / 64 (62500, muy lento). La configuración se muestra en la siguiente imagen:
MiproblemaeslainterfazconelNRF:elbusSPIesmuytemperamentalysensiblealtacto.CuandomecomunicoconelNRF,siemprepuedoleersuregistrodeESTADOcomo0x0E,sinembargo,laCONFIGURACIÓNesmásamenudoquenosiempre0x00,aveces0xC5o0xC6ymuyraramente0x08(elresultadoesperosegúnlahojadedatos).SimetounasondadealcanceenelpuertoMOSIenlafoto(comosemuestraenlaimagendearriba),entoncesobtengo0x08demaneraconsistente,sinembargo,latrazaeshorrible(veracontinuación)yconfrecuenciatienepicosgrandes,amboscanalesconfiguradosa2V/sqybasedetiempo10uS.ElrastreoenelMISOesclaro,nítidoydeamplitudcompleta.
¿Alguien tiene algún pensamiento? ¿Es este chip demasiado sensible para ser usado en una tabla de pruebas de esta manera? ¿He arruinado algo básico en el PIC configurado para causar algunos problemas terribles para el SPI? Me encantaría crear mis propios PCB, pero por varias razones no es una opción ahora, por lo que me gustaría seguir con el tablero.
¡Gracias!
Código abajo para completar:
Main.c
// CONFIG1
#pragma config FOSC = INTRC_NOCLKOUT
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = OFF
#pragma config CP = OFF
#pragma config CPD = OFF
#pragma config BOREN = OFF
#pragma config IESO = OFF
#pragma config FCMEN = OFF
#pragma config LVP = OFF
// CONFIG2
#pragma config BOR4V = BOR21V
#pragma config WRT = OFF
//general defines
#define _XTAL_FREQ 4000000
//SPI Pin
#define nCS RC1 //csn pin for nrf
//main libraries
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include "../libraries/SPILibrary16F886.h"
#include "../libraries/nrf24l01.h"
/***
Serial port set to 9600 baudrate
***/
void enableSerialPort(){
//init SPBRGH/SPBRG/BRGH/BRG16
TXSTAbits.BRGH = 1; //0 for 8 MHz
BAUDCTLbits.BRG16 = 0;
SPBRGH = 0;
SPBRG = 25; //12 for 8MHz
//clear SYNC, set SPEN
TXSTAbits.SYNC = 0;
RCSTAbits.SPEN = 1;
//set TXEN
TXSTAbits.TXEN = 1;
}
/***
putch() required for printf() to work
currently works by polling the TRMT bit so blocks main thread
***/
void putch(char c){
while(TRMT == 0)continue;
TXREG = c;
}
int main(int argc, char** argv) {
unsigned char status = 0, config = 0;
//setup oscilator
OSCCONbits.IRCF = 0b110; //111 = 8Mhz
//main variables
enableSerialPort();
TRISCbits.TRISC0 = 0; //set CE for nrf to ouput
TRISCbits.TRISC1 = 0; // set CSN for nrf to output
TRISCbits.TRISC2 = 1; //set IRQ for nrf to input
nCS = 1; //set CSN bit
__delay_ms(100);
if(!initSPI(1, 64, 'm')){ //set up SPI
printf("SPI enabled\n");
}
SPIOn();
nrf24l01_initialize_debug(false, 1, false); //initialize the 24L01 to the debug configuration as TX, 1 data byte, and auto-ack disabled
//main loop start
for(;;){
status = nrf24l01_get_status();
config = nrf24l01_get_config();
printf("S = %x, C = %x\n", status, config);
__delay_ms(200);
}//main loop end
return(EXIT_SUCCESS);
}
SPILibrary16f886.c
#include <xc.h>
#include "SPILibrary16F886.h"
void SPIOn(){
SSPEN = 1;
SSPIE = 1;
}
int initSPI(int mode, int clockDivide, char masterSlave){
//set up SPI master or slave
if(masterSlave == 'm'){
if(clockDivide == 4)
SSPCON = SSPCON & 0b11110000; //master, clock/4
else if(clockDivide == 16){
SSPCON = SSPCON & 0b11110000; //master clock/16
SSPCON = SSPCON | 0b00000001;
}
else if(clockDivide == 64){
SSPCON = SSPCON & 0b11110000; //master clock/64
SSPCON = SSPCON | 0b00000010;
}
else{
return 1; //error code 1
}
}
if(masterSlave == 's'){
SSPCON = SSPCON & 0b11110000; //clear the lsb
SSPCON = SSPCON | 0b00000100; //nSS enabled in slave mode
SMP = 0;
}
//set up SPI mode
if(mode == 1){
CKE = 1;
CKP = 0;
}
else if(mode == 2){
CKE = 0;
CKP = 0;
}
else if(mode == 3){
CKE = 1;
CKP = 1;
}
else if(mode == 4){
CKE = 0;
CKP = 1;
}
else
return 2; //error code 2
//set up interrupts
SSPIE = 1;
TRISC3 = 0; // 0 = output for sck
return 0;
}
unsigned char writeSPIByte(unsigned char data)
{
SSPSTATbits.BF = 0;
unsigned char i;
SSPBUF = data;
while(SSPSTATbits.BF == 0){}
return SSPBUF;
}
unsigned char readSPIByte(void){
writeSPIByte(0x00);
return SSPBUF;
}
void writeSPIWord(unsigned short int setting)
{
writeSPIByte(setting >> 8);
writeSPIByte(setting);
}
void readSPIWord(){
readSPIByte();
readSPIByte();
}
void SPIOff(){
SSPEN = 0;
}
ACTUALIZACIÓN 1:
Entonces, basado en los comentarios de jippie (¡¿Agregué un menú desplegable a MISO ?! y un límite de 100 nF en Vdd-Gnd) Ahora puedo hacer que nrf lea continuamente 0xE para el registro ESTATUS y luego 0x8 para el registro CONFIG. He intentado leer otros registros, incluido EN_AA que tiene la dirección 0x01 (es decir, el siguiente después de CONFIG que tiene la dirección 0x00) y todavía devuelve 0x8. Mi teoría es que la línea MOSI es un desorden (traza amarilla en la imagen de arriba). el nrf está simplemente cambiando el ESTADO seguido de la CONFIGURACIÓN independientemente de la instrucción realmente enviada porque todo lo que está recibiendo son 16 pulsos de reloj y con 0s en el pin MOSI. También he manejado RC5 (el pin MOSI) como una salida normal y tiene un rango completo cuando no está conectado a nada, por lo que el pin funciona bien desde ese punto de vista.