下面我将代码放在下面仅供参考,本人实测过哟,希望对你有用。
因为是驱动屏幕,所以是三线spi。
gc9306.c文件
#include "gc9306.H"
#include "stdlib.h"
#include "SysTick.h"
#include "font.h"
#include "system.h"
void LCD_Init(void)
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB1PeriphClockCmd( RCC_APB1Periph_SPI2, ENABLE );//SPI1时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOD,ENABLE);//使能PORTD,B时钟
//PORTD推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_14|GPIO_Pin_11; // //PORTD推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_SetBits(GPIOD,GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_14|GPIO_Pin_11);
//PORTB推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //13/14/15复用推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_13|GPIO_Pin_15|GPIO_Pin_14);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //片选PB12
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//背光控制管脚初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //PD13推挽输出 背光
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_SetBits(GPIOD,GPIO_Pin_13);//PD13 输出高
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPI
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //串行同步时钟的空闲状态为高电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式
SPI_Init(SPI2, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器
SPI_Cmd(SPI2, ENABLE); //使能SPI外设
//SPI2_ReadWriteByte(0xff);//启动传输
//----------------------------------------- Reset Sequence-------------------------------------------//
GPIO_SetBits (GPIOD,LCDRESET_PIN);
delay_ms(120);
GPIO_ResetBits (GPIOD,LCDRESET_PIN);
delay_ms(100); // delay 10ms This delay time is necessary
GPIO_SetBits (GPIOD,LCDRESET_PIN);
delay_ms(120);
//----------------------------------------end Reset Sequence---------------------------------------//
//----------------------------------display control setting----------------------------------------//
WriteComm(0xfe);
WriteComm(0xef);
WriteComm(0x36);
WriteData(0x48);//刷新方向控制
WriteComm(0x3a);
WriteData(0x05);
WriteComm(0xad);
WriteData(0x33);
WriteComm(0xaf);
WriteData(0x55);
WriteComm(0xae);
WriteData(0x2b);
//----------------------------------end display control setting--------------------------------//
//----------------------------------Power Control Registers Initial--------------------------------//
WriteComm(0xa4);
WriteData(0x44);
WriteData(0x44);
WriteComm(0xa5);
WriteData(0x42);
WriteData(0x42);
WriteComm(0xaa);
WriteData(0x88);
WriteData(0x88);
WriteComm(0xae);
WriteData(0x2b);
WriteComm(0xe8);
WriteData(0x11);
WriteData(0x0b);
WriteComm(0xe3);
WriteData(0x01);
WriteData(0x10);
WriteComm(0xff);
WriteData(0x61);
WriteComm(0xAC);
WriteData(0x00);
WriteComm(0xAf);
WriteData(0x67);
WriteComm(0xa6);
WriteData(0x2a);
WriteData(0x2a);
WriteComm(0xa7);
WriteData(0x2b);
WriteData(0x2b);
WriteComm(0xa8);
WriteData(0x18);
WriteData(0x18);
WriteComm(0xa9);
WriteData(0x2a);
WriteData(0x2a);
//---------------------------------display window 240X320-------------------------------------//
WriteComm(0x2a);
WriteData(0x00);
WriteData(0x00);
WriteData(0x00);
WriteData(0xef);
WriteComm(0x2b);
WriteData(0x00);
WriteData(0x00);
WriteData(0x01);
WriteData(0x3f);
WriteComm(0x2c);
//------------------------------------end display window ------------------------------------------//
//----------------------------------------gamma setting----------------------------------------------//
WriteComm(0xf0);
WriteData(0x02);
WriteData(0x00);
WriteData(0x00);
WriteData(0x1b);
WriteData(0x1f);
WriteData(0x0b);
WriteComm(0xf1);
WriteData(0x01);
WriteData(0x03);
WriteData(0x00);
WriteData(0x28);
WriteData(0x2b);
WriteData(0x0e);
WriteComm(0xf2);
WriteData(0x0b);
WriteData(0x08);
WriteData(0x3b);
WriteData(0x04);
WriteData(0x03);
WriteData(0x4c);
WriteComm(0xf3);
WriteData(0x0e);
WriteData(0x07);
WriteData(0x46);
WriteData(0x04);
WriteData(0x05);
WriteData(0x51);
WriteComm(0xf4);
WriteData(0x08);
WriteData(0x15);
WriteData(0x15);
WriteData(0x1f);
WriteData(0x22);
WriteData(0x0F);
WriteComm(0xf5);
WriteData(0x0b);
WriteData(0x13);
WriteData(0x11);
WriteData(0x1f);
WriteData(0x21);
WriteData(0x0F);
//------------------------------------end gamma setting------------------------------------------//
WriteComm(0x11);
delay_ms(120);
WriteComm(0x29);
WriteComm(0x2c);
lcd_address_set(0, 0, LCD_Width - 1, LCD_Height - 1);
SPI2_SetSpeed(SPI_BaudRatePrescaler_2);
WriteComm(0x29);
LCD_Set_Scroll_Area(0, 320, 240);
}
//SPI2速度设置函数
//SPI速度=fAPB1/分频系数
//@ref SPI_BaudRate_Prescaler:SPI_BaudRatePrescaler_2~SPI_BaudRatePrescaler_256
//fAPB1时钟一般为36Mhz:
void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler)
{
SPI2->CR1&=0XFFC7;//位3-5清零,用来设置波特率
SPI2->CR1|=SPI_BaudRatePrescaler; //设置SPI速度
SPI_Cmd(SPI2,ENABLE); //使能SPI2
}
//SPIx 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
u8 lcd_read_write_byte(u8 TxData)
{
u8 retry=0;
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
{
retry++;
if(retry>200)return 0;
}
SPI_I2S_SendData(SPI2, TxData); //通过外设SPIx发送一个数据
retry=0;
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位
{
retry++;
if(retry>200)return 0;
}
return SPI_I2S_ReceiveData(SPI2); //返回通过SPIx最近接收的数据
}
/**
* @brief 写命令到LCD
*
* @param cmd 需要发送的命令
*
* @return void
*/
void WriteComm(u16 cmd)
{
LCDCS=0;
LCDCX=0;
delay_us(1);
lcd_read_write_byte(cmd);
LCDCS=1;
}
/**
* @brief 写数据到LCD
*
* @param cmd 需要发送的数据
*
* @return void
*/
void WriteData(u16 data)
{
LCDCS=0;
LCDCX=1;
delay_us(1);
lcd_read_write_byte(data);
LCDCS=1;
}
/**
* @brief 写半个字的数据到LCD
*
* @param cmd 需要发送的数据
*
* @return void
*/
void lcd_write_halfword(const u16 da)
{
u8 data[2] = {0},i=0;
data[0] = da >> 8;
data[1] = da;
LCDCX=1;
LCDCS=0;
for(i=0;i<2;i++)
{
lcd_read_write_byte(data[i]);
}
LCDCS=1;
}
//显示函数
void LCD_DisplayOn(void)
{
WriteComm(0x29);
}
/**
* 设置数据操作区域
*
* @param x1,y1 起点坐标
* @param x2,y2 终点坐标
*
* @return void
*/
void lcd_address_set(u16 x1, u16 y1, u16 x2, u16 y2)
{
WriteComm(0x2a);//指定x操作区域
WriteData(x1 >> 8);
WriteData(x1 );
WriteData(x2 >> 8);
WriteData(x2 );
WriteComm(0x2b);//指定y操作区域
WriteData(y1 >> 8);
WriteData(y1 );
WriteData(y2 >> 8);
WriteData(y2 );
WriteComm(0x2C);
}
/**
* 以一种颜色清空LCD屏
*
* @param color 清屏颜色
*
* @return void
*/
void lcd_clear(u16 color)
{
unsigned int i;
u8 data[2] = {0,1};
data[0] = color >> 8;
data[1] = color;
lcd_address_set(0, 0, LCD_Width - 1, LCD_Height - 1);
LCDCX=1;
LCDCS=0;
for(i = 0; i < (LCD_Width*LCD_Height); i++)
{
lcd_read_write_byte(data[0]);
lcd_read_write_byte(data[1]);
}
LCDCS=0;
}
/**
* 画点函数
*
* @param x,y 画点坐标
*
* @return void
*/
void lcd_draw_point(u16 x, u16 y,u16 pointColor)
{
lcd_address_set(x, y, x, y);
lcd_write_halfword(pointColor);
}
//m^n函数
//返回值:m^n次方.
u32 LCD_Pow(u8 m,u8 n)
{
u32 result=1;
while(n--)result*=m;
return result;
}
//显示数字,高位为0,则不显示
//x,y :起点坐标
//len :数字的位数
//size:字体大小
//color:颜色
//num:数值(0~4294967295);
void lcd_show_num(u16 x,u16 y,u32 num,u8 len,u8 size,u16 pointColor,u16 backColor)
{
u8 t,temp;
u8 enshow=0;
for(t=0;t<len;t++)
{
temp=(num/LCD_Pow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
lcd_show_char(x+(size/2)*t,y,' ',size, pointColor,backColor);
continue;
}else enshow=1;
}
lcd_show_char(x+(size/2)*t,y,temp+'0',size,pointColor,backColor);
}
}
/*显示数字,高位为0,还是显示
x,y:起点坐标
num:数值(0~999999999);
len:长度(即要显示的位数)
size:字体大小
mode:
[7]:0,不填充;1,填充0.
[6:1]:保留
[0]:0,非叠加显示;1,叠加显示.*/
void LCD_Show_Num(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode,u16 pointColor)
{
u8 t,temp;
u8 enshow=0;
for(t=0;t<len;t++)
{
temp=(num/LCD_Pow(10,len-t-1))%10;
if(enshow==0&&t<(len-1))
{
if(temp==0)
{
if(mode&0X80)lcd_show_char(x+(size/2)*t,y,'0',size,mode&0X01,pointColor);
else lcd_show_char(x+(size/2)*t,y,' ',size,mode&0X01,pointColor);
continue;
}else enshow=1;
}
lcd_show_char(x+(size/2)*t,y,temp+'0',size,mode&0X01,pointColor);
}
}
/**
* @brief 显示一个ASCII码字符
*
* @param x,y 显示起始坐标
* @param chr 需要显示的字符
* @param size 字体大小(支持16/24/32号字体)
*
* @return void
*/
void lcd_show_char(u16 x, u16 y, char chr, u8 size,u16 pointColor,u16 backColor)
{
u8 temp, t1, t;
u8 csize; //得到字体一个字符对应点阵集所占的字节数
u16 colortemp;
u8 sta;
chr = chr - ' '; //得到偏移后的值(ASCII字库是从空格开始取模,所以-' '就是对应字符的字库)
if((x > (LCD_Width - size / 2)) || (y > (LCD_Height - size))) return;
lcd_address_set(x, y, x + size / 2 - 1, y + size - 1);//(x,y,x+8-1,y+16-1)
if((size == 16) || (size == 32) ) //16和32号字体
{
csize = (size / 8 + ((size % 8) ? 1 : 0)) * (size / 2);
for(t = 0; t < csize; t++)
{
if(size == 16)temp = ascii_1608[chr][t]; //调用1608字体
else if(size == 32)temp = ascii_3216[chr][t]; //调用3216字体
else return ; //没有的字库
for(t1 = 0; t1 < 8; t1++)
{
if(temp & 0x80) colortemp = pointColor;
else colortemp = backColor;
lcd_write_halfword(colortemp);
temp <<= 1;
}
}
}
else if (size == 12) //12号字体
{
csize = (size / 8 + ((size % 8) ? 1 : 0)) * (size / 2);
for(t = 0; t < csize; t++)
{
temp = ascii_1206[chr][t];
for(t1 = 0; t1 < 6; t1++)
{
if(temp & 0x80) colortemp = pointColor;
else colortemp = backColor;
lcd_write_halfword(colortemp);
temp <<= 1;
}
}
}
else if(size == 24) //24号字体
{
csize = (size * 16) / 8;
for(t = 0; t < csize; t++)
{
temp = ascii_2412[chr][t];
if(t % 2 == 0)sta = 8;
else sta = 4;
for(t1 = 0; t1 < sta; t1++)
{
if(temp & 0x80) colortemp = pointColor;
else colortemp = backColor;
lcd_write_halfword(colortemp);
temp <<= 1;
}
}
}
}
/**
* @brief 显示字符串
*
* @param x,y 起点坐标
* @param width 字符显示区域宽度
* @param height 字符显示区域高度
* @param size 字体大小
* @param p 字符串起始地址
*
* @return void
*/
void lcd_show_string(u16 x, u16 y, u16 width, u16 height, u8 size, char *p,u16 pointColor,u16 backColor)
{
u8 x0 = x;
width += x;
height += y;
while((*p <= '~') && (*p >= ' ')) //判断是不是非法字符!
{
if(x >= width)
{
x = x0;
y += size;
}
if(y >= height)break; //退出
lcd_show_char(x, y, *p, size,pointColor,backColor);
x += size/2;
p++;
}
}
//汉字
void lcd_Show_fontHZ(u16 x, u16 y, u8 *cn)
{
u8 i, j, wordNum;
u16 color;
u16 x0=x;
u16 y0=y;
while (*cn != '\0')
{
for (wordNum=0; wordNum<20; wordNum++)
{ //wordNum扫描字库的字数
if ((CnChar32x29[wordNum].Index[0]==*cn)
&&(CnChar32x29[wordNum].Index[1]==*(cn+1)))
{
for(i=0; i<116; i++)
{ //MSK的位数
color=CnChar32x29[wordNum].Msk[i];
for(j=0;j<8;j++)
{
if((color&0x80)==0x80)
{
lcd_draw_point(x,y,BLACK);//字体颜色
}
else
{
lcd_draw_point(x,y,WHITE);//背景颜色
}
color<<=1;
x++;
if((x-x0)==32)
{
x=x0;
y++;
if((y-y0)==29)
{
y=y0;
}
}
}//for(j=0;j<8;j++)结束
}
}
} //for (wordNum=0; wordNum<20; wordNum++)结束
cn += 2;
x += 32;
x0=x;
}
}
//滚动区域
int LCD_Set_Scroll_Area(uint16_t tfa, uint16_t vsa, uint16_t bta)
{
uint8_t data;
if (tfa + vsa + bta != 320)
{
return -1;
}
WriteComm(0x33);
data = tfa >> 8;
WriteData(data);
data = tfa;
WriteData(data);
data = vsa >> 8;
WriteData(data);
data = vsa;
WriteData(data);
data = bta >> 8;
WriteData(data);
data = bta;
WriteData(data);
return 0;
}
//
void LCD_Set_Scroll_Start_Address(uint16_t vsp)
{
WriteComm(0x37);
WriteData(vsp / 256);
WriteData(vsp % 256);
}
void fillScreen(void)
{
u8 i;
for(i = 0;i<4;i++)
{
lcd_clear(RED);
lcd_clear(BLUE);
}
}
gc9306.h文件
#ifndef _gc9306_H
#define _gc9306_H
#include "stdlib.h"
#include "system.h"
//PE口
#define LCDCS_PORT GPIOB //端口
#define LCDCS_PIN GPIO_Pin_12 //引脚
#define LCDCS_PORT_RCC RCC_APB2Periph_GPIOB //时钟
#define LCDSCLK_PORT GPIOB
#define LCDSCLK_PIN GPIO_Pin_13
#define LCDSCLK_PORT_RCC RCC_APB2Periph_GPIOB
#define LCDMISO_PORT GPIOB
#define LCDMISO_PIN GPIO_Pin_14
#define LCDMISO_PORT_RCC RCC_APB2Periph_GPIOB
#define LCDMOSI_PORT GPIOB
#define LCDMOSI_PIN GPIO_Pin_15
#define LCDMOSI_PORT_RCC RCC_APB2Periph_GPIOB
//PD口
#define LCDRESET_PORT GPIOD
#define LCDRESET_PIN GPIO_Pin_12
#define LCDRESET_PORT_RCC RCC_APB2Periph_GPIOD
#define LCDTE_PORT GPIOD
#define LCDTE_PIN GPIO_Pin_11
#define LCDTE_PORT_RCC RCC_APB2Periph_GPIOD
#define LCDCTRL_PORT GPIOD
#define LCDCTRL_PIN GPIO_Pin_13
#define LCDCTRL_PORT_RCC RCC_APB2Periph_GPIOD
#define LCDCX_PORT GPIOD
#define LCDCX_PIN GPIO_Pin_14
#define LCDCX_PORT_RCC RCC_APB2Periph_GPIOD
#define LCDCS PBout(12)//片选
#define LCDSCLK PBout(13)//时钟
#define LCDMOSI PBout(15)//主机输出
#define LCDTE PDout(11)//
#define LCDRESET PDout(12)//复位
#define LCDCX PDout(14)//显示数据、命令选择
#define LCDCTRL PDout(13)//背光
//LCD的宽和高定义
#define LCD_Width 240
#define LCD_Height 320
//颜色
#define WHITE 0xFFFF //白色
#define BLACK 0x0000
#define BLUE 0x001F
#define BRED 0XF81F
#define GRED 0XFFE0
#define GBLUE 0X07FF
#define RED 0xF800
#define MAGENTA 0xF81F
#define GREEN 0x07E0
#define CYAN 0x7FFF //
#define YELLOW 0xFFE0 //黄色
#define BROWN 0XBC40 //棕色
#define BRRED 0XFC07 //棕红色
#define GRAY 0X8430 //灰色
//GUI界面颜色
#define DARKBLUE 0X01CF //深蓝色
#define LIGHTBLUE 0X7D7C //浅蓝色
#define GRAYBLUE 0X5458 //灰蓝色
//以上三色为PANEL的颜色
#define LIGHTGREEN 0X841F //浅绿色
#define LIGHTGRAY 0XEF5B //浅灰色(PANNEL)
#define LGRAY 0XC618 //浅灰色(PANNEL),窗体背景色
#define LGRAYBLUE 0XA651 //浅灰蓝色(中间层颜色)
#define LBBLUE 0X2B12 //浅棕蓝色(选择条目的反色)
void LCD_Init(void);
void SPI2_SetSpeed(u8 SPI_BaudRatePrescaler);
u8 lcd_read_write_byte(u8 TxData);//SPI2总线读写一个字节
void LCD_DisplayOn(void);
void WriteComm(u16 cmd );
void WriteData(u16 data);
void lcd_write_halfword(const u16 da);
void lcd_address_set(u16 x1, u16 y1, u16 x2, u16 y2);
void lcd_clear(u16 color);
void lcd_draw_point(u16 x, u16 y,u16 pointColor);
void lcd_draw_circle(u16 x0, u16 y0, u8 r,u16 pointColor);
void lcd_show_num(u16 x,u16 y,u32 num,u8 len,u8 size,u16 pointColor,u16 backColor);//显示一个数字
void LCD_Show_Num(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode,u16 pointColor);//显示数字
void lcd_show_char(u16 x, u16 y, char chr, u8 size,u16 pointColor,u16 backColor);
void lcd_show_string(u16 x, u16 y, u16 width, u16 height, u8 size, char *p,u16 pointColor,u16 backColor);
void lcd_Show_fontHZ(u16 x, u16 y, u8 *cn);//中文
int LCD_Set_Scroll_Area(uint16_t tfa, uint16_t vsa, uint16_t bta);
void LCD_Set_Scroll_Start_Address(uint16_t vsp);
void fillScreen(void);
#endif
一起进步吧