STM32F103与主控 ILI9341的液晶屏TFT通过SPI1通讯问题

2019-07-21 07:14发布

最近在写一个使用SPI通讯的代码,MCU是原子的STM32F103芯片,LCD_TFT主控是ILI9341,想使用SPI的4线通讯。
我是个小白,遇到有以下几个问题,希望高手能帮忙分析一下
问题1、SPI 4线通讯引脚是CSX(片选)、D/CX(4线的寄存器或数据选择)、SCK(时钟信号)、SDI(MOSI数据输入)、SDO(MISO数据输出)
          这几个引脚都要连接吗?我想获取主控型号(9341)再写入数据,是不是就要接SDO这根线才能获取到主控?
问题2、在画原理图的时候 是不是显示屏的SDI接STM32的MOSI,SDO接STM32的MISO引脚(我认为是这个),
          还是显示屏的SDI接STM32的MISO,SDO接STM32的MOSI引脚?


问题3、我使用的是SPI 4线接口,要看ILI9341的4线时序图,但我在网上看到有人用普通IO口模拟SPI通讯,既然普通的IO口都可以根据时序图去写SPI 4线的函数,
          那就是说LCD的引脚不一定要接到STM32的SPI1接口上,那STM32的SPI1复合引脚又有什么意义呢?普通IO口模拟SPI和STM32的SPI有什么区别呢?






友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
17条回答
yyx112358
1楼-- · 2019-07-21 08:47
本帖最后由 yyx112358 于 2016-8-14 19:49 编辑
xia_yangchun 发表于 2016-8-14 17:17
hi,刚看了你的源码,有几个问题,关于写寄存器和写数据有点不明白
//写寄存器函数
//regval:寄存器 ...

这是作了一个速度上的优化。液晶屏的命令都是8位格式,而数据则是16位的。平常一般多数时间都是在写数据(至少99%吧)所以默认为16位,而需要发送命令的时候就先设定成8位发完命令再改成16位
SCK、MISO、MOSI都是STM32的硬件自动管理发送数据(向SPI的DR写数据,然后STM32自动生成相应时序,并且在发送完成后设定相应标志位,如果设置了,还会生成中断),源码里就是调用SPI_ReadWriteByte(SPI1,regval);
这是我参考的程序,没有优化过,不过比较好懂
STM32测试程序.rar (473.51 KB, 下载次数: 3667) 2016-8-14 19:49 上传 点击文件名下载附件

yyx112358
2楼-- · 2019-07-21 13:48
回答1:
如果SPI总线上只有9341一个设备,理论上可以直接接地(相当于一直选中),其他线必须都连接
回答2:
SPI的MISO是Master Input Slave Output的意思,所以MCU的MISO接9341的MISO(SDO,Slave Data Output),MOSI同理。不必像串口一样TX接RX。
回答3:
普通IO模拟当然可以。但是这样程序写起来麻烦容易出错,运行起来还占用CPU时间效率低速度慢,更没法用上DMA这样的高级功能。所以能用硬件特别是内置硬件解决就不要用软件,你看的软件模拟一般都是51这种没有硬件SPI的MCU的权宜之计。
这些东西你做多了就明白了,只要你能一直像这样仔细思考多提问题
yyx112358
3楼-- · 2019-07-21 15:23
加一个我写的例子,不过用DMA做了优化速度比较快
头文件
[mw_shl_code=c,true]#include "spi.h"
#include "delay.h"
#include "fonts.h"

#define        LCD_WIDTH                                (240)
#define        LCD_HEIGHT                        (320)

#define        LCD_DELAY(nms)        delay_ms(nms)
#define        RGB888_TO_RGB565(R,G,B)        (((R>>3)<<11)|((G>>2)<<5)|(B>>3))
//LCD_RS//dc  
#define SPILCD_RS_SET                  PAout(3)=1;//HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_SET)
#define SPILCD_RS_RESET          PAout(3)=0;//HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_RESET)
//LCD_RST
#define SPILCD_RST_SET          PAout(2)=1;// HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET)
#define SPILCD_RST_RESET         PAout(2)=0;//HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET)  
//LCD_CS  
#define SPILCD_CS_SET                 PAout(1)=1;//HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET)
#define SPILCD_CS_RESET          PAout(1)=0;//HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET)

