SPI communication, how to set up clock correctly - c

We are trying to set up SPI communication between a pic32 and an ADS1298. The issue is that we cannot get the clock set up correctly.
What I have tried is the following
#include <xc.h>
#include "SDlib16.h"
#pragma config FNOSC = FRCPLL // Oscillator selection
#pragma config POSCMOD = HS // Primary oscillator mode
#pragma config FPLLIDIV = DIV_2 // PLL input divider (8 -> 4)
#pragma config FPLLMUL = MUL_20 // PLL multiplier ( 4x20 = 80)
#pragma config FPLLODIV = DIV_1 // PLL output divider
#pragma config FPBDIV = DIV_2 // Peripheral bus clock divider 80/ 2= 40 mhz
#pragma config FSOSCEN = OFF // Secondary oscillator enable
#pragma config IESO=OFF
#pragma config FCKSM=CSDCMD
#pragma config OSCIOFNC=OFF
#pragma config FWDTEN = OFF // Watchdog timer enable
#pragma config WDTPS = PS4096 // Watchdog timer post-scaler
#pragma config FSRSSEL = PRIORITY_7 // SRS interrupt priority
/*
*
*/
void configpins(void)
{
DDPCONbits.JTAGEN = 0;//Turns off the JTAG function of all pins
AD1PCFG=0xFFFF;//Turns off the analog function of all pins
TRISBbits.TRISB8=0; //Makes RB8 an output (Chip select)
TRISBbits.TRISB12=0;//Makes RB12 an output(Hold)
TRISBbits.TRISB10=0;//Makes RB10 an output(Write protect)
}
void initialSPI(void)
{
IEC0CLR=0x03800000;//turns off SPI interrupts
SPI4CONbits.ON=0;//turns off SPI4 module
SPI4BUF=0;//Sets SPI4 buffer to 0
SPI4CONbits.ENHBUF=0;//Sets ENHBUF to zero
SPI4CONbits.CKP=0;//Sets clock phase bit to 0
SPI4BRG=0;//Sets the SPI clock to be at 20MHz(Logic analyzer cant sample high enough for 20MHz )
SPI4STATbits.SPIROV=0;//Sets overflow bit to zero
SPI4CONbits.MSTEN=1;//Sets microcontroller to master mode
SPI4CONbits.DISSDO=0;//Sets the module to control the SDO pin
SPI4CONbits.CKE=1;//Sets the clock edge bit to 1
SPI4CONbits.SMP=0;//Sets SMP bit to 0
SPI4CONbits.MODE16=0;//Turns off 16bit mode
SPI4CONbits.MODE32=0;//Turns off 32bit mode
SPI4CONbits.ON=1;// Turns on SPI4 module
}
unsigned char Transfer(unsigned char data)
{
SPI4STATbits.SPIRBF=0; //Clears the receives buffer bit
SPI4BUF = data;//Puts data into the buffer
SPI4STATbits.SPITBE=0;//Turns off buffer enable
while (!SPI4STATbits.SPIRBF);//While the Receive buffer flag is empty
return SPI4BUF; // read a byte
}
unsigned char SPITransaction(unsigned char data)//Simple one byte in and one out
{
PORTBbits.RB8=0;//clears the chip select
unsigned char CharReturned=Transfer(data);// Calls the transfer function to send byte to buffer
PORTBbits.RB8=1;//Sets the chip select
return CharReturned;//Returns the byte received from buffer
}
void ReadDevice(void)//Gets the Device ID
{
PORTBbits.RB8=0;//Clears the chip select
Transfer(0xAB);//Bytes to get the device id
Transfer(0x00);
Transfer(0x00);
Transfer(0x00);
Transfer(0x00);
Transfer(0x00);
PORTBbits.RB8=1;//Sets the Device ID
}
int main(int argc, char** argv)
{
configpins();
initialSPI();
PORTBbits.RB10=1;//Sets the Write protect to high
PORTBbits.RB12=1;//Sets Hold to high
PORTBbits.RB0=0;
while(1)// Forever loop
{
//unsigned char Result=SPITransaction('W');//Sends W to the buffer and gets back a byte
//ReadDevice();//Gets the Device ID
PORTBbits.RB8=0;//Clears the chip select
Transfer(0x08);//Bytes to get the device id
PORTBbits.RB8=1;//Sets the Device ID
}
return (EXIT_SUCCESS);
}
I do not know what am i doing wrong, when I hook up the clock to a logic analyzer, it does not look like a clock, instead it looks like something completely random anyone knows what am I doing wrong?

I think you have missed to set the SCK (clock) as output.

Related

Source and Header file syntax in MPLAB X IDE v5.50

