Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Trying to read dipswitch through SPI to LCD

SC9

Newbie
Joined
May 11, 2024
Messages
4
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
44
Hi all,

I'm using PIC18F25K22 which is 8 bit system, SPI, MCP23S08.
A1 is set to 1 and A0 is set to 1 as well on the hardware.
The software used in Mplab – anscii – embedded c
I want the SPI supposed to be control a servo later on - but at the moment I have little faith that the SPI connection to PIC is working..
I'm trying to use LCD screen to show the state of dipswitches.

The LCD code works on it's own, but the dipswitch message always read 0, regardless of what I do to them.

The code is below I believe the issue is somewhere with the SPI and MCP configuration but I've been staring at it for the past week and I really can't see what I'm missing.

Any pointers would be appreciated!



#include <xc.h>

#pragma config FOSC = HSMP // HS oscillator - medium power
#pragma config PWRTEN = ON // Powerup timer on
#pragma config BOREN = OFF // Brownout detect off
#pragma config LVP = OFF // Low voltage programming off
#pragma config PBADEN = OFF // Port B all digital I/O

#define _XTAL_FREQ 4000000 // Clock frequency for delay functions

// Port definitions
#define TRIS_SDI TRISCbits.TRISC5 // Direction define SDI input
#define TRIS_SCK TRISCbits.TRISC3 // Direction define clock pin as output
#define CS PORTBbits.RB0 // CS - RB0
#define TRIS_CS TRISBbits.TRISB0 // Direction CS - B0
#define TRIS_SDO TRISCbits.TRISC4// Direction SD0 as output

// MCP23S08 registers taken from datasheet
#define mcp23S08_read 0x47 // Control byte 01000 - first 5 bits. 11 A1 A0 - user dependent - last bit R/W=1 so read
#define mcp23S08_address_write 0x46 // Control byte 01000 - 11(A1 A0), R/W=0 so write
#define MCP_IODIR 0x00 // IO Direction register set to output
#define MCP_IPOL 0x01 // IO Polarity register - bit7 opposite logic state of the input pin
#define MCP_IOCON 0x05 // bit 0=1 - but unimplemented in data sheet. bit 2=1 - overrides intpol
#define MCP_GPPU 0x06 // 00000110 - pull-up resistor enabled on bit 1&2
#define MCP_GPIO 0x09 //
#define MCP_DEFVAL 0x03
#define MCP_INTCON 0x04

// LCD definitions
#define LCD_Port PORTB
#define EN PORTCbits.RC6
#define RS PORTCbits.RC7
#define Set_LCD_Address_command 0x80

#define Set_LCD_Position_R1C1 0x00
#define Set_LCD_Position_R2C1 0xC0
#define clear_LCD 0x01

// Function declarations
void PIC_Initialise(void);
void SPI_Initiailise(void);
void MCP23S08_Initialise(void);
void SPI_Send_data(unsigned char device_address, unsigned char register_adress, unsigned char register_data);
void WriteSPI(unsigned char data);

unsigned char ReadDipswitches(void);
void LCD_Init(void);
void LCD_Command(unsigned char cmd);
void LCD_Char(char dat);
void LCD_String(char *msg);

void main(void) {
PIC_Initialise();
SPI_Initiailise();
MCP23S08_Initialise();

LCD_Init();
LCD_Command(0x80);
LCD_String("Crying");
__delay_ms(1000);
LCD_Command(clear_LCD);

while (1) {
unsigned char switchState = ReadDipswitches();



LCD_Command(0x80); // Move cursor to the beginning of the first line
LCD_String("DIPSWITCH: ");
LCD_Char(switchState + '0'); // Display the switch state as a character
__delay_ms(500); // Delay before checking the dipswitches again
}
}

void PIC_Initialise(void) {
// Configure SPI pins
TRISCbits.TRISC3 = 0; // SCK as output
TRISCbits.TRISC4 = 1; // SDI as input
TRISCbits.TRISC5 = 0; // SDO as output
TRISBbits.TRISB0 = 0; // CS as output

// Configure LCD control pins
TRISCbits.TRISC6 = 0; // EN as output
TRISCbits.TRISC7 = 0; // RS as output

// Configure LCD data pins
TRISBbits.TRISB4 = 0; // Data 4 as output
TRISBbits.TRISB5 = 0; // Data 5 as output
TRISBbits.TRISB6 = 0; // Data 6 as output
TRISBbits.TRISB7 = 0; // Data 7 as output

// Set all other ports as digital outputs
ANSELA = ANSELB = ANSELC = 0x00;

// Clear all port outputs
LATA = LATB = LATC = 0x00;
}


