在HC32F460平台驱动 GC9306 三线制双通道SPI屏幕

说明

在HC32F460平台上以验证,通过模拟SPI的方式,驱动三线制双通道GC9306 LCD屏幕。(GC9306屏幕有多种规格有并口,3线制SPI,4线制SPI等多种规格)使用前一定要确认好自己屏幕的模式。若本文对你有有用,欢迎点赞收藏。

1. 三线制双通道 GC9306屏幕硬件介绍

引脚功能说明
1gnd电源地
2Led_A+背光+极
3VCC(2V8)电源+
4/Cs片选信号
5RSTB复位信号
6LSCKSCK SPI时钟信号
7LSDALSDA SPI数据通道1
8LSA0A0 SPI数据通道2
9LPTE帧同步
10LOVCC-
11Led_k背光 -极
12gnd电源地
13YD/NCNC
14XL/NCNC
15YU/NCNC
16XR/NCNC

2.与HC32F460芯片引脚连接

屏幕单片机
/cs->PB10
LSCK->PB13
LSDA->PB14
RSTB->PB12
A0->PB15

gc9306.h

#ifndef GC9306_H
#define GC9306_H

#define LCDCS(X)   (X? (M4_PORT->POSRB_f.POS10 = 1) : (M4_PORT->PORRB_f.POR10 = 1))
#define LCDSDA(X)   (X? (M4_PORT->POSRB_f.POS14 = 1) : (M4_PORT->PORRB_f.POR14 = 1))
#define RLCDSDA()   M4_PORT->PIDRB_f.PIN14 
#define LCDSCL(X)	 (X? (M4_PORT->POSRB_f.POS13 = 1) : (M4_PORT->PORRB_f.POR13 = 1))
#define LCDRESET(X)	 (X? (M4_PORT->POSRB_f.POS12 = 1) : (M4_PORT->PORRB_f.POR12 = 1))
#define RS(X) 		(X? (M4_PORT->POSRB_f.POS15 = 1) : (M4_PORT->PORRB_f.POR15 = 1))	//A0

 
 
//LCD的宽和高定义
#define LCD_Width 	240
#define LCD_Height 	320

void write_comm(INT16U command);
void write_data(INT16U datum);
void serial(INT8U send_data,INT8U comm_data);
void IC_code_init(void);
void read_ID(INT16U comm,INT8U count);
INT8U serial_read();
void writePixel(INT8U x_start, INT8U y_start, INT16U color);
void set_windows_x(INT16U x_strat_add,INT16U x_end_add);
void set_windows_y(INT16U y_strat_add,INT16U y_end_add);
void addres_set(INT16U strat_x,INT16U strat_y,INT16U end_x,INT16U end_y);
void grayotp(); //灰度测试

gc9306.C

#include "gc9306.h"



INT8U SRGB = 0x08;
INT16U driver_clar = 0;
INT8U scan = 0x80;
INT8U r_datum = 0;
INT8U r_data[128] = {0};

INT8U	move_y=0; //1 //计算Y轴地址偏离,1就是Y轴偏离1个像素点
INT8U	move_x=0; //2 //计算X轴地址偏离,1就是X轴偏离1个像素点


INT8U	win_starty=0x00;
INT8U	win_startx=0x00;
INT16U	addy=320;
INT16U	addx=240;
INT16U	win_endy = 0x013F;
INT16U	win_endx = 0xeF;

void delay(INT16U ms)
{
	for(INT16U jj = 0; jj < ms; jj++)
	{
		for(int ii = 0; ii <10 ; ii++);
	}
}

void write_comm(INT16U command)
{
    serial(command, 0);
}

void write_data(INT16U datum)
{
    serial(datum, 1);
}

