Frame Buffer设备驱动 (ili9488 3.5寸tft屏)

news2024/11/19 8:24:56

Frame Buffer设备驱动

  • Frame Buffer设备
  • ili9488介绍
  • 驱动编写
  • 代码编写
    • ili9488.c
    • 设备树修改
    • 测试
    • ili9488代码分析
  • LCD资料下载

Frame Buffer设备

  在早期的输出显示设备中,大部分为CRT显示器,随着技术的不断发展,现在大部分使用的是液晶显示器。这些显示设备在linux中统称为Frame Buffer设备,即帧缓冲设备,简称FB。
  需要说明的是,并不是只有显示屏这种设备才是帧缓存设备,实际上帧缓冲设备只是一种显示原理,将显示缓冲区中的数据重定向到输出设备中,也许有些输出设备仅仅只是一个虚拟的设备,那为何叫帧缓冲设备?这主要是因为帧缓冲设备的显示原理是在内存中开辟一块特定的暂存区,这块暂存区记录着所有像素数据,在一定的时间内将这个数据一一对应的写入到输出设备中,这样输出设备上就是我们需要显示的信息了。

ili9488介绍

  对于我购买的3.5寸TFT显示屏,其驱动芯片是ILI9488,采用的4线制spi,
在这里插入图片描述
其数据传输方式如下图所示
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

驱动编写

驱动主要是根据厂商提供的stm32例程来改的,在该例程里面有如下函数
在这里插入图片描述
从这里可以看出他是RGB565转的RGB666,在编写代码的时候也采用同样的思路

代码编写

ili9488.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <asm/io.h> //含有 ioremap 函数 iounmap 函数
#include <asm/uaccess.h> //含有 copy_from_user 函数和含有 copy_to_user 函数
#include <linux/device.h> //含有类相关的设备函数
#include <linux/cdev.h>
#include <linux/platform_device.h> //包含 platform 函数
#include <linux/of.h> //包含设备树相关函数
#include <linux/fb.h> //包含 frame buffer
#include <linux/spi/spi.h>
#include <linux/regmap.h>
#include <linux/gpio.h>

static struct fb_info *myfb;                 //定义一个fb_info
static struct task_struct *fb_thread;        //定义一个线程刷新屏幕
static struct spi_device *fbspi;             //保存spi驱动指针
static struct gpio_desc *dc_pin;             //dc引脚
static struct gpio_desc *reset_pin;          //reset引脚
static u32    pseudo_palette[16];            //调色板缓存区

/*
@function : write an 8-bit command to the LCD screen
@param : reg: comnmand value to be written
@return : none
*/
static void fb_write_reg(struct spi_device *spi, u8 reg)
{
    gpiod_set_value(dc_pin, 0);              //低电平,命令
    spi_write(spi, &reg, 1);

}

/*
@function : write an 16-bit data into registers,rgb565->rgb666
@param : data:data to be written
@return : none
*/
static void fb_write_data_u16(struct spi_device *spi, u16 data)
{
    u8 buf[3];
    buf[0] = ((u8)(data>>8))&0xF8;  //RED
    buf[1] = ((u8)(data>>3))&0xFC;  //GREEN
    buf[2] = ((u8)(data<<3));       //BLUE
    gpiod_set_value(dc_pin, 1); //高电平,数据
    spi_write(spi, &buf[0], 1);
    spi_write(spi, &buf[1], 1);
    spi_write(spi, &buf[2], 1);
}

/*
@function :write an 8-bit data to the lcd screen
@param :data:data value to written
@return : none
*/
static void fb_write_data_u8(struct spi_device *spi, u8 data)
{
    gpiod_set_value(dc_pin, 1); //高电平,数据
    spi_write(spi, &data, 1);
}

