金牌会员
 
- 积分
- 1383
- 金钱
- 1383
- 注册时间
- 2015-2-3
- 在线时间
- 197 小时
|
发表于 2016-8-14 16:08:39
|
显示全部楼层
加一个我写的例子,不过用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的画笔颜色和背景色
u16 POINT_COLOR=RGB888_TO_RGB565(0x6F,0x00,0x8A); //画笔颜色
u16 BACK_COLOR=RGB888_TO_RGB565(0xD2,0xD2,0xD2); //背景色
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:此点的颜色
void LCD_DrawPoint(u16 x,u16 y)
{
LCD_SetCursor(x,y); //设置光标位置
LCD_WriteRAM_Prepare(); //开始写入GRAM
LCD_WR_DATA(POINT_COLOR);
}
//在指定区域内填充单个颜色
//(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为 ex-sx+1)*(ey-sy+1)
//color:要填充的颜色
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:要清屏的填充色
void LCD_Clear(u16 color)
{
LCD_FillRect(0,0,LCD_WIDTH,LCD_HEIGHT,color);
}
//在指定区域内填充指定颜色块
//【注:图片最好是大端模式,因SPI发送是MSB在前】
//(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为 ex-sx+1)*(ey-sy+1)
//color:要填充的颜色
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
//字符空白区域覆盖为背景色
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!='\0'&&string!=0)
{
if(string!='\n')
LCD_ShowChar(x,y,string);
if( (x+xoffset<LCD_WIDTH)&&(string!='\n') )
x+=xoffset;
else
{
x=xpos;
if(y+yoffset<LCD_HEIGHT)
y+=yoffset;
else
break;
}
i++;
}
}[/mw_shl_code] |
|