typedef        enum
{
         LCD_SLEEP_IN                                                        =0x10,
         LCD_SLEEP_OUT            =0x11,   /* Sleep out register */
         LCD_GAMMA                =0x26,   /* Gamma register */
         LCD_DISPLAY_OFF          =0x28,   /* Display off register */
         LCD_DISPLAY_ON           =0x29,   /* Display on register */
         LCD_COLUMN_ADDR          =0x2A,   /* Colomn address register */
         LCD_PAGE_ADDR            =0x2B,   /* Page address register */
         LCD_GRAM                 =0x2C,   /* GRAM register */   
         LCD_MAC                  =0x36,   /* Memory Access Control register*/
         LCD_PIXEL_FORMAT         =0x3A,   /* Pixel Format register */
         LCD_WDB                  =0x51,   /* Write Brightness Display register */
         LCD_WCD                  =0x53,   /* Write Control Display register*/
         LCD_RGB_INTERFACE        =0xB0,   /* RGB Interface Signal Control */
         LCD_FRC                  =0xB1,   /* Frame Rate Control register */
         LCD_BPC                  =0xB5,   /* Blanking Porch Control register*/
         LCD_DFC                  =0xB6,   /* Display Function Control register*/
         LCD_POWER1               =0xC0,   /* Power Control 1 register */
         LCD_POWER2               =0xC1,   /* Power Control 2 register */
         LCD_VCOM1                =0xC5,   /* VCOM Control 1 register */
         LCD_VCOM2                =0xC7,   /* VCOM Control 2 register */
         LCD_POWERA               =0xCB,  /* Power control A register */
         LCD_POWERB               =0xCF,   /* Power control B register */
         LCD_PGAMMA               =0xE0,   /* Positive Gamma Correction register*/
         LCD_NGAMMA               =0xE1,   /* Negative Gamma Correction register*/
         LCD_DTCA                 =0xE8,   /* Driver timing control A */
         LCD_DTCB                 =0xEA,   /* Driver timing control B */
         LCD_POWER_SEQ            =0xED,   /* Power on sequence register */
         LCD_3GAMMA_EN            =0xF2,   /* 3 Gamma enable register */
         LCD_INTERFACE            =0xF6,   /* Interface control register */
         LCD_PRC                  =0xF7,   /* Pump ratio control register */
}LCD9341_CMD;

typedef        enum
{
        LCD_TX_MODE_ONE,
        LCD_TX_MODE_BLOCK,
}LCD_TX_MODE;

void LCD_Init(void);
void LCD_SetCursor(u16 Xpos, u16 Ypos);
void LCD_DisplayOn(void);                                                                                                        //开显示
void LCD_DisplayOff(void);                                                                                                        //关显示
void LCD_Clear(u16 Color);                                                                                                         //清屏
void LCD_SetCursor(u16 Xpos, u16 Ypos);                                                                                //设置光标
void LCD_Set_Window(u16 sx,u16 sy,u16 width,u16 height);
void LCD_SleepMode(FunctionalState NewState);

void LCD_DrawPoint(u16 x,u16 y);                                                                                        //画点
void LCD_FillRect(uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height,uint16_t color);
void LCD_DrawBitmap(u16 Xpos,u16 Ypos,u16 Width,u16 Height,u16 *bitmap);

void Draw_Circle(u16 x0,u16 y0,u8 r);                                                                                //画圆
void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2);                                                        //画线
void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2);                                                   //画矩形
void LCD_ShowChar(u16 x,u16 y,u8 c);                                                //显示一个字符
void LCD_ShowString(uint16_t xpos, uint16_t ypos,char string[]);[/mw_shl_code]