void serial(INT8U send_data,INT8U comm_data)
{
	INT16U  serial1 = 0;
	
	LCDCS(0); 
	#if serial_SPI4
	RS=comm_data;
	#else
	LCDSDA(comm_data); delay(1);LCDSCL(0); delay(1); LCDSCL(1); delay(1);
	#endif
	serial1 = send_data;
	//serial1 = serial1<<8;
	delay(1);
	LCDSDA((serial1 & 0X80) >> 7);  LCDSCL(0);  delay(1);LCDSCL(1);delay(1);
	LCDSDA((serial1 & 0X40) >> 6);  LCDSCL(0);  delay(1);LCDSCL(1);delay(1);
	LCDSDA((serial1 & 0X20) >> 5);  LCDSCL(0);  delay(1);LCDSCL(1);delay(1);
	LCDSDA((serial1 & 0X10) >> 4);  LCDSCL(0);  delay(1);LCDSCL(1);delay(1);
	LCDSDA((serial1 & 0X08) >> 3);  LCDSCL(0);  delay(1); LCDSCL(1);delay(1);
	LCDSDA((serial1 & 0X04) >> 2);  LCDSCL(0);  delay(1);LCDSCL(1);delay(1);
	LCDSDA((serial1 & 0X02) >> 1);  LCDSCL(0);  delay(1);LCDSCL(1);delay(1);
	LCDSDA((serial1 & 0X01) >> 0);  LCDSCL(0);  delay(1);LCDSCL(1);delay(1);
	delay(1);
	//LCDSCL(0); delay(1);
	 LCDCS(1);delay(1);
}

void Dual_channel(INT8U H_data,INT8U L_data)
{	
	
	INT16U  serial1 = 0;
	INT16U  serial2 = 0;
	LCDCS(0);
	LCDSDA(1);
	//RS=1;
	LCDSCL(0);LCDSCL(1);delay(1);LCDSCL(0);delay(1);
	serial2=H_data;
	serial1=L_data;
	//serial2=serial2<<8;
	//serial1=serial1<<8;
		 
	LCDSDA((serial2 & 0X80) >> 7); RS((serial1 & 0X80) >> 7);LCDSCL(0); delay(1); LCDSCL(1); delay(1);
	LCDSDA((serial2 & 0X40) >> 6); RS((serial1 & 0X40) >> 6);LCDSCL(0); delay(1); LCDSCL(1); delay(1);
	LCDSDA((serial2 & 0X20) >> 5); RS((serial1 & 0X20) >> 5);LCDSCL(0); delay(1); LCDSCL(1); delay(1);
	LCDSDA((serial2 & 0X10) >> 4); RS((serial1 & 0X10) >> 4);LCDSCL(0); delay(1); LCDSCL(1); delay(1);
	LCDSDA((serial2 & 0X08) >> 3); RS((serial1 & 0X08) >> 3);LCDSCL(0); delay(1); LCDSCL(1); delay(1);
	LCDSDA((serial2 & 0X04) >> 2); RS((serial1 & 0X04) >> 2);LCDSCL(0); delay(1); LCDSCL(1); delay(1);
	LCDSDA((serial2 & 0X02) >> 1); RS((serial1 & 0X02) >> 1);LCDSCL(0); delay(1); LCDSCL(1); delay(1);
	LCDSDA((serial2 & 0X01) >> 0); RS((serial1 & 0X01) >> 0);LCDSCL(0); delay(1); LCDSCL(1); delay(1);
//	LCDSCL(0); delay(1);
	LCDCS(1); delay(1);
}


void read_send(INT8U send_data,INT8U comm_data)
{
	INT16U  serial1 = 0;
	
	LCDCS(0);
	#if serial_SPI4
	RS=comm_data;
	#else
	LCDSDA(comm_data);LCDSCL(0); delay(1);LCDSCL(1); delay(1);
	#endif
	serial1 = send_data;
	//serial1 = serial1<<8;
	LCDSDA((serial1 & 0X80) >> 7);  LCDSCL(0); delay(1);  LCDSCL(1);  delay(1);
	LCDSDA((serial1 & 0X40) >> 6);  LCDSCL(0); delay(1);  LCDSCL(1); delay(1);
	LCDSDA((serial1 & 0X20) >> 5);  LCDSCL(0); delay(1);  LCDSCL(1); delay(1);
	LCDSDA((serial1 & 0X10) >> 4);  LCDSCL(0); delay(1);  LCDSCL(1); delay(1);
	LCDSDA((serial1 & 0X08) >> 3);  LCDSCL(0); delay(1);  LCDSCL(1); delay(1);
	LCDSDA((serial1 & 0X04) >> 2);  LCDSCL(0); delay(1);  LCDSCL(1); delay(1);
	LCDSDA((serial1 & 0X02) >> 1);  LCDSCL(0); delay(1);  LCDSCL(1); delay(1);
	LCDSDA((serial1 & 0X01) >> 0);  LCDSCL(0); delay(1);  LCDSCL(1); delay(1);
//	LCDSCL(0); delay(1);
	LCDCS(0); delay(1);
}

