前言:
本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM(MX6U)裸机篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。
引用:
正点原子IMX6U仓库 (GuangzhouXingyi) - Gitee.com
《【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf》
正点原子资料下载中心 — 正点原子资料下载中心 1.0.0 文档
正文:
本文是 “正点原子[第二期]Linux之ARM(MX6U)裸机篇--第21 讲” 的读书笔记。第21讲主要是介绍I.MX6U处理器的LCD液晶显示屏驱动的裸机开发,本节使用的是正点原子I.MX6U ALPHA/Mini 开发板配套的4.7英寸或7英寸 RGBLCD (RGB接口的LCD液晶显示屏)。本节将参考正点原子的视频教程第21讲和配套的正点原子开发指南文档进行学习。
正点原子第21讲I.MX6U ARM裸机RGBLCD液晶显示屏的视频教程比较长一共有8节视频教程,相对来说通过I.MX6U ARM 裸机寄存器来驱动RGBLCD涉及到的寄存器比较多,相对来说还是比较复杂的。
本节是正点原子第21.5讲RGBLCD视频教程,读取屏幕ID。
注意:
只有正点原子自己提供的屏幕才有其自定义的屏幕ID,正点原子定义屏幕ID的原因是正点原子开发板提供了多种的LCD屏幕尺寸,例如4.3英寸屏,7英寸屏,10英寸屏等等,所以需要屏幕ID来区分正点原子自家的集中不同尺寸型号的LCD液晶屏;在适配其他家的LCD显示屏可能不需要读取屏幕ID。
0. 概述
正点原子开发板提供了多种的LCD屏幕尺寸,例如4.3英寸屏,7英寸屏,10英寸屏等,所以在LCD裸机开发驱动实验中需要首先读取到LCD液晶屏的面板ID,通过面板ID来获取到当前使用的LCD显示屏的尺寸和LCD显示屏分辨率。
1. 硬件原理
正点原子的LCD(RGB)液晶显示屏上有几个电阻,通过GPIO读取到电阻的阻值来区分屏幕的“面板ID”型号,通过型号进而可以指导LCD液晶屏的尺寸和分辨率。
正点原子I.MX6U ALPHA/Mini 开发板底板电路原理图如下所示:
LCD_DATA15, LCD_DATA23, LCD_DATA7 ,这3个I.MX6U 连接到处理器引脚,I.MX6U处理器引脚和LCD_DATA15S, LCD_DATA23S, LCD_DATA7S 之间通过 "SGM3157" 来开关器件连接起来,只有 "LCD_VSYSNC" 引脚给出高电平是 "SGM3157" 开关才导通,所以在读取正点原子屏幕ID之前,需要先将 "LCD_VSYSNC" 引脚输出为高电平(配置为GPIO output输出模式),然后通过I.MX6U处理器引脚 “LCD_DATA15, LCD_DATA23, LCD_DATA7” 读取电平值(配置为GPIO input输入模式)来确定屏幕ID。
总结一下,读取正点原子LCD液晶屏ID的步骤如下:
- LCD_VSYNC 引脚配置为GPIO输出模式(OUTPUT)并且输出高电平。
LCD_VSYNC高电平,为SGM_CTL高电平,SGM_CTL为高电平打开3个 SGM3157 电路开关,SGM3157开关打开之后 LCD_DATA15, LCD_DATA23, LCD_DATA7 才和 LCD_DATA15S, LCD_DATA23S, LCD_DATA7S 连接起来。- 配置 LCD_DATA15, LCD_DATA23, LCD_DATA7 三个引脚为GPIO输入模式(INPUT),处理器通过读取三个GPIO引脚的电平高低来获取正点原子屏幕ID。
2. LCD接口寄存器
LCD_VSYNC IO接口寄存器如下图所示,可以将其复用为 GPIO3_IO03 的 GPIO Output 模式并且输出高电平。
LCD_DATA7 IO接口寄存器如下,可以将其复用为 GPIO3_IO12 的 GPIO Intput 模式并且读取gpio引脚上的输入是高电平还是低电平。
3. LCD 屏幕ID读取源码编写
读取正点原子LCD屏幕ID。
bsp/bsp_lcd.h
#ifndef __BSP_LCD_H__
#define __BSP_LCD_H__
#include "imx6u.h"
/* 屏幕ID */
#define ATK4342 0X4342 /* 4.3寸480*272 */
#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 ATKVGA 0xff00 /* VGA */
unsigned short lcd_read_panelId(void);
void lcd_init(void);
void lcd_gpio_init(void);
#endif
bsp/bsp_lcd.c 源码
#include "bsp_lcd.h"
#include "bsp_gpio.h"
#include "stdio.h"
/*
* @description : LCD初始化
* @param : 无
* @return : 无
*/
void lcd_init(void)
{
unsigned short panelId = 0;
panelId = lcd_read_panelId();
printf("LCD panelId=0X%X\r\n", panelId);
}
/*
* @description : 读取正点原子LCD液晶屏面板Id
* LCD_DATA23=R7(M0);LCD_DATA15=G7(M1);LCD_DATA07=B7(M2);
* M2:M1:M0
* 0 :0 :0 //4.3寸480*272 RGB屏,ID=0X4342
* 0 :0 :1 //7寸800*480 RGB屏,ID=0X7084
* 0 :1 :0 //7寸1024*600 RGB屏,ID=0X7016
* 1 :0 :1 //10.1寸1280*800,RGB屏,ID=0X1018
* 1 :0 :0 //4.3寸800*480 RGB屏,ID=0X4384
* @param : 无
* @return : 正点原子LCD液晶屏面板id
*
*/
unsigned short lcd_read_panelId(void)
{
unsigned short idx = 0;
unsigned short panelId = 0;
gpio_pin_config_t led_config;
/* LCD_VSYNC 复用为GPIO3_IO03 输出模式 */
IOMUXC_SetPinMux(IOMUXC_LCD_VSYNC_GPIO3_IO03, 0); /* IO复用 */
IOMUXC_SetPinConfig(IOMUXC_LCD_VSYNC_GPIO3_IO03, 0x10B0); /* IO电气特性 */
led_config.directioin = kGPIO_DigitalOutput;
led_config.outputLogic = 1;
//gpio_init(GPIO5, 1, &led_config);
gpio_init(GPIO3, 3, &led_config);
/* M0,M1,M2 IO 复用 */
IOMUXC_SetPinMux(IOMUXC_LCD_DATA23_GPIO3_IO28, 0); /* M0(R7) LCD_DATA23 GPIO输入模式 */
IOMUXC_SetPinMux(IOMUXC_LCD_DATA15_GPIO3_IO20, 0); /* M1(G7) LCD_DATA15 GPIO输入模式 */
IOMUXC_SetPinMux(IOMUXC_LCD_DATA07_GPIO3_IO12, 0); /* M2(B7) LCD_DATA07 GPIO输入模式 */
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA23_GPIO3_IO28, 0xF080); /* M0(R7) IO电气特性 */
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA15_GPIO3_IO20, 0xF080); /* M1(G7) IO电气特性 */
IOMUXC_SetPinConfig(IOMUXC_LCD_DATA07_GPIO3_IO12, 0xF080); /* M2(B7) IO电气特性 */
led_config.directioin = kGPIO_DigitalInput;
gpio_init(GPIO3, 28, &led_config); /* M0 */
gpio_init(GPIO3, 20, &led_config); /* M1 */
gpio_init(GPIO3, 12, &led_config); /* M2 */
idx = gpio_pinread(GPIO3, 28);
idx |= gpio_pinread(GPIO3, 20) << 1;
idx |= gpio_pinread(GPIO3, 12) << 2;
printf("idx=%d\r\n", idx);
switch(idx)
{
case 0:
panelId = ATK4342;
break;
case 1:
panelId = ATK7084;
break;
case 2:
panelId = ATK7016;
break;
case 4:
panelId = ATK4384;
break;
case 5:
panelId = ATK1018;
break;
}
return panelId;
}
4. 初始化LCD IO
初始化LCD IO接口,包括LCD_DATA0~LCD_DATA23,以及LCD_CLK, LCD_ENABLE, LCD_VSYNC, LCD_HSYNC 这些引脚的IO口复用和IO口电气特性。
以及LCD屏幕的背光 LCD_PWM 引脚的IO,从正点原子I.MX6ULL ALPHA/Mini 开发板电路原理图可以看到LCD液晶屏使用的是 GPIO1_IO08 引脚。
4.1 LCD屏幕IO口初始化源码编写
源码中 LCD_DATA0~LCD_DATA23, LCD_CLK, LCD_ENABLE, LCD_VSYNC, LCD_HYSNC 引脚的IO初始化,已经LCD背光 LCD_PWM 的 IO初始化源码如下。
bsp/bsp_lcd.c
void lcd_gpio_init(void)
{
/* LCD_DATA 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); /* LCD_CLK */
IOMUXC_SetPinMux(IOMUXC_LCD_ENABLE_LCDIF_ENABLE, 0); /* LCD_ENABLE */
IOMUXC_SetPinMux(IOMUXC_LCD_HSYNC_LCDIF_HSYNC, 0); /* LCD_HSYNC */
IOMUXC_SetPinMux(IOMUXC_LCD_VSYNC_LCDIF_VSYNC, 0); /* LCD_VSYNC */
/* LCD_DATA IO 电气属性 */
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); /* LCD_CLK */
IOMUXC_SetPinConfig(IOMUXC_LCD_ENABLE_LCDIF_ENABLE, 0xB9); /* LCD_ENABLE */
IOMUXC_SetPinConfig(IOMUXC_LCD_HSYNC_LCDIF_HSYNC, 0xB9); /* LCD_HSYNC */
IOMUXC_SetPinConfig(IOMUXC_LCD_VSYNC_LCDIF_VSYNC, 0xB9); /* LCD_VSYNC */
/* LCD背光点亮,背光GPIO初始化, LCD_PWM (Pulse Width Modulatization) */
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO08_GPIO1_IO08, 0);
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO08_GPIO1_IO08, 0x10B0);
gpio_pin_config_t led_config;
led_config.directioin = kGPIO_DigitalOutput;
led_config.outputLogic = 1; /* 默认输出高电平 */
gpio_init(GPIO1, 8, &led_config);
}
电气特性设置为 0x00B9
0x00B9 (hex)
0000 0000 1011 1001 (Binary)
5. 编译烧写SD卡验证实验结果
译修改主频后源码烧录SD卡验证本节的 LCD(RGB)液晶屏面板实验,读取ID值读取。预期烧录SD卡后正点原子I.MX6ULL ALPHA/Mini 开发板后,UART串口可以在串口中可以打印出读取到的LCD(RGB)液晶名的面板ID。
在本实验中,我使用的是I.MX6ULL Mini 开发板搭配的是4.3英寸 800*480 分辨率的LCD(RGB接口)液晶屏,烧录SD卡上电之后出口打印出来的 panelID=0x4384 和我开发板实际情况是相符的。
6. 总结和实验遇到的问题记录
6.1 问题1:烧录SD之后上电启动后,正点原子4.3英寸LCD屏的M0,M1,M2 三个GPIO口读取到的都是低电平,屏幕PanelID判断错误。
错误原因是如下第43行这里,初始化gpio_init()的时候将gpio的组别和gpio pin 引脚号写错了。应该根据实际使用的gpio引脚传递正确的gpio组别和gpio pin 引脚号来初始化对应的gpio。
这里因为写错了gpio组别和gpio pin 引脚号,LCD_VSYNC 信号实际上没有输出高电平,3个 SGM3157 开关都没有打开,从电路原理图可以看出此时读取到的M0,M1,M2都是低电平。
6.2 GPIO输出引脚的 IO 电气特性应该配置为 "0xF080"
M0,M1,M2 屏幕PanelId所使用的 LCD_DATA23, LCD_DATA15, LCD_DATA07 作为 GPIO输入Input模式的时候,应该配置IO口的电气特性值为 0xF080。
7. 结束
本章至此结束