C文件
[mw_shl_code=c,true]#include        "LCD9341.h"

//LCD的画笔颜 {MOD}和背景 {MOD}          
u16 POINT_COLOR=RGB888_TO_RGB565(0x6F,0x00,0x8A);        //画笔颜 {MOD}
u16 BACK_COLOR=RGB888_TO_RGB565(0xD2,0xD2,0xD2);  //背景 {MOD}
sFONT        *LCD_CurrentFont=&Font16x24;
#define        LCD_CURRENTFONT_TABLE_SIZEOFBIT        (2*8)
#define        LCD_CURRENTFONT_TABLE_LENGTH        (LCD_CurrentFont->Width*LCD_CurrentFont->Height/LCD_CURRENTFONT_TABLE_SIZEOFBIT)

void LCD_WriteRAM_Prepare(void);

//写寄存器函数
//regval:寄存器值
void LCD_WR_REG(u8 regval)
{
        SPILCD_CS_RESET;  //LCD_CS=0
  SPILCD_RS_RESET;        //命令
        SPI1_SET_DATASIZE_8BIT;
        SPI_ReadWriteByte(SPI1,regval);
        SPI1_SET_DATASIZE_16BIT;
        SPILCD_CS_SET;  //LCD_CS=1                            
}
//写LCD数据
//data:要写入的值
void LCD_WR_DATA(u16 data)
{
        SPILCD_CS_RESET;  //LCD_CS=0
        SPILCD_RS_SET;                //数据
//        SPI_ReadWriteByte(SPI1,data>>8);
        SPI_ReadWriteByte(SPI1,data);
        SPILCD_CS_SET;  //LCD_CS=1               
}

void LCD_WR_DATA8(u8 data)   //写8位数据
{
        SPILCD_CS_RESET;  //LCD_CS=0
        SPILCD_RS_SET;                        //数据
        SPI1_SET_DATASIZE_8BIT;
        SPI_ReadWriteByte(SPI1,data);
        SPI1_SET_DATASIZE_16BIT;
        SPILCD_CS_SET;  //LCD_CS=1                            
}
//LCD的DMA发送
//注意写LCD_WriteRAM_Prepare();  
void        LCD_DMA_Tx(uint16_t *buffer,uint32_t len,LCD_TX_MODE mode)
{
        if(mode==LCD_TX_MODE_ONE)
                SPI1_DMA_SET_TX_ONE;

        SPILCD_CS_RESET;  //LCD_CS=0
        SPILCD_RS_SET;                //数据
       
        while(len>0xFFFF)//DMA最大0xFFFF Byte
        {
                SPI1_DMA_TxSingle(buffer,0xFFFF);
                if(mode==LCD_TX_MODE_BLOCK)
                        buffer+=0xFFFF/sizeof(buffer[0]);
                len-=0xFFFF;
        }
        SPI1_DMA_TxSingle(buffer,len);
       
        SPILCD_CS_SET;  //LCD_CS=1                       
       
        if(mode==LCD_TX_MODE_ONE)
                SPI1_DMA_SET_TX_BLOCK;
}
//初始化lcd
//PA5-SCK                        ||        PA6-MISO                ||        PA7-MOSI
//PA3-LCD_RS        ||        PA2-LCD_RST        ||        PA1-LCD_CS
void LCD_Init(void)
{                 
        GPIO_InitTypeDef  GPIO_InitStructure;
       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);         //使能端口时钟
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;                                 //端口配置
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;                 //IO口速度为50MHz
        GPIO_Init(GPIOA, &GPIO_InitStructure);                                         //根据设定参数初始化
        GPIO_SetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);                                                 //输出高
               
        SPI1_Init();
        SPI_SetSpeed(SPI1,SPI_BaudRatePrescaler_2);//如有显示问题最好改为4分频(建议最大频率为18MHz)
        SPI1_DMA_TxInit();
       