I am developing the code for my PIC32MK1024MCM project. I have already tested the code well and now I am only putting all the code modules into the final project (the code is not complete in this example yet, but the functionality is not the axis of interest here). For the first time in my life, I wanted to make it a little bit more professional and use separate source and header files for all the different module function declaration. However, I am clearly facing some kind of syntax problem, because I am getting errors in almost every line of the source file (I guess I have to include something in that source file, but I am not sure) Like I said, it is my very first time facing header and source files, so could you please help me, or at least hint me, what is it that I am missing so obviously? I want to thank you in advance.
main:
#include <xc.h>
#include <configuration_bits.c>
#include <toolchain_specifics.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include "stdio.h"
#include <sys/attribs.h>
#include <analog_to_digital_conversion.h>
void main(void) {
while (1){
}
return (EXIT_FAILURE);
}
configurations_bits
// DEVCFG3
#pragma config USERID = 0xFFFF // Enter Hexadecimal value (Enter Hexadecimal value)
#pragma config PWMLOCK = OFF // PWM IOxCON lock (PWM IOxCON register writes accesses are not locked or protected)
#pragma config FUSBIDIO2 = OFF // USB2 USBID Selection (USBID pin is controlled by the port function)
#pragma config FVBUSIO2 = OFF // USB2 VBUSON Selection bit (VBUSON pin is controlled by the port function)
#pragma config PGL1WAY = OFF // Permission Group Lock One Way Configuration bit (Allow multiple reconfigurations)
#pragma config PMDL1WAY = OFF // Peripheral Module Disable Configuration (Allow multiple reconfigurations)
#pragma config IOL1WAY = OFF // Peripheral Pin Select Configuration (Allow multiple reconfigurations)
#pragma config FUSBIDIO1 = OFF // USB1 USBID Selection (USBID pin is controlled by the port function)
#pragma config FVBUSIO1 = OFF // USB2 VBUSON Selection bit (VBUSON pin is controlled by the port function)
// DEVCFG2
#pragma config FPLLIDIV = DIV_1 // System PLL Input Divider (1x Divider)
#pragma config FPLLRNG = RANGE_BYPASS // System PLL Input Range (Bypass)
#pragma config FPLLICLK = PLL_POSC // System PLL Input Clock Selection (POSC is input to the System PLL)
#pragma config FPLLMULT = MUL_4 // System PLL Multiplier (PLL Multiply by 4)
#pragma config FPLLODIV = DIV_2 // System PLL Output Clock Divider (2x Divider)
#pragma config BORSEL = HIGH // Brown-out trip voltage (BOR trip voltage 2.1v (Non-OPAMP deviced operation))
#pragma config UPLLEN = OFF // USB PLL Enable (USB PLL Disabled)
// DEVCFG1
#pragma config FNOSC = POSC // Oscillator Selection Bits (Primary Osc (HS,EC))
#pragma config DMTINTV = WIN_0 // DMT Count Window Interval (Window/Interval value is zero)
#pragma config FSOSCEN = OFF // Secondary Oscillator Enable (Disable Secondary Oscillator)
#pragma config IESO = ON // Internal/External Switch Over (Enabled)
#pragma config POSCMOD = HS // Primary Oscillator Configuration (HS osc mode)
#pragma config OSCIOFNC = OFF // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FCKSM = CSDCMD // Clock Switching and Monitor Selection (Clock Switch Disabled, FSCM Disabled)
#pragma config WDTPS = PS1 // Watchdog Timer Postscaler (1:1)
#pragma config WDTSPGM = STOP // Watchdog Timer Stop During Flash Programming (WDT stops during Flash programming)
#pragma config WINDIS = NORMAL // Watchdog Timer Window Mode (Watchdog Timer is in non-Window mode)
#pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT Disabled)
#pragma config FWDTWINSZ = WINSZ_25 // Watchdog Timer Window Size (Window size is 25%)
#pragma config DMTCNT = DMT31 // Deadman Timer Count Selection (2^31 (2147483648))
#pragma config FDMTEN = OFF // Deadman Timer Enable (Deadman Timer is disabled)
// DEVCFG0
#pragma config DEBUG = OFF // Background Debugger Enable (Debugger is disabled)
#pragma config JTAGEN = OFF // JTAG Enable (JTAG Disabled)
#pragma config ICESEL = ICS_PGx1 // ICE/ICD Comm Channel Select (Communicate on PGEC1/PGED1)
#pragma config TRCEN = OFF // Trace Enable (Trace features in the CPU are disabled)
#pragma config BOOTISA = MIPS32 // Boot ISA Selection (Boot code and Exception code is MIPS32)
#pragma config FECCCON = ECC_DECC_DISABLE_ECCON_WRITABLE // Dynamic Flash ECC Configuration Bits (ECC and Dynamic ECC are disabled (ECCCON<1:0> bits are writable))
#pragma config FSLEEP = OFF // Flash Sleep Mode (Flash is powered down when the device is in Sleep mode)
#pragma config DBGPER = PG_ALL // Debug Mode CPU Access Permission (Allow CPU access to all permission regions)
#pragma config SMCLR = MCLR_NORM // Soft Master Clear Enable (MCLR pin generates a normal system Reset)
#pragma config SOSCGAIN = G3 // Secondary Oscillator Gain Control bits (Gain is G3)
#pragma config SOSCBOOST = ON // Secondary Oscillator Boost Kick Start Enable bit (Boost the kick start of the oscillator)
#pragma config POSCGAIN = G3 // Primary Oscillator Coarse Gain Control bits (Gain Level 3 (highest))
#pragma config POSCBOOST = ON // Primary Oscillator Boost Kick Start Enable bit (Boost the kick start of the oscillator)
#pragma config POSCFGAIN = G3 // Primary Oscillator Fine Gain Control bits (Gain is G3)
#pragma config POSCAGCDLY = AGCRNG_x_25ms // AGC Gain Search Step Settling Time Control (Settling time = 25ms x AGCRNG)
#pragma config POSCAGCRNG = ONE_X // AGC Lock Range bit (Range 1x)
#pragma config POSCAGC = Automatic // Primary Oscillator Gain Control bit (Automatic Gain Control for Oscillator)
#pragma config EJTAGBEN = NORMAL // EJTAG Boot Enable (Normal EJTAG functionality)
// DEVCP
#pragma config CP = OFF // Code Protect (Protection Disabled)
// SEQ
#pragma config TSEQ = 0xFFFF // Boot Flash True Sequence Number (Enter Hexadecimal value)
#pragma config CSEQ = 0xFFFF // Boot Flash Complement Sequence Number (Enter Hexadecimal value)
analog_to_digital_conversion.h
//**************************************************************************
// ANALOG TO DIGITAL CONVERSION HEADER FILE
//**************************************************************************
#include <analog_to_digital_conversion.c>
void Anaolog_to_Digital_Conversion_Setup (void);
void Anaolog_to_Digital_Conversion_Enable (void);
void Anaolog_to_Digital_Conversion_Disable (void);
uint16_t Anaolog_to_Digital_Conversion (void);
analog_to_digital_conversion.c
//**************************************************************************
// ANALOG TO DIGITAL CONVERSION SOURCE FILE
//**************************************************************************
void Anaolog_to_Digital_Conversion_Setup (void){
//All this procedure is taken from the device`s datasheet (no ADC interrupts are desired)
ADCANCONbits.ANEN5 = 0b0; //Analog and bias circuitry disabled (to set calibration)
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADC5CFGbits.ADCCFG = DEVADC5; //Copying the factory calibration ADC module bits to the ADC configuration register
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADCCON1bits.ON = 0b0; //Disabling the ADC module
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADC5TIMEbits.SAMC = 0b1111111111; //Sample time is set to 1025 TAD
ADC5TIMEbits.ADCDIV = 0b1111111; //254 * TQ = TAD (ADC clock division bits)
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADCANCONbits.WKUPCLKCNT = 0xF; //ADC warm up time is set to 32768 ADC clock cycles (maximum warm up time, around 32 us # 100 MHz SYSCLK)
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADCCON3bits.ADCSEL = 0b0; //Analog-to-Digital Clock Source (TCLK) -> SYSCLK
ADCCON3bits.CONCLKDIV = 0b000000; //TCLK = TQ
ADCCON3bits.DIGEN5 = 0b0; //All digital bits are disabled (according to the datasheet)
ADCCON3bits.VREFSEL = 0b000; //Vref is set to AVdd and AVss
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADCIMCON1bits.DIFF11 = 0b0; //AN11 is using Single-ended mode
ADCIMCON1bits.SIGN11 = 0b0; //AN11 is using Unsigned Data mode
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADCTRGSNSbits.LVL11 = 0b0; //Analog input is sensitive to the positive edge of its trigger (this is the value after a reset)
//---------------------------------------------------------------
ADCTRG3bits.TRGSRC11 = 0b00001; //AN11 is software triggered
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADCANCONbits.ANEN5 = 0b1; //Analog and bias circuitry enabled
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADCCON1bits.ON = 0b1; //Enabling the ADC module
//---------------------------------------------------------------
while(!((ADCCON2bits.BGVRRDY)&&(ADCANCONbits.WKRDY5))); //Wait until device analog environment is ready
ADCCON3bits.DIGEN5 = 0b1; //Enable digital circuitry for data processing
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADCCON3bits.ADINSEL = 0b001011; //Select analog channel 11 for conversion
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADCCON1bits.ON = 0b0; //Disabling the ADC module
}
void Anaolog_to_Digital_Conversion_Enable (void){
ADCCON1bits.ON = 0b1; //Enabling the ADC module
}
void Anaolog_to_Digital_Conversion_Disable (void){
ADCCON1bits.ON = 0b0; //Disabling the ADC module
}
uint16_t Anaolog_to_Digital_Conversion (void){
uint16_t ADC_value = 0;
ADCCON3bits.RQCNVRT = 1; //Trigger the conversion
while(!ADCDSTAT1bits.ARDY11); //Waiting until ADC result is ready to be read (# 100 MHz SYSCLK ADC conversion should take around 2ms)
ADC_value = ADCDATA11 & 0x000FFFF; //Acquiring ADC result, register is 32 bits, but conversion only gives 12 bit ADC value, hence getting rid of higher 16 bits (those are all zeros)
return (ADC_value);
}
As per the files in your question the inclusion should be done using header files since this is the common practice.
First of all you need to include the xc.h header in each file you use the processor specific definitions like special fuunction register and bit names.
Other dependencies for your program, might be anything from the standard C library like printf from the stdio.h header or uint8_t from the stdint.h header; or any library functions that you wrote for the application and so on.
Here is a trick for you: If you use MPLAB editor to write code, after typing a few letters of a function for example, you hit the Ctrl + Space then MPLAB editor will popup possible functions. When you select one of them from the popup list end hit the enter, it will add its header file automatically.
Now let's get back to your case. Your main file looks ok except stdio.h inclusion. You must change #include "stdio.h" to #include <stdio.h>.
Your adc.c file must have some includes as I mentioned above. First of all it must include the xc.h header. And you don't have to include the *.c file in the *.h file. I also recommend you to use header guards to prevent any possible nested inclusion, resulting in redefiniton errors.
analog_to_digital_conversion.h
// Header guard
#ifndef ANALOG_TO_DIGITAL_CONVERSION_H
#define ANALOG_TO_DIGITAL_CONVERSION_H
//**************************************************************************
// ANALOG TO DIGITAL CONVERSION HEADER FILE
//**************************************************************************
// #include <analog_to_digital_conversion.c> not needed here.
void Anaolog_to_Digital_Conversion_Setup (void);
void Anaolog_to_Digital_Conversion_Enable (void);
void Anaolog_to_Digital_Conversion_Disable (void);
uint16_t Anaolog_to_Digital_Conversion (void);
#endif /* ANALOG_TO_DIGITAL_CONVERSION_H */
analog_to_digital_conversion.c
//**************************************************************************
// ANALOG TO DIGITAL CONVERSION SOURCE FILE
//**************************************************************************
// include xc header for processor register and bit names
#include <xc.h>
// since you use uint16_t, you must include stdint header
#include <stdint.h>
// Finally include your own header for any further definitions
#include "analog_to_digital_conversion.h"
void Anaolog_to_Digital_Conversion_Setup (void){
//All this procedure is taken from the device`s datasheet (no ADC interrupts are desired)
ADCANCONbits.ANEN5 = 0b0; //Analog and bias circuitry disabled (to set calibration)
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADC5CFGbits.ADCCFG = DEVADC5; //Copying the factory calibration ADC module bits to the ADC configuration register
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADCCON1bits.ON = 0b0; //Disabling the ADC module
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADC5TIMEbits.SAMC = 0b1111111111; //Sample time is set to 1025 TAD
ADC5TIMEbits.ADCDIV = 0b1111111; //254 * TQ = TAD (ADC clock division bits)
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADCANCONbits.WKUPCLKCNT = 0xF; //ADC warm up time is set to 32768 ADC clock cycles (maximum warm up time, around 32 us # 100 MHz SYSCLK)
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADCCON3bits.ADCSEL = 0b0; //Analog-to-Digital Clock Source (TCLK) -> SYSCLK
ADCCON3bits.CONCLKDIV = 0b000000; //TCLK = TQ
ADCCON3bits.DIGEN5 = 0b0; //All digital bits are disabled (according to the datasheet)
ADCCON3bits.VREFSEL = 0b000; //Vref is set to AVdd and AVss
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADCIMCON1bits.DIFF11 = 0b0; //AN11 is using Single-ended mode
ADCIMCON1bits.SIGN11 = 0b0; //AN11 is using Unsigned Data mode
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADCTRGSNSbits.LVL11 = 0b0; //Analog input is sensitive to the positive edge of its trigger (this is the value after a reset)
//---------------------------------------------------------------
ADCTRG3bits.TRGSRC11 = 0b00001; //AN11 is software triggered
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADCANCONbits.ANEN5 = 0b1; //Analog and bias circuitry enabled
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADCCON1bits.ON = 0b1; //Enabling the ADC module
//---------------------------------------------------------------
while(!((ADCCON2bits.BGVRRDY)&&(ADCANCONbits.WKRDY5))); //Wait until device analog environment is ready
ADCCON3bits.DIGEN5 = 0b1; //Enable digital circuitry for data processing
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADCCON3bits.ADINSEL = 0b001011; //Select analog channel 11 for conversion
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
ADCCON1bits.ON = 0b0; //Disabling the ADC module
}
void Anaolog_to_Digital_Conversion_Enable (void){
ADCCON1bits.ON = 0b1; //Enabling the ADC module
}
void Anaolog_to_Digital_Conversion_Disable (void){
ADCCON1bits.ON = 0b0; //Disabling the ADC module
}
uint16_t Anaolog_to_Digital_Conversion (void){
uint16_t ADC_value = 0;
ADCCON3bits.RQCNVRT = 1; //Trigger the conversion
while(!ADCDSTAT1bits.ARDY11); //Waiting until ADC result is ready to be read (# 100 MHz SYSCLK ADC conversion should take around 2ms)
ADC_value = ADCDATA11 & 0x000FFFF; //Acquiring ADC result, register is 32 bits, but conversion only gives 12 bit ADC value, hence getting rid of higher 16 bits (those are all zeros)
return (ADC_value);
}
You must use the same inclusion logic for each *.c & *.h file pair that you add to your project.
Separate compilation requires visibility of external symbols. For example in analog_to_digital_conversion.c where ADCANCONbits is referenced, the compiler needs to see at least a declaration of ADCANCONbits so that it knows that the symbol exists and what its type is. The actual linkage and resolution to a definition occurs when the linker pulse the object code from each separately compiled translation unit together.
You resolve undeclared identifier errors by providing the declaration. In this case that declaration exists inside a header file that you must #include in every translation unit that references it. I am not familiar with PIC32 development, but would imagine that header is xc.h
Yoiu have a number of other issues, for example analog_to_digital_conversion.h referenced uint16_t but does not include <stdint.h> where that type is defined. You may get away with it due to inclusion in other modules, but you should not rely on it.
Also all header files require guards to avoid multiple declarations when included more than once in the same translation unit - which can easily happen when you have nested includes for example.

