我在 SPI 主模式下使用 PIC 18F46K22 与 Waveshare 1.54" ePaper Module 通信。 FOSC 频率为内部 8Mhz,SPI 配置为 FOSC/4。因此,当我检查逻辑分析仪上的输出时,某些输出位与预期不同。并且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;
}
答案 0 :(得分:2)
将您的逻辑分析仪 SCK 和 MOSI 时序与为 https://www.waveshare.com/wiki/1.54inch_e-Paper_Module 处的部件指定的时序进行比较:
请注意,MOSI (SDIN) 状态必须在 SCK (SCLK) 的上升沿保持稳定。在您的情况下,MOSI 转换与上升沿同步,并且在 MOSI 具有正确的 D7=0 状态之前,您有一个时钟转换。 SPI 时序由时钟极性和时钟相位定义 - 提供四种可能的时钟模式。将 Waveshare 时序图与 18F46K22 datasheet 进行比较:
Waveshare 图表明可以使用 CKP=1/CKE=0 或 CKP=0/CKE=1,您有:
SSP1STAT=0x00 ;
SSP1CON1=0x20 ;
哪个是 CKP=0/CKE=0(与您的逻辑分析仪轨迹相关)。
您需要:
SSP1STAT=0x20 ; // CKE=1
SSP1CON1=0x20 ; // CKP=0
或
SSP1STAT=0x00 ; // CKE=0
SSP1CON1=0x30 ; // CKP=1
由于 SCK 的空闲状态(由 CKP 控制)是无关紧要的,我建议保持原样并使用第一个建议 - 不知何故似乎更直观。
另请注意,您的逻辑分析仪还必须设置为相同的相位/极性时钟模式,才能正确显示数据。