/*
@function :setting lcd display window
@param :xstar: the begining x coordinate of the lcd display window
        ystar: the begining y coordinate of the lcd display window
        xEnd:  the ending x coordinate of the lcd display window
        yEnd:  the ending y coordinate of the lcd display window
*/
static void fb_set_win(struct spi_device *spi, u16 xStar, u16 yStar, u16 xEnd, u16 yEnd){
    fb_write_reg(spi,  0x2a);
    fb_write_data_u8(spi, xStar >> 8);
    fb_write_data_u8(spi, xStar & 0xFF);
    fb_write_data_u8(spi, xEnd >> 8);
    fb_write_data_u8(spi, xEnd & 0xff);

    fb_write_reg(spi, 0x2b);
    fb_write_data_u8(spi, yStar >> 8);
    fb_write_data_u8(spi, yStar & 8);
    fb_write_data_u8(spi, yEnd >> 8);
    fb_write_data_u8(spi, yEnd & 0xff);

    fb_write_reg(spi, 0x2c);    //  开始写入GRAM,即往lcd的GRAM写数据,LCD随即显示到屏幕上
}

static void myfb_init(struct spi_device *spi){
    gpiod_set_value(reset_pin, 0);  //设置低电平
    msleep(100);
    gpiod_set_value(reset_pin, 1);  //设高电平
    msleep(50);

    /*   写寄存器,初始化*/

    fb_write_reg(spi, 0xf7);
    fb_write_data_u8(spi, 0xa9);
    fb_write_data_u8(spi, 0x51);
    fb_write_data_u8(spi, 0x2c);
    fb_write_data_u8(spi, 0x82);

    fb_write_reg(spi, 0xc0);
    fb_write_data_u8(spi, 0x11);
    fb_write_data_u8(spi, 0x09);

    fb_write_reg(spi, 0xc1);
    fb_write_data_u8(spi, 0x41);

    fb_write_reg(spi, 0xc5);
    fb_write_data_u8(spi, 0x00);
    fb_write_data_u8(spi, 0x0a);
    fb_write_data_u8(spi, 0x80);

    fb_write_reg(spi, 0xb1);
    fb_write_data_u8(spi, 0xB0);
    fb_write_data_u8(spi, 0x11);

    fb_write_reg(spi, 0xb4);
    fb_write_data_u8(spi, 0x02);

    fb_write_reg(spi, 0xb6);
    fb_write_data_u8(spi, 0x02);
    fb_write_data_u8(spi, 0x42);

    fb_write_reg(spi, 0xb7);
    fb_write_data_u8(spi, 0xc6);

    fb_write_reg(spi, 0xbe);
    fb_write_data_u8(spi, 0x00);
    fb_write_data_u8(spi, 0x04);

    fb_write_reg(spi, 0xe9);
    fb_write_data_u8(spi, 0x00);

    fb_write_reg(spi, 0x36);
    fb_write_data_u8(spi, (1<<3)|(0<<7)|(1<<6)|(1<<5));

    fb_write_reg(spi, 0x3a);
    fb_write_data_u8(spi, 0x66);

    fb_write_reg(spi, 0xe0);
    fb_write_data_u8(spi, 0x00);
    fb_write_data_u8(spi, 0x07);
    fb_write_data_u8(spi, 0x10);
    fb_write_data_u8(spi, 0x09);
    fb_write_data_u8(spi, 0x17);
    fb_write_data_u8(spi, 0x0b);
    fb_write_data_u8(spi, 0x41);
    fb_write_data_u8(spi, 0x89);
    fb_write_data_u8(spi, 0x4b);
    fb_write_data_u8(spi, 0x0a);
    fb_write_data_u8(spi, 0x0c);
    fb_write_data_u8(spi, 0x0e);
    fb_write_data_u8(spi, 0x18);
    fb_write_data_u8(spi, 0x1b);
    fb_write_data_u8(spi, 0x0f);

    fb_write_reg(spi, 0xe1);
    fb_write_data_u8(spi, 0x00);
    fb_write_data_u8(spi, 0x17);
    fb_write_data_u8(spi, 0x1a);
    fb_write_data_u8(spi, 0x04);
    fb_write_data_u8(spi, 0x0e);
    fb_write_data_u8(spi, 0x06);
    fb_write_data_u8(spi, 0x2f);
    fb_write_data_u8(spi, 0x45);
    fb_write_data_u8(spi, 0x43);
    fb_write_data_u8(spi, 0x02);
    fb_write_data_u8(spi, 0x0a);
    fb_write_data_u8(spi, 0x09);
    fb_write_data_u8(spi, 0x32);
    fb_write_data_u8(spi, 0x36);
    fb_write_data_u8(spi, 0x0f);
    
    fb_write_reg(spi, 0x11);
    mdelay(50);
    fb_write_reg(spi, 0x29);
    mdelay(200);

}

void fb_refresh(struct fb_info *fbi, struct spi_device *spi){
    int x, y;
    u16 *p =(u16 *)(fbi->screen_base );
    fb_set_win(spi, 0, 0, 479, 319);
    for (y = 0; y < fbi->var.yres; y++){
        for (x = 0; x < fbi->var.xres; x++){
            fb_write_data_u16(spi, *p++);
        }
    }
}

int thread_func_fb(void *data){
    struct fb_info *fbi = (struct fb_info *)data;
    while(1){
        if(kthread_should_stop())
            break;
        fb_refresh(fbi,fbspi);
    }
    return 0;
}

static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf)
{
    chan &= 0xffff;
    chan >>= 16-bf->length;
    return chan << bf->offset;
}

static u32 pseudo_palette[16];

static int myfb_setcolreg(u32 regno, u32 red, u32 green, u32 blue, u32 transp, struct fb_info *info){
    unsigned int val;
    if (regno > 16)
        return 1;
    val = chan_to_field(red, &info->var.red);
    val |= chan_to_field(green, &info->var.green);
    val |= chan_to_field(blue, &info->var.blue);

    pseudo_palette[regno] = val;
    return 0;
}

static struct fb_ops myfb_ops = {
    .owner        = THIS_MODULE,
    .fb_write     = fb_sys_write,
    .fb_setcolreg = myfb_setcolreg,            /* 设置颜色寄存器 */
    .fb_fillrect  = sys_fillrect,              /* 用像素行填充矩形框,通用库函数 */
    .fb_copyarea  = sys_copyarea,              /* 将屏幕的一个矩形区域复制到另一个区域,通用库函数*/
    .fb_imageblit = sys_imageblit,             /* 显示一幅图像,通用库函数*/           

};

static void myfb_update(struct fb_info *fbi, struct list_head *pagelist){
    /* 比较粗暴的方式,直接全部刷新 */
    fbi->fbops->fb_pan_display(&fbi->var,fbi);    /*将应用层数据刷新到FrameBuffer缓存中*/
}

static struct fb_deferred_io myfb_defio = {
    .delay = HZ/20,
    .deferred_io = &myfb_update,

};

static struct fb_var_screeninfo myfb_var ={
    .rotate = 0,
    .xres   =480,
    .yres   =320,
    .xres_virtual =480,
    .yres_virtual =320,
    .bits_per_pixel =16,           //每个像素的位数
    .nonstd    =1,
    
    /*rgb565*/
    .red.offset = 11,
    .red.length = 5,
    .green.offset = 5,
    .green.length =6,
    .blue.offset = 0,
    .blue.length = 5,
    .transp.offset = 0,
    .transp.length = 0,
    .activate   =FB_ACTIVATE_NOW,
    .vmode     =FB_VMODE_NONINTERLACED, 
};

static struct fb_fix_screeninfo myfb_fix ={
    .type =FB_TYPE_PACKED_PIXELS,
    .visual = FB_VISUAL_TRUECOLOR, //
    .line_length =480*2,           // width *bpp /8  就是宽度乘每个像素需要的位数除8 ,就是每行需要的字节数
    .accel = FB_ACCEL_NONE, //没有使用硬件加速
    .id    = "myfb",
};