void LCD_Init(void)
{
	LCDRESET(1);                //set the P4^1 as 1 for the LCDRESET();
	delay(20);           		// Delay 1ms
	LCDRESET(0);                 //set the P4^1 as 0 for the LCDRESET();
	delay(100);          // Delay 10ms
	LCDRESET(1);                //set the P4^1 as 1 for the LCDRESET();
	delay(300);         // Delay 200ms  

	 
    //************************Start initial sequence****************************//
		if(0)
		{
	//	CPT2.8
			write_comm(0xfe);
			write_comm(0xef);
			write_comm(0x36);
			write_data(scan|SRGB);
			write_comm(0x3a);
			write_data(0x05);
			//------end display control setting----//
			//------Power Control Registers Initial----//
			write_comm(0xa4);
			write_data(0x44);
			write_data(0x44);
			write_comm(0xa5);
			write_data(0x42);
			write_data(0x42);
			write_comm(0xaa);
			write_data(0x88);
			write_data(0x88);
			write_comm(0xe8);
			write_data(0x11);
			write_data(0x0b);
			write_comm(0xe3);
			write_data(0x01);
			write_data(0x10);
			write_comm(0xff);
			write_data(0x61);
			write_comm(0xAC);
			write_data(0x00);
			
			write_comm(0xae);
			write_data(0x2b);
			
			write_comm(0xad); 
			write_data(0x33);
			
			write_comm(0xaf); 
			write_data(0x55);
			
			write_comm(0xa6);
			write_data(0x2a);
			write_data(0x2a);
			write_comm(0xa7);
			write_data(0x2b);
			write_data(0x2b);
			write_comm(0xa8);
			write_data(0x18);
			write_data(0x18);
			write_comm(0xa9);
			write_data(0x2a);
			write_data(0x2a);
			//-----display window 240X320---------//
			write_comm(0x2a);
			write_data(0x00);
			write_data(0x00);
			write_data(0x00);
			write_data(0xef);
			write_comm(0x2b);
			write_data(0x00);
			write_data(0x00);
			write_data(0x01);
			write_data(0x3f);
			write_comm(0x2c);
			
			
			write_comm(0x35);
			write_data(0x00);
			
			
			write_comm(0x44);
			write_data(0x00);
			write_data(0x0a);
			write_comm(0xF0);
			write_data(0x02);
			write_data(0x00);
			write_data(0x00);
			write_data(0x01);
			write_data(0x04);
			write_data(0x09);
			
			write_comm(0xF1);
			write_data(0x01);
			write_data(0x03);
			write_data(0x00);
			write_data(0x04);
			write_data(0x0D);
			write_data(0x11);
			
			write_comm(0xF2);
			write_data(0x0B);
			write_data(0x07);
			write_data(0x32);
			write_data(0x04);
			write_data(0x04);
			write_data(0x45);
			
			write_comm(0xF3);
			write_data(0x13);
			write_data(0x0D);
			write_data(0x40);
			write_data(0x04);
			write_data(0x04);
			write_data(0x50);
			
			write_comm(0xF4);
			write_data(0x0C);
			write_data(0x18);
			write_data(0x18);
			write_data(0x1C);
			write_data(0x1E);
			write_data(0x0F);
			
			write_comm(0xF5);
			write_data(0x05);
			write_data(0x11);
			write_data(0x0E);
			write_data(0x1B);
			write_data(0x1B);
			write_data(0x0F);
			#if SPI_2DATA
			write_comm(0xE9);	//双通道
			write_data(0x00);
			#endif
			
			write_comm(0x11);
			delay(300);
			write_comm(0x29);
			write_comm(0x2c);
		}
		else
		{  
		//GC9306__BOE2.8
			write_comm(0xfe);
			write_comm(0xef);
			write_comm(0x36);
			write_data(scan|SRGB);
			write_comm(0x3a);
			write_data(0x05);
			//------end display control setting----//
			//------Power Control Registers Initial----//
			write_comm(0xa4);
			write_data(0x44);
			write_data(0x44);
			write_comm(0xa5);
			write_data(0x42);
			write_data(0x42);
			write_comm(0xaa);
			write_data(0x88);
			write_data(0x88);
			write_comm(0xe8);
			write_data(0x11);
			write_data(0x0b);
			write_comm(0xe3);
			write_data(0x01);
			write_data(0x10);//18
			
			write_comm(0xAC);
			write_data(0x00);
			
			write_comm(0xAd);
			write_data(0x33);
			
			write_comm(0xae);
			write_data(0x2b);
			
			write_comm(0xAf);
			write_data(0x55);
			
			write_comm(0xff);
			write_data(0x61);
			write_comm(0xa6);
			write_data(0x2a);
			write_data(0x2a);
			write_comm(0xa7);
			write_data(0x2b);
			write_data(0x2b);
			write_comm(0xa8);
			write_data(0x18);
			write_data(0x18);
			write_comm(0xa9);
			write_data(0x2a);
			write_data(0x2a);
			
			//------------gamma setting------------------//
			write_comm(0xF0);
			write_data(0x02);
			write_data(0x00);
			write_data(0x00);
			write_data(0x01);
			write_data(0x03);
			write_data(0x00);
			
			write_comm(0xF1);
			write_data(0x01);
			write_data(0x02);
			write_data(0x00);
			write_data(0x00);
			write_data(0x12);
			write_data(0x1D);
			
			write_comm(0xF2);
			write_data(0x06);
			write_data(0x06);
			write_data(0x24);
			write_data(0x04);
			write_data(0x04);
			write_data(0x35);
			
			write_comm(0xF3);
			write_data(0x18);
			write_data(0x0D);
			write_data(0x50);
			write_data(0x04);
			write_data(0x03);
			write_data(0x60);
			
			write_comm(0xF4);
			write_data(0x0B);
			write_data(0x17);
			write_data(0x15);
			write_data(0x08);
			write_data(0x08);
			write_data(0x0F);
			
			write_comm(0xF5);
			write_data(0x07);
			write_data(0x14);
			write_data(0x15);
			write_data(0x2E);
			write_data(0x30);
			write_data(0x0F);
			//--------end gamma setting--------------//
			#if SPI_2DATA
			write_comm(0xE9);
			write_data(0x08);
			#endif
			write_comm(0x11);
			delay(300);
			write_comm(0x29);
		}

		//RID=0;
		driver_clar=34;//GC9306的ID编码为 34
		return;
}