//        SPILCD_RST_RESET;
//         LCD_DELAY(50); // delay 20 ms
//  SPILCD_RST_SET;         
//         LCD_DELAY(50); // delay 20 ms

        SPILCD_RST_RESET ;        //LCD_RST=0         //SPI接口复位
        LCD_DELAY(20); // delay 20 ms
  SPILCD_RST_SET ;        //LCD_RST=1               
        LCD_DELAY(20);

        LCD_WR_REG(LCD_POWERA);  
        LCD_WR_DATA8(0x39);
        LCD_WR_DATA8(0x2C);
        LCD_WR_DATA8(0x00);
        LCD_WR_DATA8(0x34);
        LCD_WR_DATA8(0x02);

        LCD_WR_REG(LCD_POWERB);  
        LCD_WR_DATA8(0x00);
        LCD_WR_DATA8(0XC1);
        LCD_WR_DATA8(0X30);

        LCD_WR_REG(LCD_DTCA);  
        LCD_WR_DATA8(0x85);
        LCD_WR_DATA8(0x00);
        LCD_WR_DATA8(0x78);

        LCD_WR_REG(LCD_DTCB);  
        LCD_WR_DATA8(0x00);
        LCD_WR_DATA8(0x00);

        LCD_WR_REG(LCD_POWER_SEQ);  
        LCD_WR_DATA8(0x64);
        LCD_WR_DATA8(0x03);
        LCD_WR_DATA8(0X12);
        LCD_WR_DATA8(0X81);

        LCD_WR_REG(LCD_PRC);  
        LCD_WR_DATA8(0x20);

        LCD_WR_REG(LCD_POWER1);    //Power control
        LCD_WR_DATA8(0x23);   //VRH[5:0]

        LCD_WR_REG(LCD_POWER2);    //Power control
        LCD_WR_DATA8(0x10);   //SAP[2:0];BT[3:0]

        LCD_WR_REG(LCD_VCOM1);    //VCM control
        LCD_WR_DATA8(0x3e); //对比度调节
        LCD_WR_DATA8(0x28);

        LCD_WR_REG(LCD_VCOM2);    //VCM control2
        LCD_WR_DATA8(0x86);  //--

        LCD_WR_REG(LCD_MAC);    // Memory Access Control
        LCD_WR_DATA8(0x48); //C8           //48 68竖屏//28 E8 横屏

        LCD_WR_REG(LCD_PIXEL_FORMAT);   
        LCD_WR_DATA8(0x55);

        LCD_WR_REG(LCD_FRC);   
        LCD_WR_DATA8(0x00);  
        LCD_WR_DATA8(0x18);

        LCD_WR_REG(LCD_DFC);    // Display Function Control
        LCD_WR_DATA8(0x08);
        LCD_WR_DATA8(0x82);
        LCD_WR_DATA8(0x27);  

        LCD_WR_REG(LCD_3GAMMA_EN);    // 3Gamma Function Disable
        LCD_WR_DATA8(0x00);

        LCD_WR_REG(0x26);    //Gamma curve selected
        LCD_WR_DATA8(0x01);

        LCD_WR_REG(LCD_PGAMMA);    //Set Gamma
        LCD_WR_DATA8(0x0F);
        LCD_WR_DATA8(0x31);
        LCD_WR_DATA8(0x2B);
        LCD_WR_DATA8(0x0C);
        LCD_WR_DATA8(0x0E);
        LCD_WR_DATA8(0x08);
        LCD_WR_DATA8(0x4E);
        LCD_WR_DATA8(0xF1);
        LCD_WR_DATA8(0x37);
        LCD_WR_DATA8(0x07);
        LCD_WR_DATA8(0x10);
        LCD_WR_DATA8(0x03);
        LCD_WR_DATA8(0x0E);
        LCD_WR_DATA8(0x09);
        LCD_WR_DATA8(0x00);

        LCD_WR_REG(LCD_NGAMMA);    //Set Gamma
        LCD_WR_DATA8(0x00);
        LCD_WR_DATA8(0x0E);
        LCD_WR_DATA8(0x14);
        LCD_WR_DATA8(0x03);
        LCD_WR_DATA8(0x11);
        LCD_WR_DATA8(0x07);
        LCD_WR_DATA8(0x31);
        LCD_WR_DATA8(0xC1);
        LCD_WR_DATA8(0x48);
        LCD_WR_DATA8(0x08);
        LCD_WR_DATA8(0x0F);
        LCD_WR_DATA8(0x0C);
        LCD_WR_DATA8(0x31);
        LCD_WR_DATA8(0x36);
        LCD_WR_DATA8(0x0F);

        LCD_WR_REG(LCD_SLEEP_OUT);    //Exit Sleep
        LCD_DELAY(120);
       
        LCD_WR_REG(LCD_DISPLAY_ON);    //Display on
        LCD_WR_REG(LCD_GRAM);
        LCD_Clear(RGB888_TO_RGB565(0xE2,0xE2,0xE2));
       
}  
void        LCD_SleepMode(FunctionalState NewState)
{
        if(NewState==ENABLE)
        {
                LCD_WR_REG(LCD_SLEEP_IN);
                delay_ms(5);
        }
        else
        {
                LCD_WR_REG(LCD_SLEEP_OUT);
                delay_ms(120);
        }
}