void SPI_Initiailise(void) {

SSP1STAT = 0x40; // Bit 6 set to 1 - SPI Clock Edge Select

SSP1CON1 = 0x20; // Enables serial port and configures SCKx, SDOx, SDIx and SSx, clock = FOSC / 4
}

void MCP23S08_Initialise ()
{
SPI_Send_data(mcp23S08_address_write, MCP_IOCON, 0x38); //sequential and slew disables

SPI_Send_data(mcp23S08_address_write, MCP_IODIR, 0xFF); // sets all as inputs
SPI_Send_data(mcp23S08_address_write, MCP_IPOL, 0x00); //set polarity to same
SPI_Send_data(mcp23S08_address_write, MCP_GPPU, 0x00); //pull ups disabled
SPI_Send_data(mcp23S08_address_write, MCP_INTCON, 0x00); //compare register for interrupt on change
SPI_Send_data(mcp23S08_address_write, MCP_DEFVAL, 0x00); //compare register for interrupt on change
}


void SPI_Send_data(unsigned char device_address, unsigned char register_adress, unsigned char register_data) {

CS = 0;

WriteSPI(device_address);
WriteSPI(register_adress);
WriteSPI(register_data);
CS = 1;
}


void WriteSPI(unsigned char data) {
SSP1BUF = data; // Write data to SSPBUF (data buffer)
while(!PIR1bits.SSPIF); // Wait for complete 1 byte transmission
PIR1bits.SSPIF = 0; // Clear SSPIF flag

}


unsigned char ReadDipswitches(void) {

unsigned char switchState;



CS = 0; // Lower chip select line

WriteSPI(mcp23S08_read); // Selecting read address

WriteSPI(MCP_GPIO); // GPIO register selection

// Dummy write to receive data

SSP1BUF = 0x00;

while(!SSP1STATbits.BF); // Wait for buffer full

switchState = SSP1BUF; // Read received data

CS = 1;



return switchState; // Value read from SSP1BUF (data buffer) is the SPI

}


void LCD_Init(void)

{

LCD_Port = 0x00; // Port as output port

__delay_ms(20); // 41ms delay

LCD_Command(0x30); //

__delay_ms(5); // 41ms delay

LCD_Command(0x30); //

__delay_ms(2); // 41ms delay

LCD_Command(0x30); //

__delay_ms(1); // 41ms delay

LCD_Command(0x02); // Return home

__delay_ms(5); // 41ms delay

LCD_Command(0x28); //

__delay_ms(5); // 1ms delay

LCD_Command(0x08); //

__delay_ms(5); // 1ms delay

LCD_Command(0x01); // Clear Display

__delay_ms(15); // 41ms delay

LCD_Command(0x06); //

__delay_ms(1); // 2ms delay

LCD_Command(0x0F); //

__delay_ms(1); // 2ms delay


}


void LCD_Command(unsigned char cmd)

{

char ldata = 0;

ldata = (ldata & 0x0f) | (0xF0 & cmd); //

RS = 0; //

EN = 1; //

PORTB = ldata;

__delay_ms(1);

EN = 0;

__delay_ms(5);

ldata = (ldata & 0x0f) | (cmd << 4); //

PORTB = ldata;

EN = 1;

__delay_ms(1);

EN = 0;

__delay_ms(5);

}


void LCD_String(char *msg)

{

while ((*msg) != 0)

{

LCD_Char(*msg);

msg++;

}

}


void LCD_Char(char dat)

{

char ldata = 0;

ldata = (ldata & 0x0f) | (0xF0 & dat);

//ldata = dat; //
PORTB = ldata;
RS = 1; //
EN = 1; //
// NOP();
__delay_us(10);
EN = 0;
__delay_ms(5);
ldata = (ldata & 0x0f) | (dat << 4);
//ldata = dat; //
PORTB = ldata;
EN = 1; //High
__delay_us(10);
// NOP();

EN = 0;

__delay_ms(5);

}

PIC.png
 

Attachments

  • Dipswitch.txt
    6.8 KB · Views: 34
Hi,

I´ve used the MCP23S08. As input as well as output.

To give you detailed answer I need detailed informations first.
Like a schematic, especially the MCPxx part.

Do you have a scope to verify SPI signals?

Klaus
 
Hi,

I´ve used the MCP23S08. As input as well as output.

To give you detailed answer I need detailed informations first.
Like a schematic, especially the MCPxx part.

Do you have a scope to verify SPI signals?

Klaus
Hi,
Thank you for replying!
Unfortunately I have nothing to scope the SPI signals. I tried adding LED light - in case the issue is with my LCD but, no joy there.
The schematic can be seen below. A1 and A0 are set to 1 in the hardware.

1715440884417.png
 