void read_ID(INT16U comm,INT8U count)
{
	INT8U count1;
	
#if serial_of_on
	read_send(comm, 0);
#else
		write_comm(comm);
#endif	

	LCDCS(0);
	//RS=1;
#if serial_of_on
	LCDSCL(1);//串口读ID脉冲,不用时请注解
	LCDSCL(0);
#else
	WRD=1;
	RD0=1;	
#endif
	r_datum=0;
	for(count1=0;count1<count;count1++)
	{
#if serial_of_on
         r_data[count1] = serial_read();//串口读ID不用时请注解
#else
		RD0=0;
		DBL=0xFF;
		RD0=1;
		r_data[count1]=DBL;

#endif
	}
	LCDCS(1);
	r_datum=1;
}

INT8U serial_read()
{
	INT8U serial_ID, a;
	serial_ID=0;
	r_datum=1;
	LCDSDA(1);
	r_datum=0;
	for(a=0;a<8;a++)
	{
		LCDSCL(0);
		__nop;
		LCDSCL(1);	
		__nop;	
		serial_ID |= RLCDSDA();//LCDSDA();;//SPI4_SDO;
		
		if(a<7)
		serial_ID<<=1;

	}
	return serial_ID;
	r_datum=1;
}

void writePixel(INT8U x_start, INT8U y_start, INT16U color)
{
	addres_set(x_start,y_start,x_start,y_start);
	write_comm(0x2C);
	#if data_six_BUS
	    write_data(color);
	#else
		#if SPI_2DATA 
		    Dual_channel(color>>8, color&0xff);
		#else
            write_data(color>>8);
            write_data(color&0xff);
		#endif
	#endif
}