//开始写GRAM
void LCD_WriteRAM_Prepare(void)
{
        LCD_WR_REG(LCD_GRAM);  
}         
//设置光标位置
//Xpos:横坐标
//Ypos:纵坐标
void LCD_SetCursor(u16 Xpos, u16 Ypos)
{
        LCD_WR_REG(LCD_COLUMN_ADDR);
        LCD_WR_DATA(Xpos);
        LCD_WR_REG(LCD_PAGE_ADDR);
        LCD_WR_DATA(Ypos);
}
void LCD_Set_Window(u16 Xpos,u16 Ypos,u16 width,u16 height)
{   
        width=Xpos+width-1;//末列地址
        height=Ypos+height-1;//末行地址
       
        LCD_WR_REG(0x2a);
        LCD_WR_DATA8(Xpos>>8);
        LCD_WR_DATA8(Xpos&0XFF);         
        LCD_WR_DATA8(width>>8);
        LCD_WR_DATA8(width&0XFF);  
        LCD_WR_REG(0x2b);
        LCD_WR_DATA8(Ypos>>8);
        LCD_WR_DATA8(Ypos&0XFF);
        LCD_WR_DATA8(height>>8);
        LCD_WR_DATA8(height&0XFF);
}

//画点
//x,y:坐标
//POINT_COLOR:此点的颜 {MOD}
void LCD_DrawPoint(u16 x,u16 y)
{
        LCD_SetCursor(x,y);                //设置光标位置
        LCD_WriteRAM_Prepare();        //开始写入GRAM
        LCD_WR_DATA(POINT_COLOR);
}
//在指定区域内填充单个颜 {MOD}
//(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为ex-sx+1)*(ey-sy+1)   
//color:要填充的颜 {MOD}
void LCD_FillRect(uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height,uint16_t color)
{         
/*        u16 i,j;
//        for(i=Ypos;i<Height;i++)
//        {                                                                          
//                 LCD_SetCursor(Xpos,i);                                      //设置光标位置
//                LCD_WriteRAM_Prepare();                             //开始写入GRAM         
//               
//                LCD_DMA_Tx(&color,Width,LCD_TX_MODE_ONE);
////                for(j=0;j<Width;j++)
////                        LCD_WR_DATA(color);        //设置光标位置          
//        }
*/
        LCD_Set_Window(Xpos,Ypos,Width,Height);
        LCD_WriteRAM_Prepare();
        LCD_DMA_Tx(&color,Width*Height*sizeof(uint16_t),LCD_TX_MODE_ONE);
}
//清屏函数
//color:要清屏的填充 {MOD}
void LCD_Clear(u16 color)
{
        LCD_FillRect(0,0,LCD_WIDTH,LCD_HEIGHT,color);
}  
//在指定区域内填充指定颜 {MOD}块       
//【注:图片最好是大端模式,因SPI发送是MSB在前】
//(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为ex-sx+1)*(ey-sy+1)   
//color:要填充的颜 {MOD}
void LCD_DrawBitmap(u16 Xpos,u16 Ypos,u16 Width,u16 Height,u16 *bitmap)
{
        u32 i=0;
        LCD_Set_Window(Xpos,Ypos,Width,Height);
        LCD_WriteRAM_Prepare();
        SPILCD_CS_RESET;  //LCD_CS=0
        SPILCD_RS_SET;//数据
        SPI1_DMA_TxSingle(bitmap,Width*Height);
        SPILCD_CS_SET;
//        LCD_DMA_Tx(bitmap,Width*Height*2,LCD_TX_MODE_BLOCK);
}  
//画线
//x1,y1:起点坐标
//x2,y2:终点坐标  
void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2)
{
        u16 t;
        int xerr=0,yerr=0,delta_x,delta_y,distance;
        int incx,incy,uRow,uCol;
        delta_x=x2-x1; //计算坐标增量
        delta_y=y2-y1;
        uRow=x1;
        uCol=y1;
        if(delta_x>0)incx=1; //设置单步方向
        else if(delta_x==0)incx=0;//垂直线
        else {incx=-1;delta_x=-delta_x;}
        if(delta_y>0)incy=1;
        else if(delta_y==0)incy=0;//水平线
        else{incy=-1;delta_y=-delta_y;}
        if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
        else distance=delta_y;
        for(t=0;t<=distance+1;t++ )//画线输出
        {  
                LCD_DrawPoint(uRow,uCol);//画点
                xerr+=delta_x ;
                yerr+=delta_y ;
                if(xerr>distance)
                {
                        xerr-=distance;
                        uRow+=incx;
                }
                if(yerr>distance)
                {
                        yerr-=distance;
                        uCol+=incy;
                }
        }  
}   
//画矩形          
//(x1,y1),(x2,y2):矩形的对角坐标
void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2)
{
        LCD_DrawLine(x1,y1,x2,y1);
        LCD_DrawLine(x1,y1,x1,y2);
        LCD_DrawLine(x1,y2,x2,y2);
        LCD_DrawLine(x2,y1,x2,y2);
}
//在指定位置画一个指定大小的圆
//(x,y):中心点
//r    :半径
void Draw_Circle(u16 x0,u16 y0,u8 r)
{
        int a,b;
        int di;
        a=0;b=r;          
        di=3-(r<<1);             //判断下个点位置的标志
        while(a<=b)
        {
                LCD_DrawPoint(x0+a,y0-b);             //5
                LCD_DrawPoint(x0+b,y0-a);             //0           
                LCD_DrawPoint(x0+b,y0+a);             //4               
                LCD_DrawPoint(x0+a,y0+b);             //6
                LCD_DrawPoint(x0-a,y0+b);             //1      
                LCD_DrawPoint(x0-b,y0+a);            
                LCD_DrawPoint(x0-a,y0-b);             //2            
                  LCD_DrawPoint(x0-b,y0-a);             //7                     
                a++;
                //使用Bresenham算法画圆     
                if(di<0)di +=4*a+6;          
                else
                {
                        di+=10+4*(a-b);   
                        b--;
                }                                                     
        }
}        

//在指定位置(x,y)显示一个字符c
//字符空白区域覆盖为背景 {MOD}
void LCD_ShowChar(u16 Xpos,u16 Ypos,u8 c)
{
        uint16_t        i=0;
        const uint16_t *tblc=LCD_CurrentFont->table+(c-0x20)*LCD_CURRENTFONT_TABLE_LENGTH;
        LCD_Set_Window(Xpos,Ypos,LCD_CurrentFont->Width,LCD_CurrentFont->Height);
        LCD_WriteRAM_Prepare();
        SPILCD_CS_RESET;  //LCD_CS=0
        SPILCD_RS_SET;                //数据
       
        for(i=0;i<LCD_CURRENTFONT_TABLE_LENGTH;i++)
        {
                uint16_t        cnt;
                for(cnt=0;cnt<LCD_CURRENTFONT_TABLE_SIZEOFBIT;cnt++)
                {
                        if(        (tblc&(1<<cnt))        ==0)//一般说来字符中空白区域更多
                                SPI_ReadWriteByte(SPI1,BACK_COLOR);
                        else
                                SPI_ReadWriteByte(SPI1,POINT_COLOR);
                }
        }
        SPILCD_CS_SET;
}   
//显示字符串
//写到屏幕最右侧自动换行
void                 LCD_ShowString(uint16_t xpos, uint16_t ypos,char string[])
{
        u16 i=0,xoffset=LCD_CurrentFont->Width,yoffset=LCD_CurrentFont->Height,x=xpos,y=ypos;
       
        while(string!=''&&string!=0)
        {
                if(string!=' ')
                        LCD_ShowChar(x,y,string);
                if(        (x+xoffset<LCD_WIDTH)&&(string!=' ')        )
                        x+=xoffset;
                else
                {
                        x=xpos;
                        if(y+yoffset<LCD_HEIGHT)
                                y+=yoffset;
                        else
                                break;
                }
                i++;
        }
}[/mw_shl_code]
xia_yangchun
4楼-- · 2019-07-21 18:58
 精彩回答 2  元偷偷看……