in case the issue is with my LCD
So you don´t know whether the problem is SPI or display?.

Better give a detailed error description. How do you test it? What is your expectation? What does work like expected, what does not work like expeted?
And do your software debuggin step by step.

Klaus
 
I want to ensure that SPI link is working - the end goal is for the dipswitches to control the angle of the servo movement, which I attempted and didn't work so I tried to scale back what I was doing.

I checked dipswitches without SPI, with the connection to the PIC - I used LED and 7 segment signal and it worked fine.

The LCD turns on and I can send messages to it, but it won't count the dipswitches that have been flipped. I'm not sure whether the code for the LCD to do this is 100% correct though. That's why I added LED light in case the issue was with my LED 'counting' code.

I'm running out of the ideas how I can check whether it's definitely SPI link that is not working - but it seems that other components are working fine till the SPI is connected to it.

At this point, I think it's either hardware, or something in my code that has been done incorrectly. I have 2 MCPs on my board and I tried connecting to both, however that didn't change anything.. so I'm kind of leaning towards the code being an issue..

Thank you!
 
Well, i’m confused. How did you make the jump from ‘the display doesn’t show the state of the dip switches’ to ‘the SPI doesn’t work’?

Maybe it’s:
1. The MCP23S08.
2. A bad connection
3. Your code (sorry, i’m not going to read through all that)
4. Your display

Have you verified you can write ANYTHING to the display?
Have you tried using the debugger? That would be the first thing I did before posting anything.
 
Well, i’m confused. How did you make the jump from ‘the display doesn’t show the state of the dip switches’ to ‘the SPI doesn’t work’?

Maybe it’s:
1. The MCP23S08.
2. A bad connection
3. Your code (sorry, i’m not going to read through all that)
4. Your display

Have you verified you can write ANYTHING to the display?
Have you tried using the debugger? That would be the first thing I did before posting anything.
Sorry, I'm most likely writing about it in roundabout way, as I'm pretty inexperienced with embbeded.

I think the SPI doesn't work -as whenever I wanted LCD or LED to react to dipswitches which are connected to MCP/SPI, nothing was happening. Yet, dipswitches work fine, when connected directly to PIC.

At this point I just want to ensure the MCP/SPI works. I think I initlised it correctly.

Yes, I can write to LCD no problem, there are no issues displaying messages. I'm using mplab icd 4 for debugging.

Thank you
 
Hi,

I recommend to first make the display work. Then you can use it as visual feedback for any other device/software debugging.

the data flow seems to be:
MCP --> SPI --> microcontroller (SPI byte) --> ASCII byte --> display

Now write software step by step in this (backwards) order

* Make the display work, just to show anything useful
* then make the display to an show ASCII variable (single byte), but continously changing. Like "0" then "1" and back with a delay of 1s
* then make a variable (maybe a counter, 1 s period time), generate 8 ASCII values "0"/"1" (according the bit states) and display them
* then read the SPI and value and display it

Report what happens, where you encounter problems.

Klaus
 
void MCP23S08_Initialise ()
{
SPI_Send_data(mcp23S08_address_write, MCP_IOCON, 0x38); //sequential and slew disables

SPI_Send_data(mcp23S08_address_write, MCP_IODIR, 0xFF); // sets all as inputs
SPI_Send_data(mcp23S08_address_write, MCP_IPOL, 0x00); //set polarity to same
SPI_Send_data(mcp23S08_address_write, MCP_GPPU, 0x00); //pull ups disabled
SPI_Send_data(mcp23S08_address_write, MCP_INTCON, 0x00); //compare register for interrupt on change
SPI_Send_data(mcp23S08_address_write, MCP_DEFVAL, 0x00); //compare register for interrupt on change
}


void SPI_Send_data(unsigned char device_address, unsigned char register_adress, unsigned char register_data) {

CS = 0;

WriteSPI(device_address);
WriteSPI(register_adress);
WriteSPI(register_data);
CS = 1;
}


void WriteSPI(unsigned char data) {
SSP1BUF = data; // Write data to SSPBUF (data buffer)
while(!PIR1bits.SSPIF); // Wait for complete 1 byte transmission
PIR1bits.SSPIF = 0; // Clear SSPIF flag

}

where you are storing the response from MC23S08 IC?
Try to do it like that and print it on LCD, what you receive from MC23S08
uint8_t WriteSPI(unsigned char data) {
SSP1BUF = data; // Write data to SSPBUF (data buffer)
while(!PIR1bits.SSPIF); // Wait for complete 1 byte transmission
PIR1bits.SSPIF = 0; // Clear SSPIF flag
return SSP1BUF;
}
 

LaTeX Commands Quick-Menu:

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top