void addres_set(INT16U strat_x,INT16U strat_y,INT16U end_x,INT16U end_y)
{
	set_windows_x(strat_x,end_x);
	set_windows_y(strat_y,end_y);
}

void set_windows_x(INT16U x_strat_add,INT16U x_end_add)
{
	x_strat_add+=move_x;
	x_end_add+=move_x;
	write_comm(0x2A);
	write_data(x_strat_add>>8);
	write_data(x_strat_add&0xFF);
	write_data(x_end_add>>8);
	write_data(x_end_add&0xFF);
}

void set_windows_y(INT16U y_strat_add,INT16U y_end_add)
{
	y_strat_add+=move_y;
	y_end_add+=move_y;
	write_comm(0x2B);
	write_data(y_strat_add>>8);
	write_data(y_strat_add&0xFF);
	write_data(y_end_add>>8);
	write_data(y_end_add&0xFF);
}

void display_sixten(INT16U RGB)
{
	INT8U hdata;
	
	#if SPI_2DATA
		hdata=RGB>>8;
		Dual_channel(hdata,(RGB&0xff));
	#else
		serial(RGB>>8,1);
		serial(RGB,1);
	#endif

}

void grayotp()	//灰度
{
	unsigned int up,DOWN,x,cal_x;
	INT8U g_up,g_dowy1,g_dowy2,g_dowx1,g_dowx2;
	cal_x=addx/16;

	g_up=addy/2;
	g_dowy1=(g_up/2)/2;//50
	g_dowy2=g_up/2;//60
	g_dowx1=((addx/2)/2)/2;//30
	g_dowx2=((addx/2)/2);//60
	

	set_windows_x(win_startx,win_endx);	//set windows to 128
	set_windows_y(win_starty,win_endy);	//set windows to 160
	write_comm(0x2C);

	for(up=0;up<g_up;up++)//1.44  64//1.77  80
	{
	  for(x=0;x<cal_x;x++)//128*160=8//160*128=10 //1.44不变
		 {
		  display_sixten(0x0000);  
		 }
	  for(x=0;x<cal_x;x++)
		 {
		 	display_sixten(0x1082); 
		 }
	  for(x=0;x<cal_x;x++)
		 {
		 	display_sixten(0x2104);
		 }
	  for(x=0;x<cal_x;x++)
		 {
		 	display_sixten(0x3186);
		 }
	  for(x=0;x<cal_x;x++)
		 {
		 	display_sixten(0x4208); 
		 }
	  for(x=0;x<cal_x;x++)
		 {
		 	display_sixten(0x528A); 
		 }
	  for(x=0;x<cal_x;x++)
		 {
		 	display_sixten(0x630C);  
		 }
	  for(x=0;x<cal_x;x++)
		 {
		 	display_sixten(0x738E); 
		 }
	  for(x=0;x<cal_x;x++)
		 {
		 	display_sixten(0x8C71); 
		 }
	  for(x=0;x<cal_x;x++)
		 {
		 	display_sixten(0x9CF3);
		 }
	  for(x=0;x<cal_x;x++)
		 {
		 	display_sixten(0xAD75); 
		 }
	  for(x=0;x<cal_x;x++)
		 {
		 	display_sixten(0xBDF7); 
		 }
	  for(x=0;x<cal_x;x++)
		 {
		 	display_sixten(0xCE79); 
		 }
	  for(x=0;x<cal_x;x++)
		 {
		 	display_sixten(0xDEFB); 
		 }
	  for(x=0;x<cal_x;x++)
		 {
		 	display_sixten(0xEF7D); 
		 }
	  for(x=0;x<cal_x;x++)
		 {
		 	display_sixten(0xFFFF);
		 }
	}
	/********************************************/
	cal_x=addx/2;
		for(DOWN=0;DOWN<g_dowy1;DOWN++)//y//1.44=21 //1.77=20//160*128=21
		{
			for(x=0;x<cal_x;x++)//x//128*160=64//160*128=80
			{
				display_sixten(0xFFFF); 
			}
			for(x=0;x<cal_x;x++)//x//128*160=64//160*128=80
			{
				display_sixten(0x0000);
			}
		}
	
	
		for(DOWN=0;DOWN<g_dowy2;DOWN++)//1.44=22//1.77=40//160*128=22
		{
	
			for(x=0;x<g_dowx1;x++)//1.77=16160*128=26
			{
				display_sixten(0xFFFF);
			}
	
			for(x=0;x<g_dowx2;x++)//1.77=32160*128=28
			{
				display_sixten(0xEF7D);
			}
	
			for(x=0;x<g_dowx1;x++)//1.77=16160*128=26
			{
				display_sixten(0xFFFF);
			}
	
			for(x=0;x<g_dowx1;x++)//1.77=16160*128=26
			{
				display_sixten(0x0000);
			}
			for(x=0;x<g_dowx2;x++)//1.77=32160*128=28
			{
				display_sixten(0x1082);
			}
			for(x=0;x<g_dowx1;x++)//1.77=16160*128=26
			{
				display_sixten(0x0000);
			}
		}
	
	
		for(DOWN=0;DOWN<g_dowy1;DOWN++) //1.44=21//1.77=20//160*128=21
		{
			for(x=0;x<cal_x;x++)//x//128*160=64//160*128=80
			{
				display_sixten(0xFFFF);
			}	
			for(x=0;x<cal_x;x++)//x//128*160=64//160*128=80
			{
				display_sixten(0x0000);
			}
		}
        
}