xia_yangchun
5楼-- · 2019-07-21 21:16
本帖最后由 xia_yangchun 于 2016-8-14 17:19 编辑
yyx112358 发表于 2016-8-14 16:08
加一个我写的例子,不过用DMA做了优化速度比较快
头文件
[mw_shl_code=c,true]#include "spi.h"


hi,刚看了你的源码,有几个问题,关于写寄存器和写数据有点不明白
//写寄存器函数
//regval:寄存器值
void LCD_WR_REG(u8 regval)
{
    SPILCD_CS_RESET;  //LCD_CS=0
  SPILCD_RS_RESET;  //命令
    SPI1_SET_DATASIZE_8BIT;             //该处不是很明白,为什么要设置8bit???
    SPI_ReadWriteByte(SPI1,regval);
    SPI1_SET_DATASIZE_16BIT;           //该处不是很明白,为什么又要设置16bit???
    SPILCD_CS_SET;  //LCD_CS=1           
}

还有一点就是我看了一下,你这个应该是先片选CS,然后在选命令或数据,然后那个8bit没看懂,然后就使用SPI发出命令(同时应该也在读取)然后就是16bit(这个没看懂),然后就把片选至”1“了,我看了一下我上面附的4线时序图,好像你这个只用到了RS(也就是DCX)和CS两个引脚,SCK和SDI、SDO都没用上???不是很懂?请教了,谢谢!
alanvership
6楼-- · 2019-07-22 03:06
yyx112358 发表于 2016-8-14 10:20
这是作了一个速度上的优化。液晶屏的命令都是8位格式,而数据则是16位的。平常一般多数时间都是在写数据 ...

你好,我下载了你的程序,按照程序里面的代码接线,顺序如下:
T_IRQC10
T_DOC2
T_DINC3
T_CSC0
T_CLKC1
SDO(MISO)A6
LED:3.3V
SCKA5
SDI(MOSI)A7
D/CC4
RESETB0
CS:PA4
GND:GND
VCC:3.3V
开发板是战舰的,但是接上去后屏幕是灰 {MOD}的啥也不显示。请问是什么问题

一周热门 更多>