Skip to content

Instantly share code, notes, and snippets.

@nlhans
Created February 14, 2015 22:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nlhans/44fbbc8abdcdad7939c1 to your computer and use it in GitHub Desktop.
Save nlhans/44fbbc8abdcdad7939c1 to your computer and use it in GitHub Desktop.
// PIC18F4620 Configuration Bit Settings
// 'C' source line config statements
#include <xc.h>
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
// CONFIG1H
#pragma config OSC = INTIO7 // Oscillator Selection bits (Internal oscillator block, CLKOUT function on RA6, port function on RA7)
#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 PWRT = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable bits (Brown-out Reset disabled in hardware and software)
#pragma config BORV = 3 // Brown Out Reset Voltage bits (Minimum setting)
// CONFIG2H
#pragma config WDT = OFF // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit))
#pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768)
// CONFIG3H
#pragma config CCP2MX = PORTC // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = OFF // PORTB A/D Enable bit (PORTB<4:0> pins are configured as digital I/O on Reset)
#pragma config LPT1OSC = OFF // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config MCLRE = ON // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)
// CONFIG4L
#pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = ON // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
#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 bit (Block 0 (000800-003FFFh) not code-protected)
#pragma config CP1 = OFF // Code Protection bit (Block 1 (004000-007FFFh) not code-protected)
#pragma config CP2 = OFF // Code Protection bit (Block 2 (008000-00BFFFh) not code-protected)
#pragma config CP3 = OFF // Code Protection bit (Block 3 (00C000-00FFFFh) 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 bit (Block 0 (000800-003FFFh) not write-protected)
#pragma config WRT1 = OFF // Write Protection bit (Block 1 (004000-007FFFh) not write-protected)
#pragma config WRT2 = OFF // Write Protection bit (Block 2 (008000-00BFFFh) not write-protected)
#pragma config WRT3 = OFF // Write Protection bit (Block 3 (00C000-00FFFFh) 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 bit (Block 0 (000800-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF // Table Read Protection bit (Block 1 (004000-007FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF // Table Read Protection bit (Block 2 (008000-00BFFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF // Table Read Protection bit (Block 3 (00C000-00FFFFh) 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)
#include <stdint.h>
void I2cInit()
{
TRISCbits.TRISC3 = 1;
TRISCbits.TRISC4 = 1;
TRISCbits.TRISC1 = 0;
TRISCbits.TRISC5 = 0;
TRISCbits.TRISC0 = 0;
TRISD = 0;
SSPSTAT = 0;
SSPSTATbits.SMP = 1;
SSPCON1 = 0;
SSPCON2 = 0;
SSPCON1bits.SSPM = 0b0110;
SSPCON1bits.SSPEN = 1;
SSPCON2bits.GCEN = 1;
SSPCON2bits.SEN = 1;
SSPADD = (0x10 << 1);
SSPIF = 0;
SSPIE = 1;
PEIE = 1;
GIE = 1;
}
uint8_t readMode = 0;
uint8_t cmd_operand;
uint8_t cmd_address;
uint8_t buffer[16];
// Handle custom I2C protocol
// Protocol uses:
// [Addr] [Operand] [Address Byte] [Data]
// A master will write like so:
// START [Addr | 0] [0x01] [addr] [multiple bytes] STOP
// A master will read like so:
// START [Addr | 0] [0x02] [addr] STOP (pause) START [Addr | 1] [multiple bytes] STOP
// (pause) was added to let the Rigol DS1000Z LA pick up the individual packets.
// So it basically now acts like a little I2C SRAM, or EEPROM if you would handle the operands as persistent.
void i2cHandler(uint8_t transactionByte, uint8_t r_nw)
{
volatile uint8_t dummy;
switch (transactionByte)
{
case 0:
// This was the address byte. Read and skip
dummy = SSPBUF;
break;
case 1:
// This is the operand
cmd_operand = SSPBUF;
break;
case 2:
// This is the ddress
cmd_address = SSPBUF;
// If we're reading, we need to think ahead. (0x02)
if (cmd_operand == 0x01)
{
break;
}
break;
// Data bytes:
default:
// Execute operand byte 1
if (cmd_operand == 0x02)
{
// Master is reading?
SSPBUF = buffer[cmd_address];
cmd_address++;
}
if (cmd_operand == 0x01)
{
buffer[cmd_address] = SSPBUF;
cmd_address++;
}
break;
}
}
uint8_t i2cM = 0, i2cB = 0;
void interrupt introutine (void) // interrupt function
{
//PORTCbits.RC5 = 1;
//volatile uint8_t dt;//
if (SSPIF)
{
SSPIF = 0;
//
if (!SSPSTATbits.D_A)
{
i2cM = SSPSTATbits.R_W;
if (i2cM == 0)
{
// Then reset the statemachine;
i2cB = 0;
}
else
{
i2cB++; // todo: can overflow
}
}
else
{
i2cB++;
}
i2cHandler(i2cB, i2cM);
SSPCON1bits.CKP = 1; // release the clock, so the master can continue
// master should drive clock with it's open-drain + pull-up as well; no push-pull.
/*
Old I2c code:
http://dangerousprototypes.com/2012/08/04/app-note-slave-i2c-communication-and-setup-on-pic-devices-with-mssp-modules/
if (SSPSTATbits.R_W) // master read
{
if (SSPSTATbits.D_A == 0)
{
// New Address
// First byte that is being read:
SSPBUF = readMode++;
SSPCON1bits.CKP = 1;
}
else
{
// New data
// Oncoming byte that are being read:
SSPBUF = readMode++;
SSPCON1bits.CKP = 1;
}
}
if (!SSPSTATbits.R_W) // master write
{
// We received a new address
if (SSPSTATbits.D_A == 0)
{
// reset data statemachine here.
dt = SSPBUF;
SSPCON1bits.CKP = 1;
readMode = 0;
}
else
{
// read dummy byte
dt = SSPBUF;
SSPCON1bits.CKP = 1;
}
}
PORTD = SSPSTAT;*/
}
//PORTCbits.RC5 = 0;
}
int main(void)
{
OSCCONbits.IRCF = 7;
I2cInit();
while(1)
PORTCbits.RC1 ^= 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment