Issue in interfacing SPI e-ink display with PIC 18F46K22

不羁岁月 提交于 2021-01-28 04:48:30

问题


I am using a PIC 18F46K22 in SPI master mode to communicate with a Waveshare 1.54" ePaper Module. The FOSC frequency is 8Mhz internal and SPI configuration is FOSC/4. So when I check the output on logic-analyzer some output bits are differ from expected. And there is some deviation in SCL.

#include <xc.h>
#include "config.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "main.h"

//#define _XTAL_FREQ 8000000
#define SPI1_DUMMY_DATA 0x0
#define SPI_RX_IN_PROGRESS 0x0
#define MY_BUFFER_SIZE 25

extern UBYTE EPD_Init(const unsigned char* lut);


unsigned char myWriteBuffer[100]="Hi I'm master..";
uint8_t myReadBuffer[100];
uint8_t total;
uint8_t temp;
uint8_t my_data = 0x58;

void UART_Init(void)
{
    //69
    SPBRG2 = 69;

    TXSTA2bits.BRGH = 1;
    BAUDCON2bits.BRG16 = 1; // Divisor at 8 bit

    TRISDbits.TRISD6 = 0;
    TRISDbits.TRISD7 = 1;

    RCSTA2bits.SPEN = 1; // Enable serial port    
    TXSTA2bits.SYNC = 0; // Async operation

    TXSTA2bits.TX9 = 0; // No tx of 9th bit
    RCSTA2bits.RX9 = 0; // No rx of 9th bit

    TXSTA2bits.TXEN = 1; // Enable transmitter
    RCSTA2bits.CREN = 1; // Enable receiver    
}

void UART_Putch(unsigned char bt)
{
    while (!PIR3bits.TX2IF); // hold the program till TX buffer is free
    TXREG2 = bt; //Load the transmitter buffer with the received value
}

void UART_Print(unsigned const char *ptr)
{
    while (*ptr != 0)
    {
        UART_Putch(*ptr++);
    }
}

unsigned char UART_getch() {
    unsigned char temp;
    if (RCSTA2bits.OERR) // check for Error 
    {
        RCSTA2bits.CREN = 0; //If error -> Reset
        //__delay_ms(10);
        RCSTA2bits.CREN = 1; //If error -> Reset 
    }
    while (!PIR3bits.RC2IF); // hold the program till RX buffer is free

    temp = RCREG2;
    return temp; //receive the value and send it to main function
}

void main() 
{
    ANSELA = 0;
    ANSELB = 0;
    ANSELC = 0;
    ANSELD = 0;
    
    TRISBbits.TRISB0 = 0; //RST Pin OUTPUT
    TRISBbits.TRISB1 = 0; //DC Pin OUTPUT
    TRISBbits.TRISB2 = 0; //CS Pin OUTPUT
    
    TRISBbits.RB3 = 1;  //BUSY Pin INPUT
        
//    int i;
    
    TRISD =0;/* PORT initialize as output */
    
    EPD_RST_PIN = 0;
    EPD_DC_PIN = 0;
     
    //OSCCON = 0x72;        /* Use internal osc. frequency 16 MHz */    
    
    OSCCONbits.SCS = 0b10;          //Frequency & PLL SETUP
    OSCCONbits.IRCF = 0b110;        //8 MHz
    while (!OSCCONbits.HFIOFS);
    
    OSCTUNEbits.PLLEN = 0;          //PLL disable

    
    UART_Init();


    
    SPI_Init_Master();      /* Initialize SPI communication as a master */   
    

  
    if(EPD_Init(lut_full_update) != 0) {
        UART_Print("e-Paper init failed\r\n");
        while(1);
    }
    UART_Print("e-Paper init\r\n");
    for(uint8_t i = 0; i < 10; i++){
    __delay_ms(10);
    }


    EPD_Clear();
    UART_Print("e-Paper cleared\r\n");
       for(uint8_t i = 0; i < 10; i++){
    __delay_ms(50);
    }
    

    while(1)
    {

        

//        total = 0;
//        //do
//        //{
//            LATAbits.LATA5=0;
//            //total = SPI1_Exchange8bitBuffer(SPI1_DUMMY_DATA, MY_BUFFER_SIZE, &myReadBuffer[total]);
//            total = SPI1_Exchange8bit(my_data);
//            
//            LATAbits.LATA5=1;
//            __delay_ms(500);
//            __delay_ms(500);
//            // Do something else...
//
//        //} while(total < MY_BUFFER_SIZE);
//            //while(1);
//           
//         EPD_Clear();
//    
//    __delay_ms(500);
    }
}

