华大HC32F460 SPI 驱动 ST7735S LCD显示器
前言:
STM32改HC32F460 换芯片后发现SPI硬件驱动不了屏了,这个小问题搞了很久,最后用逻辑分析仪,分析时序,然后解决了,解决方案就是SPI发送一个字节数据后加硬件延时.
CPU和LCD硬件连接
ST77735S 时序
4线SPI写入时序
GPIO模拟SPI逻辑分析仪时序数据 时序没有问题
第一次测量硬件SPI出出错的时序数据 时序错误
正常使用的硬件SPI时序
注意事项: SPI时钟用的是Pclk1时钟,我主频是200MHz Pclk1 是100MHz ,SPI 8分频 后是12.5MHz,
和下面代码中的发送后硬件延时有很大关系.
#define LCD_WD(dat) SPI_SendData8(SPI_UNIT, dat);delay(50);
#include "inc.h"
#define LCD_SPI1_ON
#define USE_HORIZONTAL 2
#if USE_HORIZONTAL==0||USE_HORIZONTAL==1
#define LCD_W 128
#define LCD_H 160
#else
#define LCD_W 160
#define LCD_H 128
#endif
#ifdef LCD_SPI1_OFF
#define SPI_LCD_SCL PortB,Pin02
#define SPI_LCD_SI PortB,Pin01
#define SPI_LCD_CS PortB,Pin10
#define SPI_LCD_A0 PortB,Pin00
#define SPI_LCD_RES PortA,Pin07
typedef enum
{
LCD_RES,
LCD_A0,
LCD_SI,
LCD_SCL,
LCD_CS,
LCD_ALL
}LCD_TYPE;
GPIO_STRUCT LCD_GPIO[LCD_ALL]=
{
SPI_LCD_RES,Pin_Mode_Out,0,
SPI_LCD_A0,Pin_Mode_Out,0,
SPI_LCD_SI,Pin_Mode_Out,0,
SPI_LCD_SCL,Pin_Mode_Out,0,
SPI_LCD_CS,Pin_Mode_Out,0
};
#define LCD_SCLK_Clr() PORT_ResetBits(SPI_LCD_SCL)
#define LCD_SCLK_Set() PORT_SetBits(SPI_LCD_SCL)
#define LCD_MOSI_Clr() PORT_ResetBits(SPI_LCD_SI)
#define LCD_MOSI_Set() PORT_SetBits(SPI_LCD_SI)
#define LCD_RES_Clr() PORT_ResetBits(SPI_LCD_RES)
#define LCD_RES_Set() PORT_SetBits(SPI_LCD_RES)
#define LCD_DC_Clr() PORT_ResetBits(SPI_LCD_A0)
#define LCD_DC_Set() PORT_SetBits(SPI_LCD_A0)
#define LCD_CS_Clr() PORT_ResetBits(SPI_LCD_CS)
#define LCD_CS_Set() PORT_SetBits(SPI_LCD_CS)
#endif
#ifdef LCD_SPI1_ON
#define SPI_LCD_SCL PortB,Pin02
#define SPI_LCD_SI PortB,Pin01
#define SPI_LCD_CS PortB,Pin10
#define SPI_LCD_A0 PortB,Pin00
#define SPI_LCD_RES PortA,Pin07
#define SPI_SCK_PORT (PortB)
#define SPI_SCK_PIN (Pin02)
#define SPI_SCK_FUNC (Func_Spi1_Sck)
#define SPI_MOSI_PORT (PortB)
#define SPI_MOSI_PIN (Pin01)
#define SPI_MOSI_FUNC (Func_Spi1_Mosi)
#define SPI_UNIT (M4_SPI1)
#define SPI_UNIT_CLOCK (PWC_FCG1_PERIPH_SPI1)
#define SPI_MASTER_MODE
typedef enum
{
LCD_RES,
LCD_A0,
LCD_CS,
LCD_ALL
}LCD_TYPE;
GPIO_STRUCT LCD_GPIO[LCD_ALL]=
{
SPI_LCD_RES,Pin_Mode_Out,0,
SPI_LCD_A0,Pin_Mode_Out,0,
SPI_LCD_CS,Pin_Mode_Out,0
};
#define LCD_RES_Clr() PORT_ResetBits(SPI_LCD_RES)
#define LCD_RES_Set() PORT_SetBits(SPI_LCD_RES)
#define LCD_DC_Clr() PORT_ResetBits(SPI_LCD_A0)
#define LCD_DC_Set() PORT_SetBits(SPI_LCD_A0)
#define LCD_CS_Clr() PORT_ResetBits(SPI_LCD_CS)
#define LCD_CS_Set() PORT_SetBits(SPI_LCD_CS)
static void Spi_Config(void)
{
stc_spi_init_t stcSpiInit;
MEM_ZERO_STRUCT(stcSpiInit);
PWC_Fcg1PeriphClockCmd(SPI_UNIT_CLOCK, Enable);
PORT_SetFunc(SPI_SCK_PORT, SPI_SCK_PIN, SPI_SCK_FUNC, Disable);
PORT_SetFunc(SPI_MOSI_PORT, SPI_MOSI_PIN, SPI_MOSI_FUNC, Disable);
stcSpiInit.enClkDiv = SpiClkDiv8;
stcSpiInit.enFrameNumber = SpiFrameNumber1;
stcSpiInit.enDataLength = SpiDataLengthBit8;
stcSpiInit.enFirstBitPosition = SpiFirstBitPositionMSB;
stcSpiInit.enSckPolarity = SpiSckIdleLevelHigh;
stcSpiInit.enSckPhase = SpiSckOddChangeEvenSample;
stcSpiInit.enReadBufferObject = SpiReadReceiverBuffer;
stcSpiInit.enWorkMode = SpiWorkMode3Line;
stcSpiInit.enTransMode = SpiTransFullDuplex;
stcSpiInit.enCommAutoSuspendEn = Disable;
stcSpiInit.enModeFaultErrorDetectEn = Disable;
stcSpiInit.enParitySelfDetectEn = Disable;
stcSpiInit.enParityEn = Disable;
stcSpiInit.enParity = SpiParityEven;
#ifdef SPI_MASTER_MODE
stcSpiInit.enMasterSlaveMode = SpiModeMaster;
stcSpiInit.stcDelayConfig.enSsSetupDelayOption = SpiSsSetupDelayCustomValue;
stcSpiInit.stcDelayConfig.enSsSetupDelayTime = SpiSsSetupDelaySck1;
stcSpiInit.stcDelayConfig.enSsHoldDelayOption = SpiSsHoldDelayCustomValue;
stcSpiInit.stcDelayConfig.enSsHoldDelayTime = SpiSsHoldDelaySck1;
stcSpiInit.stcDelayConfig.enSsIntervalTimeOption = SpiSsIntervalCustomValue;
stcSpiInit.stcDelayConfig.enSsIntervalTime = SpiSsIntervalSck6PlusPck2;
#endif
#ifdef SPI_SLAVE_MODE
stcSpiInit.enMasterSlaveMode = SpiModeSlave;
#endif
SPI_Init(SPI_UNIT, &stcSpiInit);
SPI_Cmd(SPI_UNIT, Enable);
}
#endif
#ifdef LCD_SPI1_OFF
void LCD_Writ_Bus(u8 dat)
{
u8 i;
LCD_CS_Clr();
for(i=0;i<8;i++)
{
LCD_SCLK_Clr();
if(dat&0x80)
{
LCD_MOSI_Set();
}
else
{
LCD_MOSI_Clr();
}
LCD_SCLK_Set();
dat<<=1;
}
LCD_CS_Set();
}
#endif
#ifdef LCD_SPI1_ON
void delay(int t)
{
while(t--);
}
#define LCD_WD(dat) SPI_SendData8(SPI_UNIT, dat);delay(50);
#endif
void LCD_WR_DATA8(u8 dat)
{
LCD_WD(dat);
}
void LCD_WR_DATA(u16 dat)
{
LCD_WD(dat>>8);
LCD_WD(dat);
}
void DEV_LCD_Init(void)
{
for(int i =LCD_RES;i <= LCD_CS;i++)
{
rxm_w(DEV_GPIO,&LCD_GPIO[i],NULL);
}
}
void LCD_WR_REG(u8 dat)
{
LCD_DC_Clr();
LCD_WR_DATA8(dat);
LCD_DC_Set();
}
void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2)
{
if(USE_HORIZONTAL==0)
{
LCD_WR_REG(0x2a);
LCD_WR_DATA(x1+2);
LCD_WR_DATA(x2+2);
LCD_WR_REG(0x2b);
LCD_WR_DATA(y1+1);
LCD_WR_DATA(y2+1);
LCD_WR_REG(0x2c);
}
else if(USE_HORIZONTAL==1)
{
LCD_WR_REG(0x2a);
LCD_WR_DATA(x1+2);
LCD_WR_DATA(x2+2);
LCD_WR_REG(0x2b);
LCD_WR_DATA(y1+1);
LCD_WR_DATA(y2+1);
LCD_WR_REG(0x2c);
}
else if(USE_HORIZONTAL==2)
{
LCD_WR_REG(0x2a);
LCD_WR_DATA(x1+1);
LCD_WR_DATA(x2+1);
LCD_WR_REG(0x2b);
LCD_WR_DATA(y1+2);
LCD_WR_DATA(y2+2);
LCD_WR_REG(0x2c);
}
else
{
LCD_WR_REG(0x2a);
LCD_WR_DATA(x1+1);
LCD_WR_DATA(x2+1);
LCD_WR_REG(0x2b);
LCD_WR_DATA(y1+2);
LCD_WR_DATA(y2+2);
LCD_WR_REG(0x2c);
}
}
void delay_ms(u16 time)
{
Ddl_Delay1ms(time);
}
void LCD_BLK_Set(void)
{
rxm_io(DEV_OUTPUT,BLED,1);
}
void LCD_Init(void)
{
DEV_LCD_Init();
#ifdef LCD_SPI1_ON
Spi_Config();
#endif
LCD_RES_Clr();
delay_ms(100);
LCD_RES_Set();
delay_ms(100);
LCD_BLK_Set();
delay_ms(100);
LCD_CS_Clr();
LCD_WR_REG(0x11);
delay_ms(120);
LCD_WR_REG(0xB1);
LCD_WR_DATA8(0x05);
LCD_WR_DATA8(0x3C);
LCD_WR_DATA8(0x3C);
LCD_WR_REG(0xB2);
LCD_WR_DATA8(0x05);
LCD_WR_DATA8(0x3C);
LCD_WR_DATA8(0x3C);
LCD_WR_REG(0xB3);
LCD_WR_DATA8(0x05);
LCD_WR_DATA8(0x3C);
LCD_WR_DATA8(0x3C);
LCD_WR_DATA8(0x05);
LCD_WR_DATA8(0x3C);
LCD_WR_DATA8(0x3C);
LCD_WR_REG(0xB4);
LCD_WR_DATA8(0x03);
LCD_WR_REG(0xC0);
LCD_WR_DATA8(0x28);
LCD_WR_DATA8(0x08);
LCD_WR_DATA8(0x04);
LCD_WR_REG(0xC1);
LCD_WR_DATA8(0XC0);
LCD_WR_REG(0xC2);
LCD_WR_DATA8(0x0D);
LCD_WR_DATA8(0x00);
LCD_WR_REG(0xC3);
LCD_WR_DATA8(0x8D);
LCD_WR_DATA8(0x2A);
LCD_WR_REG(0xC4);
LCD_WR_DATA8(0x8D);
LCD_WR_DATA8(0xEE);
LCD_WR_REG(0xC5);
LCD_WR_DATA8(0x1A);
LCD_WR_REG(0x36);
if(USE_HORIZONTAL==0)LCD_WR_DATA8(0x00);
else if(USE_HORIZONTAL==1)LCD_WR_DATA8(0xC0);
else if(USE_HORIZONTAL==2)LCD_WR_DATA8(0x70);
else LCD_WR_DATA8(0xA0);
LCD_WR_REG(0xE0);
LCD_WR_DATA8(0x04);
LCD_WR_DATA8(0x22);
LCD_WR_DATA8(0x07);
LCD_WR_DATA8(0x0A);
LCD_WR_DATA8(0x2E);
LCD_WR_DATA8(0x30);
LCD_WR_DATA8(0x25);
LCD_WR_DATA8(0x2A);
LCD_WR_DATA8(0x28);
LCD_WR_DATA8(0x26);
LCD_WR_DATA8(0x2E);
LCD_WR_DATA8(0x3A);
LCD_WR_DATA8(0x00);
LCD_WR_DATA8(0x01);
LCD_WR_DATA8(0x03);
LCD_WR_DATA8(0x13);
LCD_WR_REG(0xE1);
LCD_WR_DATA8(0x04);
LCD_WR_DATA8(0x16);
LCD_WR_DATA8(0x06);
LCD_WR_DATA8(0x0D);
LCD_WR_DATA8(0x2D);
LCD_WR_DATA8(0x26);
LCD_WR_DATA8(0x23);
LCD_WR_DATA8(0x27);
LCD_WR_DATA8(0x27);
LCD_WR_DATA8(0x25);
LCD_WR_DATA8(0x2D);
LCD_WR_DATA8(0x3B);
LCD_WR_DATA8(0x00);
LCD_WR_DATA8(0x01);
LCD_WR_DATA8(0x04);
LCD_WR_DATA8(0x13);
LCD_WR_REG(0x3A);
LCD_WR_DATA8(0x05);
LCD_WR_REG(0x29);
}
void LCD_DrawPoint(u16 x,u16 y,u16 color)
{
LCD_Address_Set(x,y,x,y);
LCD_WR_DATA(color);
}
int DEV_LCD_r1(int fd)
{
return 0;
}
int DEV_LCD_w1(int fd,int buf)
{
return 0;
}
int DEV_LCD_r(int fd,void *buf,int len)
{
return 0;
}
int DEV_LCD_w(int fd,void *buf,int len)
{
return 0;
}
int DEV_LCD_io(int fd,int mode,int value)
{
return 0;
}
_DRV{
LCD_Init();
};
总结: SPI硬件驱动LCD,充分了解时序,用逻辑分析仪分析数据,找出出错点在哪里
|