添加文件测试

在main函数中调用初始化程序后,再调用灰度测试函数。

void main()
{
    IC_code_init();

    while(1)
    {
        grayotp();
    }
}

写在最后

当然以上方式刷新屏幕的速度太慢了,我们下一篇将使用硬件SPi +DMA的方式进行刷新屏幕

  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HC32F460芯片上有4路串口,驱动使用了HC32官方的库函数来实现。一般的初始化流程如下代码所示: ```c stc_usart_uart_init_t init; memset(&init, 0, sizeof(init)); init.enClkMode = UsartIntClkCkNoOutput; init.enClkDiv = UsartClkDiv_1; init.enDataLength= UsartDataBits8; init.enDirection = UsartDataLsbFirst; init.enStopBit = UsartOneStopBit; init.enParity = (en_usart_parity_t)parity; init.enSampleMode= UsartSampleBit8; init.enDetectMode= UsartStartBitFallEdge; init.enHwFlow = UsartRtsEnable; USART_UART_Init(hw->uart, &init); USART_SetBaudrate(hw->uart, baudrate); USART_FuncCmd(hw->uart, UsartTx, Enable); USART_FuncCmd(hw->uart, UsartRx, Enable); USART_FuncCmd(hw->uart, UsartRxInt, Enable); ``` HC32F460还提供了一个模板工程,支持IAR和MDK开发环境,内涵ADC、GPIO、外部中断、通用GPIO、FLASH读写、串口、定时器和看门狗驱动二次封装。使用该模板工程能够方便地进行开发。 在实际项目中,如果接入了一个RS485设备,可能会出现无法正常接收数据的问题。故障表现是MCU不进入接收中断。经过检查硬件,没有发现问题,示波器能够看到引脚有波形过来。最后通过Keil的外设查看窗口,发现UART的寄存器中SR的FE标记被置为1。这表示接收到的数据帧存在错误。 如果你需要更详细的信息,可以参考国产MCU华大HC32F460系列芯片的软硬件开发资料、SDK包和应用设计笔记。这些资料包括HC32F460 EVB介绍、仿真器、最小开发工程模板、硬件Demo板参考原理图、编程工具、集成开发环境支持包、驱动库及样例等。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值