void SPI_Init_Master()
{
    /* PORT definition for SPI pins*/    
    TRISCbits.TRISC4 = 1;   /* RB0 as input(SDI) */
    TRISCbits.TRISC3 = 0;   /* RB1 as output(SCK) */
//    TRISBbits.TRISB2 = 0; /* RA5 as a output(SS') */
    TRISCbits.TRISC5 = 0;   /* RC7 as output(SDO) */

    /* To initialize SPI Communication configure following Register*/
    EPD_CS_PIN = 1;
    SSP1STAT=0x00;      /* Data change on rising edge of clk , BF=0*/
    SSP1CON1=0x20;      /* Slave mode,Serial enable, idle state high for clk */ 
    PIR1bits.SSP1IF=0;
    /* Disable the ADC channel which are on for multiplexed pin
    when used as an input */    
    ADCON0=0;           /* This is for de-multiplexed the SCL
                and SDI from analog pins*/
    ADCON1=0x0F;        /* This makes all pins as digital I/O */    
}

uint8_t SPI1_Exchange8bit(uint8_t data)
{
    // Clear the Write Collision flag, to allow writing
    SSP1CON1bits.WCOL = 0;

    SSP1BUF = data;

    while(SSP1STATbits.BF == SPI_RX_IN_PROGRESS)
    {
    }

    return (SSP1BUF);
}

uint8_t SPI1_Exchange8bitBuffer(uint8_t *dataIn, uint8_t bufLen, uint8_t *dataOut)
{
    uint8_t bytesWritten = 0;

    if(bufLen != 0)
    {
        if(dataIn != NULL)
        {
            while(bytesWritten < bufLen)
            {
                if(dataOut == NULL)
                {
                    SPI1_Exchange8bit(dataIn[bytesWritten]);
                }
                else
                {
                    dataOut[bytesWritten] = SPI1_Exchange8bit(dataIn[bytesWritten]);
                }

                bytesWritten++;
            }
        }
        else
        {
            if(dataOut != NULL)
            {
                while(bytesWritten < bufLen )
                {
                    temp = SPI1_Exchange8bit(SPI1_DUMMY_DATA);
                    
                    if(temp!=SPI1_DUMMY_DATA)
                    {
                        UART_Putch(temp);  //uart print
                        dataOut[bytesWritten] = temp;
                        bytesWritten++;
                    }
                    __delay_ms(5);
                }
            }
        }
    }

    return bytesWritten;
}

回答1:


Compare your logic analyser SCK and MOSI timing with that specified for the part at https://www.waveshare.com/wiki/1.54inch_e-Paper_Module:

Note that the MOSI (SDIN) state must be stable on the rising edge of SCK (SCLK). In your case the MOSI transitions are synchronous with the rising edge, and you have a clock transition before the MOSI has the correct D7=0 state. SPI timing is defined by both clock polarity and clock phase - giving four possible clock modes. Compare the Waveshare timing diagram with the 18F46K22 datasheet:

The Waveshare diagram suggests that either CKP=1/CKE=0, or CKP=0/CKE=1 may be used, you have:

SSP1STAT=0x00 ;
SSP1CON1=0x20 ;

Which is CKP=0/CKE=0 (which correlates with your logic analyser trace).

You need on of either:

SSP1STAT=0x20 ; // CKE=1
SSP1CON1=0x20 ; // CKP=0

or

SSP1STAT=0x00 ; // CKE=0
SSP1CON1=0x30 ; // CKP=1

Since idle state (controlled by CKP) of SCK is a don't-care, I suggest leaving that as-is and using the first suggestion - that seems more intuitive somehow.

Note also that your logic analyser must also be set to the same phase/polarity clock mode in order for its presentation of the data to be correct.



来源:https://stackoverflow.com/questions/65503631/issue-in-interfacing-spi-e-ink-display-with-pic-18f46k22

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!