static int myfb_probe(struct spi_device *spi){
    int ret;
    void *gmem_addr;
    u32 gmem_size;
    fbspi = spi; //保存spi驱动指针
    printk(KERN_ERR"register myfb_spi_probe!\n");

    //申请GPIO用作DC引脚
    dc_pin = devm_gpiod_get(&spi->dev,"dc",GPIOF_OUT_INIT_LOW);
    if(IS_ERR(dc_pin)){
        printk(KERN_ERR"fail to request dc_gpios!\n");
    }

    //申请GPIO用作RESET引脚
    reset_pin =devm_gpiod_get(&spi->dev,"reset",GPIOF_OUT_INIT_HIGH);
    if(IS_ERR(reset_pin)){
        printk(KERN_ERR"fail to request reset-gpios!\n");
        return -1;
    }

    gpiod_direction_output(dc_pin, 0);  //设置输出方向
    gpiod_direction_output(reset_pin, 1); //设置输出方向

    printk(KERN_INFO"register myfb_probe dev !\n");
    myfb = framebuffer_alloc(sizeof(struct fb_info), &spi->dev); //向内核申请fb_info结构体
    //初始化底层操作结构体
    myfb->fbops =&myfb_ops;  //指定底层操作结构体
    gmem_size =320*480*2;   //设置显存大小,16bit 占2字节
    gmem_addr =kmalloc(gmem_size,GFP_KERNEL);  //分配Frame Buffer 显存

    if(!gmem_addr){
        printk(KERN_ERR"fail to alloc fb buffer!\n");

    }
    myfb->pseudo_palette = pseudo_palette;
    myfb->var =myfb_var;   // 设置分辨率参数
    myfb->fix =myfb_fix;   // 设置显示参数
    myfb->screen_buffer =gmem_addr; //设置显存地址
    myfb->screen_size = gmem_size; //设置显存大小
    myfb->fix.smem_len = gmem_size; //设置应用层显存大小
    myfb->fix.smem_start =(u32) gmem_addr; //设置应用层数据地址

    memset((void *)myfb->fix.smem_start, 0,myfb->fix.smem_len);  //清楚数据缓存
    myfb_init(spi);  //初始化显示屏
    myfb->fbdefio =&myfb_defio; //设置刷新参数
    fb_deferred_io_init(myfb);   //初始化刷新机制
    ret = register_framebuffer(myfb);   //注册fb驱动
    if(ret)
    {
        framebuffer_release(myfb);
        unregister_framebuffer(myfb);
        devm_gpiod_put(&spi->dev, dc_pin);
        devm_gpiod_put(&spi->dev, reset_pin);
        printk(KERN_ERR"fail to register fb dev!\n");
        return -1;
    }
    //开启一个线程用来刷新显示屏
    fb_thread = kthread_run(thread_func_fb,myfb,spi->modalias);
    return 0;

}

int myfb_remove(struct spi_device *spi){
    fb_deferred_io_cleanup(myfb);  //清除刷新机制
    unregister_framebuffer(myfb);
    devm_gpiod_put(&spi->dev,dc_pin);
    devm_gpiod_put(&spi->dev,reset_pin);
    return 0;

}

struct of_device_id myfb_match[] ={
    {.compatible = "ilitek,ili9488"},
    {},
};

struct spi_driver myfb_drv = {
    .driver ={
        .owner = THIS_MODULE,
        .name = "myfb_spi_driver",
        .of_match_table = myfb_match,
    },
    .probe =myfb_probe,
    .remove = myfb_remove,

} ;

module_spi_driver(myfb_drv);


MODULE_LICENSE("GPL"); //不加的话加载会有错误提醒
MODULE_AUTHOR("2241507913@qq.com"); //作者
MODULE_VERSION("0.1"); //版本
MODULE_DESCRIPTION("myfb_spi_driver"); //简单的描述

设备树修改

在bcm2711-rpi-4-b.dts设备树修改&spi0

&spi0 {
	pinctrl-names = "default";
	pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
	cs-gpios = <&gpio 8 1>, <&gpio 7 1>;
    status = "okay";
    
	ili9488@0{
        status = "okay";
        compatible = "ilitek,ili9488";
        reg = <0>;  /* CE0 Ƭѡ*/
        #address-cells = <1>;
        #size-cells = <0>;
        spi-max-frequency = <32000000>;
        dc-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
        reset-gpios = <&gpio 18 GPIO_ACTIVE_HIGH>;
        rotation =<90>;
    };

	spidev1: spidev@1{
		compatible = "spidev";
		reg = <1>;	/* CE1 */
		#address-cells = <1>;
		#size-cells = <0>;
		spi-max-frequency = <125000000>;
	};
};

测试

使用insmod加载ili9488.ko
在这里插入图片描述

加载完成后,在/dev目录下可以看到fb0,此为驱动里面注册的帧缓冲区
在这里插入图片描述
/dev/tty0是默认映射到/dev/fb0上的,所以,我们通过操作/dev/tty0即可操作屏幕

在这里插入图片描述
解决办法
sudo chmod 777 /dev/tty0
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ili9488代码分析

对于调色板myfb_setcolreg()函数,这里并未使用,是直接使用的rgb,

LCD资料下载

链接: [link](链接: link)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1095190.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RabbitMQ死信队列原理与项目代码示例

1、产生死信消息的原因 当在消费消息时&#xff0c;如果队列里的消息出现以下情况&#xff0c;那么该消息将成为一条死信消息&#xff1a; 当一条消息被使用 channel.basicNack方法 或 channel.basicReject方法所nack响应 &#xff0c;并且此时requeue 属性被设置为false。 消…

使用Elasticsearch来进行简单的DDL搜索数据

说明&#xff1a;Elasticsearch提供了多种多样的搜索方式来满足不同使用场景的需求&#xff0c;我们可以使用Elasticsearch来进行各种复制的查询&#xff0c;进行数据的检索。 1.1 精准查询 用来查询索引中某个类型为keyword的文本字段&#xff0c;类似于SQL的“”查询。 创…

Python学习基础笔记六十七——格式化字符串

Printf-Style String Formatting: Printf风格字符串格式化 salary input(请输入薪资&#xff1a;)# 计算出缴税额&#xff0c;存入变量tax tax int(salary) *25/100 # 转化为字符串&#xff0c;方便下面的字符串拼接 taxStr str(tax) # 计算出税后工资&#xff0c;存入变…

Linux基础—1

1、命令行 1) 重要快捷键 按键作用Tab命令补全Ctrl强行终止当前程序Ctrld键盘输入结束或退出终端Ctrls暂停当前程序&#xff0c;暂停后按下任意键恢复运行Ctrlz将当前程序放到后台运行&#xff0c;恢复到前台为命令fgCtrla将光标移至输入行头&#xff0c;相当于Home键Ctrle将…

计算机操作系统-第六天

目录 1、操作系统的体系结构&#xff08;简要了解&#xff09; 操作系统的内核&#xff1a; 操作系统的体系结构 关于微内核的相关理解&#xff1a; 本节思维导图&#xff1a; 1、操作系统的体系结构&#xff08;简要了解&#xff09; 操作系统的内核&#xff1a; 内核是…

整理总结提高抖音小店商品转化率的五大策略

要提高抖音小店的商品转化率&#xff0c;即将浏览者转化为实际购买者&#xff0c;四川不若与众整理了需要注意的以下几个关键因素。 首先&#xff0c;优化商品页面设计。商品页面是消费者获取产品信息和决策的关键环节。商家应确保商品页面简洁清晰&#xff0c;配备高质量的产品…

Pytest+Allure生成可添加附件的测试报告

#测试套件层级 allure.feature("测试PecExplorer") #重试次数&#xff0c;粒度为用例&#xff0c;建议用例设计可重复性高 pytest.mark.flaky(reruns3) class TestPecExplorer:#功能模块层级allure.story("登录界面")#测试用例层级allure.title("Test…

C语言程序设计 三四节课堂笔记

C语言程序设计 三四节课堂笔记 C语言程序设计 三四节课堂笔记3.0 程序编写顺序&#xff08;了解&#xff09;3.1 C语言的特点3.2 认识C程序1. C程序的基本框架2. C语言程序的结构特点3. C程序的开发过程 C语言程序设计 第四节课4.1 开发环境dev-C的使用1. 如何将英文界面调整为…

Spring-Java

Spring&#xff1a; 图片出处&#xff1a;b站黑马 ssm学习截图 是一个大家族 &#xff0c;是一套完整的开发生态圈。可以利用这个spring全家桶快速构建企业级开发环境。 Spring Freamwork 是其他框架的基础 Springbot 使用了注解开发 SpringCloud 分布式 云服务 Sprin…

Leetcode—88.合并两个有序数组【简单】

