Linux-Ubuntu之RGBLCD显示屏

Linux-Ubuntu之RGBLCD显示屏

一,实现原理

采用的是4.3寸 800×480显示屏,即每行有800个像素点,每列有480个像素点,外接时钟信号,控制刷新频率,每次刷新时,每一帧信号采用'Z'字型的方式,依次从第一行,第二行...往下面去刷,正常每个像素点由RGB三个通道来控制颜色,RGB三通道每一个通道用一个字节,这个显示屏采用ARGB,A是一个透明通道,因此颜色方面采用四个字节控制。

**显示原理:**电子枪打开,从左往右扫描,显示完一行后,电子枪关闭,水平同步信号HSYNC会打开,从电子枪关闭到水平同步信号打开的时间间隔叫HFP,然后电子枪移动到屏幕左边下一行,HSYNC结束到电子枪打开这个时间间隔是HBP,VSYNC是帧同步信号,当显示完整个屏幕即一帧后,电子枪关闭到VSYNC信号打开的时间间隔是VFP,等VSYNC关闭到电子枪重新从左上角打开的时间间隔是VBP。
时钟 :显示一帧图像用的时钟数: (VSPW+VBP+LINE+VFP) * (HSPW + HBP + HOZVAL + HFP)=(3+32+480+13)(48+88+800+40)=515328,显示60帧:515328 60=30919680≈31MHZ,因此时钟选择31MHZ即可满足该屏幕刷新。采用PPL5给LCD作为原始时钟源,然后经过选择器和分频器设置为31MHZ即可。

显存 :一个像素颜色用四个字节,800480 3=153600个字节约等于1.5MB内存。

最后是对寄存器进行配置:①初始化LCD使用的IO,设置复用功能和电器属性,对不同屏幕设置不同时钟。②设置CCM相应寄存器,尤其是关于扫描方面寄存器配置。③设置初始化地址,LCD的CTRL,CTRL1,CUR_BUF,TRANSFER_COUNT,NEXT_BUF寄存器。④编写响应的显示函数,清屏等。

二,驱动代码

需要先读这个LCD的ID,ID能说明长和宽,即对应的像素有多少,才能对屏幕进行设置。

c 复制代码
/*LCD.h*/
#ifndef _DSP_LCD_H
#define _DSP_LCD_H
#include "imx6ul.h"
/*屏幕ID*/
#define  ATK4342 0x4342 
#define  ATK4384 0x4384 //4.3寸 800×480
#define  ATK7084 0x7084 //7寸 800×480
#define  ATK7016 0x7016 //7寸 1024×600
#define  ATK1018 0x1018 //10.1寸 1280×800

/*显存首地址*/
#define SHOW_ADRESS  (0x89000000)
/*颜色*/
#define LCD_BLUE		  0x000000FF
#define LCD_GREEN		  0x0000FF00
#define LCD_RED 		  0x00FF0000
#define LCD_CYAN		  0x0000FFFF
#define LCD_MAGENTA 	  0x00FF00FF
#define LCD_YELLOW		  0x00FFFF00
#define LCD_LIGHTBLUE	  0x008080FF
#define LCD_LIGHTGREEN	  0x0080FF80
#define LCD_LIGHTRED	  0x00FF8080
#define LCD_LIGHTCYAN	  0x0080FFFF
#define LCD_LIGHTMAGENTA  0x00FF80FF
#define LCD_LIGHTYELLOW   0x00FFFF80
#define LCD_DARKBLUE	  0x00000080
#define LCD_DARKGREEN	  0x00008000
#define LCD_DARKRED 	  0x00800000
#define LCD_DARKCYAN	  0x00008080
#define LCD_DARKMAGENTA   0x00800080
#define LCD_DARKYELLOW	  0x00808000
#define LCD_WHITE		  0x00FFFFFF
#define LCD_LIGHTGRAY	  0x00D3D3D3
#define LCD_GRAY		  0x00808080
#define LCD_DARKGRAY	  0x00404040
#define LCD_BLACK		  0x00000000
#define LCD_BROWN		  0x00A52A2A
#define LCD_ORANGE		  0x00FFA500
#define LCD_TRANSPARENT   0x00000000
/**LCD屏幕信息结构体*/
 struct tflcd_typedef{
    unsigned short height;//屏幕高度
    unsigned short width;//屏幕宽度
    unsigned char pixsize;//每个像素占据第字节数字
    unsigned short vspw;
    unsigned short vbpd;
    unsigned short vfpd;
    unsigned short hspw;
    unsigned short hbpd;
    unsigned short hfpd;
    unsigned int framebuffer;//屏幕显存地址
    unsigned int forecolor;//前景色
    unsigned int backcolor;//背景色
};
extern struct tflcd_typedef tftlcd_dev;
void lcd_init(void);//初始化
unsigned short lcd_read_panelid(void);//读取屏幕ID
void lcdgpio_init(void);//背光设置
void lcd_reset(void);/*复位*/
void lcd_noreset(void);/*停止复位*/
void lcd_enable(void);/*使能LCD控制器*/
void lcd_clock_init(unsigned char loopDiv,unsigned char prediv,unsigned char div);//根据不同屏幕配置不同时钟配置
inline void lcd_drawpoint(unsigned short x,unsigned short y,unsigned int color);//画点
inline unsigned int lcd_readpoint(unsigned int x,unsigned int y);//读点
void lcd_clear(unsigned int color);//清屏
void lcd_fill(unsigned short x0,unsigned short y0,unsigned short x1,unsigned short y1,unsigned int color);
#endif 