PIC32MK1024MCM064 gets stuck in timer2 ISR

I am beginner exploring PIC32MK1024MCM064 timers. Just want to write simple code with self triggering timer and some main program in the background. So I achieved my code to get into the ISR part, but the code gets stuck in the ISR after first time interrupt event. The code does not come back to the main loop with blinking leds. I investigated the datasheet quite well, but besides clearing the interrupt flag, I don`t know what to do else. I really thank you in advance for any help provided
// DEVCFG3
#pragma config USERID = 0xFFFF // Enter Hexadecimal value (Enter Hexadecimal value)
#pragma config PWMLOCK = OFF // PWM IOxCON lock (PWM IOxCON register writes accesses are not locked or protected)
#pragma config FUSBIDIO2 = ON // USB2 USBID Selection (USBID pin is controlled by the USB2 module)
#pragma config FVBUSIO2 = ON // USB2 VBUSON Selection bit (VBUSON pin is controlled by the USB2 module)
#pragma config PGL1WAY = OFF // Permission Group Lock One Way Configuration bit (Allow multiple reconfigurations)
#pragma config PMDL1WAY = OFF // Peripheral Module Disable Configuration (Allow multiple reconfigurations)
#pragma config IOL1WAY = OFF // Peripheral Pin Select Configuration (Allow multiple reconfigurations)
#pragma config FUSBIDIO1 = ON // USB1 USBID Selection (USBID pin is controlled by the USB1 module)
#pragma config FVBUSIO1 = ON // USB2 VBUSON Selection bit (VBUSON pin is controlled by the USB1 module)
// DEVCFG2
#pragma config FPLLIDIV = DIV_1 // System PLL Input Divider (1x Divider)
#pragma config FPLLRNG = RANGE_BYPASS // System PLL Input Range (Bypass)
#pragma config FPLLICLK = PLL_FRC // System PLL Input Clock Selection (FRC is input to the System PLL)
#pragma config FPLLMULT = MUL_2 // System PLL Multiplier (PLL Multiply by 1)
#pragma config FPLLODIV = DIV_2 // System PLL Output Clock Divider (2x Divider)
#pragma config BORSEL = HIGH // Brown-out trip voltage (BOR trip voltage 2.1v (Non-OPAMP deviced operation))
#pragma config UPLLEN = OFF // USB PLL Enable (USB PLL Disabled)
// DEVCFG1
#pragma config FNOSC = FRC // Oscillator Selection Bits (Internal Fast RC (FRC))
#pragma config DMTINTV = WIN_0 // DMT Count Window Interval (Window/Interval value is zero)
#pragma config FSOSCEN = OFF // Secondary Oscillator Enable (Disable Secondary Oscillator)
#pragma config IESO = OFF // Internal/External Switch Over (Disabled)
#pragma config POSCMOD = OFF // Primary Oscillator Configuration (Primary osc disabled)
#pragma config OSCIOFNC = OFF // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FCKSM = CSDCMD // Clock Switching and Monitor Selection (Clock Switch Disabled, FSCM Disabled)
#pragma config WDTPS = PS1 // Watchdog Timer Postscaler (1:1)
#pragma config WDTSPGM = STOP // Watchdog Timer Stop During Flash Programming (WDT stops during Flash programming)
#pragma config WINDIS = NORMAL // Watchdog Timer Window Mode (Watchdog Timer is in non-Window mode)
#pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT Disabled)
#pragma config FWDTWINSZ = WINSZ_25 // Watchdog Timer Window Size (Window size is 25%)
#pragma config DMTCNT = DMT31 // Deadman Timer Count Selection (2^31 (2147483648))
#pragma config FDMTEN = OFF // Deadman Timer Enable (Deadman Timer is disabled)
// DEVCFG0
#pragma config DEBUG = OFF // Background Debugger Enable (Debugger is disabled)
#pragma config JTAGEN = OFF // JTAG Enable (JTAG Disabled)
#pragma config ICESEL = ICS_PGx3 // ICE/ICD Comm Channel Select (Communicate on PGEC3/PGED3)
#pragma config TRCEN = OFF // Trace Enable (Trace features in the CPU are disabled)
#pragma config BOOTISA = MIPS32 // Boot ISA Selection (Boot code and Exception code is MIPS32)
#pragma config FECCCON = ECC_DECC_DISABLE_ECCON_WRITABLE// Dynamic Flash ECC Configuration Bits (ECC and Dynamic ECC are disabled (ECCCON<1:0> bits are writable))
#pragma config FSLEEP = OFF // Flash Sleep Mode (Flash is powered down when the device is in Sleep mode)
#pragma config DBGPER = PG_ALL // Debug Mode CPU Access Permission (Allow CPU access to all permission regions)
#pragma config SMCLR = MCLR_NORM // Soft Master Clear Enable (MCLR pin generates a normal system Reset)
#pragma config SOSCGAIN = G3 // Secondary Oscillator Gain Control bits (Gain is G3)
#pragma config SOSCBOOST = ON // Secondary Oscillator Boost Kick Start Enable bit (Boost the kick start of the oscillator)
#pragma config POSCGAIN = G3 // Primary Oscillator Coarse Gain Control bits (Gain Level 3 (highest))
#pragma config POSCBOOST = ON // Primary Oscillator Boost Kick Start Enable bit (Boost the kick start of the oscillator)
#pragma config POSCFGAIN = G3 // Primary Oscillator Fine Gain Control bits (Gain is G3)
#pragma config POSCAGCDLY = AGCRNG_x_25ms// AGC Gain Search Step Settling Time Control (Settling time = 25ms x AGCRNG)
#pragma config POSCAGCRNG = ONE_X // AGC Lock Range bit (Range 1x)
#pragma config POSCAGC = Automatic // Primary Oscillator Gain Control bit (Automatic Gain Control for Oscillator)
#pragma config EJTAGBEN = NORMAL // EJTAG Boot Enable (Normal EJTAG functionality)
// DEVCP
#pragma config CP = OFF // Code Protect (Protection Disabled)
// SEQ
#pragma config TSEQ = 0x0 // Boot Flash True Sequence Number (Enter Hexadecimal value)
#pragma config CSEQ = 0xFFFF // Boot Flash Complement Sequence Number (Enter Hexadecimal value)
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#include <xc.h>
#include <toolchain_specifics.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include "stdio.h"
#include <sys/attribs.h>
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define CPU_CLOCK_FREQUENCY 8000000
#define _CP0_GET_COUNT() _mfc0 (_CP0_COUNT, _CP0_COUNT_SELECT)
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void delay_ms ( uint32_t delay_ms)
{
uint32_t startCount, endCount;
endCount=((CPU_CLOCK_FREQUENCY/1000)*delay_ms)/2;
startCount=_CP0_GET_COUNT();
while((_CP0_GET_COUNT()-startCount)<endCount);
}
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void Timer2_setup(void){
PB2DIVbits.ON = 0b0; //PB2CLK is disabled
PB2DIVbits.PBDIVRDY = 0b1; //Enabling the PBDIV configuration
PB2DIVbits.PBDIV = 0b0000000; //PBCLKx is SYSCLK divided by 128
PB2DIVbits.PBDIVRDY = 0b0; //Disabling the PBDIV configuration
PB2DIVbits.ON = 0b1; //PB2CLK is enabled
//----------------------------------------------------
T2CONbits.ON = 0b0; //Timer2 is disabled
T2CONbits.TCS = 0b0; //Internal peripheral clock
T2CONbits.T32 = 0b1; //Timer2 is set to 32 bits
T2CONbits.TCKPS = 0b101; //1:256 prescale value
T2CONbits.SIDL = 0b1; //Timer2 does not work in idle mode
TMR2 = 0x0; //Clear counter
PR2 = 124999U; //Timer2 period is set to 1000 milliseconds
//----------------------------------------------------
//Interrupt setup
IEC0bits.T2IE = 0b1; //Enable timer interrupt
IPC2bits.T2IP = 0b001; //Interrupt priority set to 1
}
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
int main ( void )
{
TRISAbits.TRISA7 = 0;
LATAbits.LATA7 = 0;
TRISBbits.TRISB14 = 0;
LATBbits.LATB14 = 0;
TRISBbits.TRISB15 = 0;
LATBbits.LATB15 = 0;
Timer2_setup();
__builtin_enable_interrupts(); // VERY IMPORTANT Built in macro function to globally enable interrupts
T2CONbits.ON = 0b1; //Timer2 is enabled
while (1)
{
LATBbits.LATB14 = 1;
delay_ms(300);
LATBbits.LATB14 = 0;
LATBbits.LATB15 = 1;
delay_ms(300);
LATBbits.LATB15 = 0;
}
return (EXIT_FAILURE);
}
//INTERRUPTS-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void __ISR( _TIMER_2_VECTOR, IPL1SRS) Timer2_Handler (void){
T2CONbits.ON = 0b0; //Timer2 is disabled
TMR2 = 0x0; //Clear counter
LATAbits.LATA7 = 1;
delay_ms(300); //Interrupt indicator
LATAbits.LATA7 = 0;
IFS0bits.T2IF = 0b0; //Clear input change interrupt
T2CONbits.ON = 0b1; //Timer2 is enabled
}
You most definitely shouldn't call delay_ms() in your interrupt handler. I'm fairly sure that this is the reason of your problem. IRQ handlers should be as quick as possible.
Check out https://www.aidanmocke.com/blog/2018/11/15/timers/. This whole blog is great for learning firmware development on PIC32.

Microchip Starter Kits with SPI mode

I want to use microcontrollers for communicating data by SPI. So, I have chosen firstly the Microchip USB Starter Kit III module which has a PIC32MX470F512L. I tried several ways to code its SPI, but only the clock signal SCK can be seen on an oscilloscope.
Then, i tried the same code (just adjusted a few code lines to the new PIC) with the Microchip Starter Kit I which has a PIC32MX360F512L. And all run perfectly. So, i don't understand why the USB Starter Kit III doesn't work for SPI communication?
I give you the code used to test the SPI SDO & /SS.
#define _SUPPRESS_PLIB_WARNING
#include <stdio.h>
#include <stdlib.h>
#include <plib.h>
#include <p32xxxx.h>
#include <xc.h>
#include <peripheral/spi.h>
// DEVCFG2
#pragma config FPLLIDIV = DIV_2 // PLL Input Divider (12x Divider)
#pragma config FPLLMUL = MUL_20 // PLL Multiplier (24x Multiplier)
#pragma config FPLLODIV = DIV_1 // System PLL Output Clock Divider (PLL Divide by 256)
// DEVCFG1
#pragma config FNOSC = PRIPLL // Oscillator Selection Bits (Primary Osc w/PLL (XT+,HS+,EC+PLL))
#pragma config FSOSCEN = OFF // Secondary Oscillator Enable (Disabled)
#pragma config IESO = ON // Internal/External Switch Over (Enabled)
#pragma config POSCMOD = HS // Primary Oscillator Configuration (HS osc mode)
#pragma config OSCIOFNC = OFF // CLKO Output Signal Active on the OSCO Pin (Disabled)
#pragma config FPBDIV = DIV_1 // Peripheral Clock Divisor (Pb_Clk is Sys_Clk/8)
#pragma config FCKSM = CSDCMD // Clock Switching and Monitor Selection (Clock Switch Disable, FSCM Disabled)
#pragma config WDTPS = PS1048576 // Watchdog Timer Postscaler (1:1048576)
#pragma config FWDTEN = OFF // Watchdog Timer Enable (WDT Disabled (SWDTEN Bit Controls))
// DEVCFG0
#pragma config DEBUG = OFF // Background Debugger Enable (Debugger is Enabled)
#pragma config ICESEL = ICS_PGx2 // ICE/ICD Comm Channel Select (Communicate on PGEC1/PGED1)
#pragma config PWP = OFF // Program Flash Write Protect (Disable)
#pragma config BWP = OFF // Boot Flash Write Protect bit (Protection Disabled)
#pragma config CP = OFF // Code Protect (Protection Disabled)
int main(void) {
TRISGbits.TRISG6=0; //SCK2
TRISGbits.TRISG7=1; //SDI2
TRISGbits.TRISG8=0; //SDO2
TRISGbits.TRISG9=0; //SS2
OpenSPI2(SPI_MODE16_ON|SPI_SMP_ON|MASTER_ENABLE_ON|SEC_PRESCAL_5_1|PRI_PRESCAL_16_1, SPI_ENABLE);
int data;
PORTGbits.RG9 = 1;
while(1)
{
PORTGbits.RG9 = 0;
putcSPI2(0xaaaa);
data=getcSPI2();
PORTGbits.RG9 = 1;
}
return 0;
}
Thanks
Pin Mapping
Do you do the pin mapping ? It does not appear on the code your posted.
You need to assign the pin to the SPI Module using the PPS (peripheral pin select).
OpenSPI is a library function, but it's also needed to do the pin mapping with the pin peripheral select (PPS)
Point 12.3.1 http://ww1.microchip.com/downloads/en/DeviceDoc/60001120F.pdf
Pin State (analog / digital)
Check your pin are not in (default) analog state. If the pin also has an analog (AN) function, the default state will be analog and you cannot control that pin. You need to set the register ANSELx (or AD1PCFG) to set the pin.
In the chip PIC32MX470F512L the pin you are using (RG6-9) also has analog function (AN):
10 AN16/C1IND/RPG6/SCK2/PMA5/RG6
11 AN17/C1INC/RPG7/PMA4/RG7
12 AN18/C2IND/RPG8/PMA3/RG8
14 AN19/C2INC/RPG9/PMA2/RG9
Page 7 http://ww1.microchip.com/downloads/en/DeviceDoc/60001185F.pdf
Analog pin Section 12.2.5 http://ww1.microchip.com/downloads/en/DeviceDoc/60001120F.pdf
Hi everyone and thanks for your replies !
Thanks to your help, i found out that issue. Pin configuration was necesary. Below the code i added for pin configuration.
// Mapping SPI1 & SPI2
SDI1Rbits.SDI1R = 0xa; // SDI1 to C4
RPD0Rbits.RPD0R = 0x8; // SDO1 to D0
RPB2Rbits.RPB2R = 0x7; // SS1 to B2
SDI2Rbits.SDI2R = 0x1; // SDI2 to G7
RPG8Rbits.RPG8R = 0x6; // SDO2 to G8
RPG9Rbits.RPG9R = 0x6; // SS2 to G9

Connecting two PIC18F starter kits using USART2

I want to connect two PIC18F starter kits (with PIC18F46J50), using RS232. Since USART1 is already connected to the card reader (integrated), I need to use USART2 (I need to remap RX2/TX2 to RP19/RP20 pins-RD2/RD3).
I already found some demo code for SENDING:
#define _XTAL_FREQ 8000000 //The speed of your internal(or)external oscillator
#include <p18cxxx.h>
#include <usart.h>
int i = 0;
// CONFIG1L
#pragma config WDTEN = OFF // Watchdog Timer (Disabled - Controlled by SWDTEN bit)
#pragma config PLLDIV =3 // PLL Prescaler Selection bits - Divide by 3 (12 MHz oscillator input)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset (Enabled)
#pragma config XINST = OFF // Extended instruction set disabled
// CONFIG1H
#pragma config CPUDIV = OSC1 // CPU System Clock Postscaler (No CPU system clock divide)
#pragma config CP0 = OFF // Code Protect (Program memory is not code-protected)
// CONFIG2L
#pragma config OSC = HSPLL //HS oscillator, PLL enabled, HSPLL used by USB
#pragma config T1DIG = ON // T1OSCEN Enforcement (Secondary Oscillator clock source may be selected)
#pragma config LPT1OSC = OFF // Low-Power Timer1 Oscillator (High-power operation)
#pragma config FCMEN = OFF //Fail-Safe Clock Monitor disabled
#pragma config IESO = OFF //Two-Speed Start-up disabled
// CONFIG2H
#pragma config WDTPS = 32768 // Watchdog Postscaler (1:32768)
// CONFIG3L
#pragma config DSWDTOSC = INTOSCREF // DSWDT Clock Select (DSWDT uses INTRC)
#pragma config RTCOSC = T1OSCREF // RTCC Clock Select (RTCC uses T1OSC/T1CKI)
#pragma config DSBOREN = OFF // Zero-Power BOR disabled in Deep Sleep
#pragma config DSWDTEN = OFF // Deep Sleep Watchdog Timer (Disabled)
#pragma config DSWDTPS = 8192 //1:8,192 (8.5 seconds)
// CONFIG3H
#pragma config IOL1WAY =OFF //IOLOCK bit can be set and cleared
#pragma config MSSP7B_EN = MSK7 // MSSP address masking (7 Bit address masking mode)
// CONFIG4L
#pragma config WPFP = PAGE_1 // Write/Erase Protect Page Start/End Location (Write Protect Program Flash Page 0)
#pragma config WPEND = PAGE_0 //Start protection at page 0
#pragma config WPCFG = OFF //Write/Erase last page protect Disabled
// CONFIG4H
#pragma config WPDIS = OFF //WPFP[5:0], WPEND, and WPCFG bits ignored
#define USE_AND_MASKS
unsigned char Txdata[] = "MICROCHIP_USART";
void Delay1Second(void);
void main (void)
{
unsigned char spbrg=0,baudconfig=0,i=0;
// REMAPE ID PORT
PPSCON = 0x00; // unlock peripheral Pin select register
RPOR19 = 0x05; // assign USART2 TX to RP19/RD2
RPINR16 = 0x14; // assign USART2 RX to RP20/RD3
PPSCON = 0x01; // lock peripheral Pin select register
TRISDbits.TRISD2 = 0; // TX2 output
TRISDbits.TRISD3 = 1; // RX2 input
//------USART Setup ----
Close2USART(); //turn off usart if was previously on
spbrg = 51;
Open2USART(USART_TX_INT_OFF &
USART_RX_INT_OFF &
USART_ASYNCH_MODE &
USART_EIGHT_BIT &
USART_CONT_RX &
USART_BRGH_HIGH, spbrg);
baudconfig = BAUD_8_BIT_RATE & BAUD_AUTO_OFF;
baud2USART (baudconfig);
PORTB = 0x03;
while(1){
//------USART Transmission ----
while(Busy2USART()); //Check if Usart is busy or not
puts2USART((char *)Txdata); //transmit the string
Delay1Second();
Close2USART();
}
}
void Delay1Second()
{
for(i=0;i<100;i++)
{
__delay_ms(10);
}
}
I connected the two boards using two wires (on D2 and D3 pins), and I want to send a string from board1 to board2. I think I need to use interrupts to read, but I haven't found any demo code. Also, I don't know if the configuration pins are ok.
Can somebody show me how to receive the sent text to board no.2?
I will assume that you did the wiring correctly.
You don't need interrupts to receive. It can be useful but it's not required. To receive your string, you just have to do :
gets2USART( str, 10 );
If your string if 10 characters long (including the null terminator).
If you want to receive a string of an arbitrary length, you may write your own gets2USART to read until the null terminator. It is actually quite simple, here is the source code of gets2USART to help you :
void gets2USART(char *buffer, unsigned char len)
{
char i; // Length counter
unsigned char data;
for(i=0;i<len;i++) // Only retrieve len characters
{
while(!DataRdy2USART());// Wait for data to be received
data = getc2USART(); // Get a character from the USART
// and save in the string
*buffer = data;
buffer++; // Increment the string pointer
}
}
Also, here is the source code of puts2USART :
void puts2USART( char *data)
{
do
{ // Transmit a byte
while(Busy2USART());
putc2USART(*data);
} while( *data++ );
}
You can see that there already is a while(Busy2USART());, so you don't need to add one. It is logical, because the UART is byte wise, so it is busy when it sends a byte, and the function needs to check for every byte.
Also, you are closing the UART after use, but actually loop to redo the sending. Since you just closed the UART, that won't work.

Reading pic input on PIC12LF1552

I'm working on a project and I need to use the PIC12LF1552. The code I'm trying to run is very simple, consists on reading the input on RA5 and then setting the output on RA2 to light an LED.
The problem is that it seems that the PIC is not reading the input on RA5. If I program the PIC to blink the LED without reading any input, it works correctly.
The program used to compile is MPLAB X 2.05, and the programmer being used is Pickit3.
The code that I'm using is this:
#include <xc.h>
#include "pic12lf1552.h"
#include <stdio.h>
#include <stdlib.h>
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config STVREN = OFF // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LPBOR = OFF // Low-Power Brown Out Reset (Low-Power BOR is disabled)
#pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
#define LED PORTAbits.RA2
#define SWITCH PORTAbits.RA5
void MSDelay (unsigned int);
void main(void)
{
//Set up I/O pins
TRISAbits.TRISA2 = 0; //RA2 = LED output
TRISAbits.TRISA5 = 1; //RA5 = switch
ADCON1=0b00100;
// ADCON1 = ;
//int b;
// int i;
if(SWITCH == 0)
{
LED=1;
MSDelay(2000);
LED=0;
}
else
{
LED=0;
MSDelay(2000);
}
}
void MSDelay(unsigned int itime)
{
unsigned int i;
unsigned char j;
for(i=0; i<itime;i++);
for(j=0; j<165;j++);
}
According to the datasheet http://www.alldatasheet.com/datasheet-pdf/pdf/504825/MICROCHIP/PIC12LF1552.html, on page 93 about the ANSELA register :
"The ANSELA bits default to the Analog
mode after Reset. To use any pins as
digital general purpose or peripheral
inputs, the corresponding ANSEL bits
must be initialized to ‘0’ by user software."
If you don't plan to use analog inputs, you may add something like ANSELA=0;
for the moment, output works because : "The state of the ANSELA bits has no effect on digital
output functions. A pin with TRIS clear and ANSEL set
will still operate as a digital output,...
"
Bye,

Resources