2023每日刷题&#xff08;一&#xff09; Leetcode—88.合并两个有序数组 题解 因为这两个数组已经排好序&#xff0c;我们可以把两个指针分别放在两个数组的末尾&#xff0c;即 nums1 的m − 1 位和 nums2 的 n − 1 位。每次将较大的那个数字复制到 nums1 的后边&#xff0…

计算机操作系统面试题自用

什么是操作系统&#xff1a; 操作系统是管理硬件和软件的一种应用程序。操作系统是运行在计算机上最重要的一种软件 操作系统的主要功能 解释一下操作系统的主要目的是什么 操作系统是一种软件&#xff0c;它的主要目的有三种 1 管理计算机资源&#xff0c;这些资源包括 C…

LangChain结合milvus向量数据库以及GPT3.5结合做知识库问答之一 --->milvus的docker compose安装

https://github.com/milvus-io/milvus/releaseshttps://github.com/milvus-io/milvus/releases 以下步骤均在Linux环境中进行&#xff1a; 将milvus-standalone-docker-compose.yml下载到本地。 1、新建一个目录milvus 2、将milvus-standalone-docker-compose.yml放到milvu…

UWB承启定位基站

UWB承启定位基站 随着我们使用UWB做超高精度的定位项目越来越多&#xff0c;我们发现之前的定位基站完全站在二维或三维的角度去设计还是存在对应的缺陷&#xff0c;这个时候需要在很短的距离内安装多一个基站&#xff0c;对于用户来说&#xff0c;会觉得设备变多了&#xff0…

05在IDEA中配置Maven的基本信息

配置Maven信息 配置Maven家目录 每次创建Project工程后都需要设置Maven家目录位置&#xff0c;否则IDEA将使用内置的Maven核心程序和使用默认的本地仓库位置 一般我们配置了Maven家目录后IDEA就会自动识别到conf/settings.xml配置文件和配置文件指定的本地仓库位置创建新的P…

Java中的栈(Stack)为什么要采用先进后出

Java虚拟机栈 Java虚拟机栈是描述Java方法运行过程的内存模型。 当一个方法即将被运行时&#xff0c;Java虚拟机栈首先会在Java虚拟机栈中为该方法创建一块“栈帧”&#xff0c;栈帧中包含局部变量表(基本数据类型变量、引用类型的变量、returnAddress类型的变量)、操作数栈、…

小谈设计模式(29)—访问者模式

小谈设计模式&#xff08;29&#xff09;—访问者模式 专栏介绍专栏地址专栏介绍 访问者模式角色分析访问者被访问者 优缺点分析优点将数据结构与算法分离增加新的操作很容易增加新的数据结构很困难4 缺点增加新的数据结构比较困难增加新的操作会导致访问者类的数量增加34 总结…

windows10系统-16-制作导航网站WebStack-Hugo

上个厕所功夫把AI导航搞定了 使用Hugo搭建静态站点 如何使用Hugo框架搭建一个快如闪电的静态网站 1 Hugo 参考Hugo中文文档 参考使用Hugo搭建个人网站 Hugo是由Go语言实现的静态网站生成器。简单、易用、高效、易扩展、快速部署。 1.1 安装Hugo 二进制安装&#xff08;推荐…

iMeta框架使用方法

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是「奇点」&#xff0c;江湖人称 singularity。刚工作几年&#xff0c;想和大家一同进步&#x1f91d;&#x1f91d; 一位上进心十足的【Java ToB端大厂…

判断一棵树是否为完全二叉树——层序遍历

完全二叉树&#xff08;包括满二叉树 &#xff09; 利用层序遍历&#xff0c;当取顶取到空的时候&#xff08;这个时候取的这一层的所有节点是一定在队列里面的&#xff09;&#xff0c;就结束入队&#xff0c;然后判断他的后面的节点是否都为空 这里重点还是要理解二叉树的层…

求二叉树的高度——函数递归的思想

二叉树的高度&#xff1a;左右两个数最高的那个的1 int TreeHight(BTNode* root) {if (root NULL){return 0;}int lefhightTreeHight(root->left);int righthight TreeHight(root->right);return lefhight > righthight ? TreeHight(root->left) 1 : TreeHight…