/*LCD.c*/
#include "dcp_lcd.h"
#include "dsp_gpio.h"
#include "dsp_delay.h"
#include "stdio.h"
/*屏幕参数结构体变量*/
struct tflcd_typedef tftlcd_dev;
/*LCD初始化*/
 void lcd_init(void)
 {
    unsigned short lcd_ID=0;
    lcd_ID = lcd_read_panelid();
    printf("屏幕ID为:%x \r\n",lcd_ID);
    /*初始化ID*/
    lcdgpio_init();
    lcd_reset();
    delay(10);
    lcd_noreset();

    /*根据不同屏幕设置*/
    if(lcd_ID == ATK4384)
    {   
        tftlcd_dev.height = 480;
        tftlcd_dev.width = 800; 
        tftlcd_dev.vspw = 3;
        tftlcd_dev.vbpd = 32;
        tftlcd_dev.vfpd = 13;
        tftlcd_dev.hspw = 48;
        tftlcd_dev.hbpd = 88;
        tftlcd_dev.hfpd = 40;
        lcd_clock_init(,4,8);//时钟频率 31.5MHZ
    }else if(lcd_ID == ATK4342)
    {   
        tftlcd_dev.height = 272;
        tftlcd_dev.width = 480; 
        tftlcd_dev.vspw = 1;
        tftlcd_dev.vbpd = 8;
        tftlcd_dev.vfpd = 8;
        tftlcd_dev.hspw = 1;
        tftlcd_dev.hbpd = 40;
        tftlcd_dev.hfpd = 5;
        lcd_clock_init(27,8,8);//时钟频率 10.1MHZ    
    }
    tftlcd_dev.pixsize = 4;
    tftlcd_dev.framebuffer = SHOW_ADRESS;
    tftlcd_dev.forecolor = LCD_WHITE;
    tftlcd_dev.backcolor = LCD_BLACK;

    /*配置LCDIF控制器接口*/
    LCDIF->CTRL = 0;
    LCDIF->CTRL |= (1<<5) |(3<<8)|(3<<10)|(1<<17)|(1<<19);

    LCDIF->CTRL1 = 0;
    LCDIF->CTRL1 |=(7<<16);

    LCDIF->TRANSFER_COUNT = 0;
    LCDIF->TRANSFER_COUNT =(tftlcd_dev.height<<16)|(tftlcd_dev.width<<0);

    LCDIF->VDCTRL0 =0;
    LCDIF->VDCTRL0 = (tftlcd_dev.vspw<<0)|(1<<20)|(1<<21)|
                    (1<<24)|(0<<25)|(0<<26)|(0<<27)|(1<<28)|(0<<29);

    LCDIF->VDCTRL1 = tftlcd_dev.vspw+tftlcd_dev.vbpd+tftlcd_dev.height+tftlcd_dev.vfpd;//一帧画面的总时间
    LCDIF->VDCTRL2 = (tftlcd_dev.hspw+tftlcd_dev.hbpd+tftlcd_dev.width+tftlcd_dev.hfpd )|(tftlcd_dev.hspw<<18);
    LCDIF->VDCTRL3 = (tftlcd_dev.vspw+tftlcd_dev.vbpd)|((tftlcd_dev.hspw+tftlcd_dev.hbpd)<<16);
    LCDIF->VDCTRL4 = (tftlcd_dev.width)|(1<<18);

    LCDIF->CUR_BUF = (unsigned int)tftlcd_dev.framebuffer;//放起始地址
    LCDIF->NEXT_BUF = (unsigned int)tftlcd_dev.framebuffer;
    lcd_enable();
    delay(20);
    lcd_clear(LCD_WHITE);

 }
 /*IO初始化*/
void lcdgpio_init(void)
{
	/* 1、IO初始化复用 */
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA00_LCDIF_DATA00,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA01_LCDIF_DATA01,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA02_LCDIF_DATA02,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA03_LCDIF_DATA03,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA04_LCDIF_DATA04,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA05_LCDIF_DATA05,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA06_LCDIF_DATA06,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA07_LCDIF_DATA07,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA08_LCDIF_DATA08,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA09_LCDIF_DATA09,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA10_LCDIF_DATA10,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA11_LCDIF_DATA11,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA12_LCDIF_DATA12,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA13_LCDIF_DATA13,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA14_LCDIF_DATA14,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA15_LCDIF_DATA15,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA16_LCDIF_DATA16,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA17_LCDIF_DATA17,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA18_LCDIF_DATA18,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA19_LCDIF_DATA19,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA20_LCDIF_DATA20,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA21_LCDIF_DATA21,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA22_LCDIF_DATA22,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_DATA23_LCDIF_DATA23,0);

	IOMUXC_SetPinMux(IOMUXC_LCD_CLK_LCDIF_CLK,0);	
	IOMUXC_SetPinMux(IOMUXC_LCD_ENABLE_LCDIF_ENABLE,0);	
	IOMUXC_SetPinMux(IOMUXC_LCD_HSYNC_LCDIF_HSYNC,0);
	IOMUXC_SetPinMux(IOMUXC_LCD_VSYNC_LCDIF_VSYNC,0);

    /*GPIO电气属性*/
    IOMUXC_SetPinConfig(IOMUXC_LCD_DATA00_LCDIF_DATA00,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA01_LCDIF_DATA01,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA02_LCDIF_DATA02,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA03_LCDIF_DATA03,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA04_LCDIF_DATA04,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA05_LCDIF_DATA05,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA06_LCDIF_DATA06,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA07_LCDIF_DATA07,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA08_LCDIF_DATA08,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA09_LCDIF_DATA09,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA10_LCDIF_DATA10,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA11_LCDIF_DATA11,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA12_LCDIF_DATA12,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA13_LCDIF_DATA13,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA14_LCDIF_DATA14,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA15_LCDIF_DATA15,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA16_LCDIF_DATA16,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA17_LCDIF_DATA17,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA18_LCDIF_DATA18,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA19_LCDIF_DATA19,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA20_LCDIF_DATA20,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA21_LCDIF_DATA21,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA22_LCDIF_DATA22,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA23_LCDIF_DATA23,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_CLK_LCDIF_CLK,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_ENABLE_LCDIF_ENABLE,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_HSYNC_LCDIF_HSYNC,0xB9);
	IOMUXC_SetPinConfig(IOMUXC_LCD_VSYNC_LCDIF_VSYNC,0xB9);

    IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18,0xF080);

    /*2.背光设置*/
    IOMUXC_SetPinMux(IOMUXC_GPIO1_IO08_GPIO1_IO08,0);
	IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO08_GPIO1_IO08,0XB9);
    gpio_config_t bl_config;
    bl_config.section= gpio_out;
    bl_config.mode=1;
    gpio_init(GPIO1,8,&bl_config);

}

/*像素时钟第初始化,LCD频率=24×loopDiv/prediv/div,后面两个都是分频值*/
void lcd_clock_init(unsigned char loopDiv,unsigned char prediv,unsigned char div)
{
    /*不用小数分频器*/
    CCM_ANALOG->PLL_VIDEO_NUM = 0;
    CCM_ANALOG->PLL_VIDEO_DENOM = 0;

    CCM_ANALOG->PLL_VIDEO =(1<<13)|(2<<19)|(loopDiv<<0);

    CCM_ANALOG->MISC2 &=~(3<<30);
    CCM_ANALOG->MISC2 = 0 << 30;

    CCM->CSCDR2 &=~(7<<15);
    CCM->CSCDR2 |=(2<<15);

    CCM->CSCDR2 &=~(7<<12);
    CCM->CSCDR2 |=(prediv-1)<<12;

    CCM->CBCMR &=~(7<<23);
    CCM->CBCMR |=(div-1)<<23;

    CCM->CSCDR2 &=~(7<<9);
	CCM->CSCDR2 |= (0 << 9);
}
/*复位*/
void lcd_reset(void)
{
    LCDIF->CTRL =1<<31;
}
/*停止复位*/
void lcd_noreset(void)
{
    LCDIF->CTRL = 0<<31;
}
/*使能LCD控制器*/
void lcd_enable(void)
{
    LCDIF->CTRL |= 1<<0;
}

 unsigned short lcd_read_panelid(void)
 {
    unsigned char idx = 0;
    unsigned short idx_result = 0;
    /*打开模拟开关*/
    IOMUXC_SetPinMux(IOMUXC_LCD_VSYNC_GPIO3_IO03,0);		
	IOMUXC_SetPinConfig(IOMUXC_LCD_VSYNC_GPIO3_IO03,0X10b0);

    /*GPIO初始化*/
    gpio_config_t lcd_config;
    lcd_config.section= gpio_out;
    lcd_config.mode=1;
    gpio_init(GPIO3,3,&lcd_config);

    /*读取屏幕ID*/
    IOMUXC_SetPinMux(IOMUXC_LCD_DATA07_GPIO3_IO12,0);//B7		
    IOMUXC_SetPinMux(IOMUXC_LCD_DATA15_GPIO3_IO20,0);//G7	
    IOMUXC_SetPinMux(IOMUXC_LCD_DATA23_GPIO3_IO28,0);//R7
    IOMUXC_SetPinConfig(IOMUXC_LCD_DATA07_GPIO3_IO12,0Xf080);//B7
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA15_GPIO3_IO20,0Xf080);//G7
	IOMUXC_SetPinConfig(IOMUXC_LCD_DATA23_GPIO3_IO28,0Xf080);//R7
    lcd_config.section= gpio_in;//设置为输入
    gpio_init(GPIO3,12,&lcd_config);		
    gpio_init(GPIO3,20,&lcd_config);
    gpio_init(GPIO3,28,&lcd_config);
    idx = (unsigned char)gpio_read(GPIO3,28);//idx= R7: G7: B7:
    idx |= (unsigned char)gpio_read(GPIO3,20)<<1;
    idx |= (unsigned char)gpio_read(GPIO3,12)<<2;
    switch(idx)
    {
        case 0:
            idx_result = ATK4342;
            break;
        case 1:
            idx_result = ATK7084;
            break;
        case 2:
            idx_result = ATK7016;
            break;
        case 5:
            idx_result = ATK1018;
            break;
        case 4:
            idx_result = ATK4384;
            break;
        default:
            break;
    }
    return idx_result;
 }

 /*画点函数*/
 inline void lcd_drawpoint(unsigned short x,unsigned short y,unsigned int color)
 {
     *(unsigned int*)((unsigned int)tftlcd_dev.framebuffer+tftlcd_dev.pixsize*(tftlcd_dev.width*y+x))=color;
 }
 /*读点函数,即读点的颜色*/
 inline unsigned int lcd_readpoint(unsigned int x,unsigned int y)
 {
     return *(unsigned int *)((unsigned int)tftlcd_dev.framebuffer+tftlcd_dev.pixsize*(tftlcd_dev.width*y+x));
 }
 /*清除屏幕*/
 void lcd_clear(unsigned int color)
 {
     unsigned int num;
     unsigned int i =0 ;
     unsigned int *startaddr =(unsigned int *)tftlcd_dev.framebuffer;
     num = (unsigned int)(tftlcd_dev.height*tftlcd_dev.width);
     for(i=0;i<num;i++)
     {
         startaddr[i]=color;
     }
 }
void lcd_fill(unsigned short x0,unsigned short y0,unsigned short x1,unsigned short y1,unsigned int color)
{ 
    unsigned short x, y;
	if(x0 < 0) x0 = 0;
	if(y0 < 0) y0 = 0;
	if(x1 >= tftlcd_dev.width) x1 = tftlcd_dev.width - 1;
	if(y1 >= tftlcd_dev.height) y1 = tftlcd_dev.height - 1;
    for(y = y0; y <= y1; y++)
    {
        for(x = x0; x <= x1; x++)
			lcd_drawpoint(x, y, color);
    }
}

主函数:

c 复制代码
#include "main.h"

#include "dsp_clk.h"

#include "dsp_led.h"

#include "dsp_delay.h"

#include "beep.h"

#include "dsp_key.h"

#include "dsp_int.h"

#include "dsp_exti.h"

#include "dsp_epit.h"

#include "dsp_uart.h"

#include "stdio.h"

#include "dsp_lcd.h"

#include "dsp_lcdapi.h"

unsigned int show_color[8]={LCD_BLACK,LCD_YELLOW,LCD_BLUE,

                            LCD_GREEN,LCD_LIGHTRED,LCD_LIGHTYELLOW,

                            LCD_GRAY,LCD_ORANGE};

int main(void)

{

    int b=0;

    unsigned char kkkk=0;

    int_init();//中断初始化

    imx6u_clkinit();//时钟初始化

    key_init();//按键初始化

    clk_enable();//时钟初始化

    uart_init();//串口初始化

    beep_init();//凤鸣器初始化

    led_init();//led初始化

    lcd_init();//LCD读ID号

    tftlcd_dev.forecolor = LCD_RED;

    tftlcd_dev.backcolor = LCD_WHITE;

   // lcd_show_string(10,40,260,32,32,(char *)"Fucking high");

    while(1)

    {

        tftlcd_dev.forecolor = LCD_RED;

        lcd_show_string(100,100,240,32,32,(char *)"2025.1.1");

        // lcd_clear(show_color[b]);

        // b++;

        // if(b==8) b=0;

        led_mode(kkkk);

        delay(1000);

        kkkk = !kkkk;     

    }

    return 0;    

}

三,总结

1.c语言知识

c 复制代码
int aaaa= 0x11223344
 *(unsigned int *)a=5

这个意思是先把aaaa强制类型转换成无符号整形指针,即地址为0X11223344,在前面再加*,意思就是这个指针指向的内容,即先强制转化为指针后,再往这个地址对应的内容进行赋值。

相关推荐
对自己不够狠21 分钟前
Linux 常用命令
linux·运维·服务器
大兵编码1 小时前
linux系统常用命令
linux·运维·服务器
关关钧2 小时前
【Linux】函数
linux·运维·服务器
m0_748234085 小时前
构建流媒体直播服务器:nginx与nginx-rtmp-module实战指南
运维·服务器·nginx
Lang_xi_5 小时前
Bash Shell的操作环境
linux·开发语言·bash
关关钧6 小时前
【Linux】sed编辑器
linux·运维·编辑器
哦豁灬6 小时前
linux查看硬件信息
linux·运维·服务器
m0_748252606 小时前
在Linux系统上使用nmcli命令配置各种网络(有线、无线、vlan、vxlan、路由、网桥等)
linux·服务器·网络
raysync8887 小时前
如何保留企业传输系统操作习惯来实现企业无缝FTP替代升级
运维·服务器·网络
小白的登仙路7 小时前
进程间通讯
linux·c语言·进程间通讯