您尚未登录。

楼主 # 2022-02-02 11:16:48

摸鱼moyu
会员
注册时间: 2021-09-18
已发帖子: 41
积分: 41

关于f1c200s上模拟8080驱动st7789,慢的要命,要没有办法大佬指点下让io快起来

问题同标题
起因是之前我为了学习linux自己画了一个板子但是ic上只有两个spi一个给了flash一个给了esp8089,为了体验各种操作方式把spi都用了,也不知道ic上那个40pin的是模拟的还是硬件的,本着学习的目就用了模拟8080来驱动st7789,前几天用st7735当终端,但他始终是复用了spi,现在想让io快起来给添加到framebuffer,

现在附上代码供大佬检查主要还是io的方式是不是这样不太好

st7789.c

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include "st7789bus.h"



#define ST7789_CNT	1
#define ST7789_NAME	"st7789"

struct st7789_dev st7789dev;

static struct file_operations st7789_fops = {
	.owner = THIS_MODULE,
};

static int st7789_probe(struct platform_device *dev)
{
	int ret;
	printk("st7789_probe\r\n");
	ret = alloc_chrdev_region(&st7789dev.devid, 0, ST7789_CNT, ST7789_NAME);
	if(ret < 0){
		printk("devid_err\r\n");
		return -EINVAL;
	}
	st7789dev.major = MAJOR(st7789dev.devid);
	printk("st7789 major:%d\r\n",st7789dev.major);

	cdev_init(&st7789dev.cdev, &st7789_fops);
	cdev_add(&st7789dev.cdev, st7789dev.devid, ST7789_CNT);

	st7789dev.class = class_create(THIS_MODULE, ST7789_NAME);
	if(IS_ERR(st7789dev.class)){
		return PTR_ERR(st7789dev.class);
	}

	st7789dev.device = device_create(st7789dev.class, NULL, st7789dev.devid, NULL, ST7789_NAME);
	if(IS_ERR(st7789dev.device)){
		return PTR_ERR(st7789dev.device);
	}

	st7789_gpio_request(&st7789dev);

	Lcd_Init();
	LCD_Clear(0x07E0);

	return 0;
}

static int st7789_remove(struct platform_device *dev)
{
	int i;
	printk("st7789_remove\r\n");

	gpio_free(st7789dev.res);
	gpio_free(st7789dev.cs);
	gpio_free(st7789dev.dc);
	gpio_free(st7789dev.wr);
	gpio_free(st7789dev.rd);
	for(i=0;i<8;i++){
		gpio_free(st7789dev.db[j]);
	}

	device_destroy(st7789dev.class, st7789dev.devid);
	class_destroy(st7789dev.class);
	cdev_del(&st7789dev.cdev);
	unregister_chrdev_region(st7789dev.devid, ST7789_CNT);

	return 0;
}

static struct of_device_id st7789_of_match[] = {
	{.compatible = "cxj,8080"},
	{}
};

static struct platform_driver st7789_driver = {
	.probe = st7789_probe,
	.remove = st7789_remove,
	.driver = {
		.owner = THIS_MODULE,
		.name = "st7789",
		.of_match_table = st7789_of_match,
	},

};

static int __init st7789_init(void)
{
    return platform_driver_register(&st7789_driver);
}


static void __exit st7789_exit(void)
{
    platform_driver_unregister(&st7789_driver);
}

module_init(st7789_init);
module_exit(st7789_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("CXJ");

st7789bus.h

#ifndef ST7789BUS_H
#define ST7789BUS_H

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>

struct st7789_dev {
    dev_t devid;
    int major;
    struct cdev cdev;
    struct class *class;
    struct device *device;
    struct device_node *node;

    int res;
    int cs;
    int dc;
    int wr;
    int rd;
    int db[8];
};

extern struct st7789_dev st7789dev;

#define    LCD_RST_SET     gpio_set_value(st7789dev.res, 1)
#define    LCD_CS_SET   gpio_set_value(st7789dev.cs, 1)
#define    LCD_DC_SET     gpio_set_value(st7789dev.dc, 1)
#define    LCD_WR_SET     gpio_set_value(st7789dev.wr, 1)
#define    LCD_RD_SET     gpio_set_value(st7789dev.rd, 1)

#define    LCD_RST_CLR  gpio_set_value(st7789dev.res, 0)
#define    LCD_CS_CLR   gpio_set_value(st7789dev.cs, 0)
#define    LCD_DC_CLR     gpio_set_value(st7789dev.dc, 0)
#define    LCD_WR_CLR     gpio_set_value(st7789dev.wr, 0)
#define    LCD_RD_CLR     gpio_set_value(st7789dev.rd, 0)

#define LCD_W 240
#define LCD_H 240

int st7789_gpio_request(struct st7789_dev *dev);
void Lcd_Init(void);
void LCD_Clear(uint16_t Color);


#endif

st7789bus.c

#include "st7789bus.h"

/*中景园复制粘贴修修改改*/

int st7789_gpio_request(struct st7789_dev *dev)
{
    int ret=1;
    int i;
    char name[10];
    dev->node = of_find_node_by_path("/st7789");
    if(dev->node == NULL){
        printk("tree_node is not find\r\n");
        return -EINVAL;
    }

    dev->res = of_get_named_gpio(dev->node, "res-gpios", 0);
    if(dev->res < 0){
        printk("can not get res-gpios\r\n");
    }
    dev->cs = of_get_named_gpio(dev->node, "cs-gpios", 0);
    if(dev->cs < 0){
        printk("can not get cs-gpios\r\n");
        ret = -EINVAL;
    }
    dev->dc = of_get_named_gpio(dev->node, "dc-gpios", 0);
    if(dev->dc < 0){
        printk("can not get dc-gpios\r\n");
        ret = -EINVAL;
    }
    dev->wr = of_get_named_gpio(dev->node, "wr-gpios", 0);
    if(dev->wr < 0){
        printk("can not get wr-gpios\r\n");
        ret = -EINVAL;
    }
    dev->rd = of_get_named_gpio(dev->node, "rd-gpios", 0);
    if(dev->rd < 0){
        printk("can not get rd-gpios\r\n");
        ret = -EINVAL;
    }
    for(i=0;i<8;i++){
        dev->db[j] = of_get_named_gpio(dev->node, "db-gpios", i);
        if(dev->db[j] < 0){
            printk("can not get db[%d]-gpios\r\n",i);
            ret = -EINVAL;
        }
    }
    if(ret != -EINVAL){
        printk("res:%d cs:%d dc:%d wr:%d rd:%d\r\n", dev->res, dev->cs, dev->dc, dev->wr, dev->rd);
        for(i=0;i<8;i++){
            printk("db[%d]:%d", i, dev->db[j]);
        }
    }

    gpio_request(dev->res, "res");
    gpio_direction_output(dev->res, 0);
    gpio_request(dev->cs, "cs");
    gpio_direction_output(dev->cs, 0);
    gpio_request(dev->dc, "dc");
    gpio_direction_output(dev->dc, 0);
    gpio_request(dev->wr, "wr");
    gpio_direction_output(dev->wr, 0);
    gpio_request(dev->rd, "rd");
    gpio_direction_output(dev->rd, 0);

    for(i=0;i<8;i++){
        sprintf(name,"db%d",i);
        gpio_request(dev->db[j], name);
        gpio_direction_output(dev->db[j], 0);
    }

    return ret;
}

void data_out(struct st7789_dev dev, uint8_t dat)
{
    int i;
    for(i=0;i<8;i++){
        gpio_set_value(dev.db[j],dat&0x01);
        dat = dat>>1;
    }
}

/******************************************************************************
      函数说明:LCD 8位并口数据写入函数
      入口数据:dat  要写入的并行数据
      返回值:  无
******************************************************************************/
void LCD_Writ_Bus(uint8_t dat) 
{    
    LCD_CS_CLR;
    LCD_RD_SET;
    LCD_WR_CLR;
    data_out(st7789dev, dat);
    LCD_WR_SET;
    LCD_CS_SET;
}


/******************************************************************************
      函数说明:LCD写入数据
      入口数据:dat 写入的数据
      返回值:  无
******************************************************************************/
void LCD_WR_DATA8(uint8_t dat)
{
    LCD_DC_SET;//写数据
    LCD_Writ_Bus(dat);
}


/******************************************************************************
      函数说明:LCD写入数据
      入口数据:dat 写入的数据
      返回值:  无
******************************************************************************/
void LCD_WR_DATA(uint16_t dat)
{
    LCD_DC_SET;//写数据
    LCD_Writ_Bus(dat>>8);
    LCD_Writ_Bus(dat);
}


/******************************************************************************
      函数说明:LCD写入命令
      入口数据:dat 写入的命令
      返回值:  无
******************************************************************************/
void LCD_WR_REG(uint8_t dat)
{
    LCD_DC_CLR;//写命令
    LCD_Writ_Bus(dat);
}

/******************************************************************************
      函数说明:设置起始和结束地址
      入口数据:x1,x2 设置列的起始和结束地址
                y1,y2 设置行的起始和结束地址
      返回值:  无
******************************************************************************/
void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2)
{
    LCD_WR_REG(0x2a);//列地址设置
    LCD_WR_DATA(x1);
    LCD_WR_DATA(x2);
    LCD_WR_REG(0x2b);//行地址设置
    LCD_WR_DATA(y1);
    LCD_WR_DATA(y2);
    LCD_WR_REG(0x2c);//储存器写
}



// int Lcd_Test(struct st7789_dev dev)
// {
//     int ret;

//     LCD_WR_REG(0x04); //read id
//     /*移植中景园发现画屏
//     增加时序延迟不行画屏
//     怀疑时序出错但是这个是移植大概率不会有问题
//     阅读datasheet的8080时序发现好像没啥问题画屏就算有反应
//     准备读id看时序发现原来LCD_Writ_Bus里没有禁止读LCD_RD_SET;
//     加上就行了
//     */

//     return ret;
// }

/******************************************************************************
      函数说明:LCD初始化函数
      入口数据:无
      返回值:  无
******************************************************************************/
void Lcd_Init(void)
{
    LCD_RST_CLR;
    mdelay(200);
    LCD_RST_SET;
    mdelay(200);
    
//************* Start Initial Sequence **********// 
    LCD_WR_REG(0x01);
    mdelay(200);

    LCD_WR_REG(0x36); 
    LCD_WR_DATA8(0x00);

    LCD_WR_REG(0x3A); 
    LCD_WR_DATA8(0x05);

    LCD_WR_REG(0xB2);
    LCD_WR_DATA8(0x0C);
    LCD_WR_DATA8(0x0C);
    LCD_WR_DATA8(0x00);
    LCD_WR_DATA8(0x33);
    LCD_WR_DATA8(0x33); 

    LCD_WR_REG(0xB7); 
    LCD_WR_DATA8(0x35);  

    LCD_WR_REG(0xBB);
    LCD_WR_DATA8(0x19);

    LCD_WR_REG(0xC0);
    LCD_WR_DATA8(0x2C);

    LCD_WR_REG(0xC2);
    LCD_WR_DATA8(0x01);

    LCD_WR_REG(0xC3);
    LCD_WR_DATA8(0x12);   

    LCD_WR_REG(0xC4);
    LCD_WR_DATA8(0x20);  

    LCD_WR_REG(0xC6); 
    LCD_WR_DATA8(0x0F);    

    LCD_WR_REG(0xD0); 
    LCD_WR_DATA8(0xA4);
    LCD_WR_DATA8(0xA1);

    LCD_WR_REG(0xE0);
    LCD_WR_DATA8(0xD0);
    LCD_WR_DATA8(0x04);
    LCD_WR_DATA8(0x0D);
    LCD_WR_DATA8(0x11);
    LCD_WR_DATA8(0x13);
    LCD_WR_DATA8(0x2B);
    LCD_WR_DATA8(0x3F);
    LCD_WR_DATA8(0x54);
    LCD_WR_DATA8(0x4C);
    LCD_WR_DATA8(0x18);
    LCD_WR_DATA8(0x0D);
    LCD_WR_DATA8(0x0B);
    LCD_WR_DATA8(0x1F);
    LCD_WR_DATA8(0x23);

    LCD_WR_REG(0xE1);
    LCD_WR_DATA8(0xD0);
    LCD_WR_DATA8(0x04);
    LCD_WR_DATA8(0x0C);
    LCD_WR_DATA8(0x11);
    LCD_WR_DATA8(0x13);
    LCD_WR_DATA8(0x2C);
    LCD_WR_DATA8(0x3F);
    LCD_WR_DATA8(0x44);
    LCD_WR_DATA8(0x51);
    LCD_WR_DATA8(0x2F);
    LCD_WR_DATA8(0x1F);
    LCD_WR_DATA8(0x1F);
    LCD_WR_DATA8(0x20);
    LCD_WR_DATA8(0x23);

    LCD_WR_REG(0x21); 

    LCD_WR_REG(0x11); 
    //Delay (120); 

    LCD_WR_REG(0x29); 
} 


/******************************************************************************
      函数说明:LCD清屏函数
      入口数据:无
      返回值:  无
******************************************************************************/
void MY_LCD_WR_DATA(uint16_t Color)
{
    LCD_DC_SET;//写数据

    LCD_CS_CLR;
    LCD_RD_SET;
    LCD_WR_CLR;
    data_out(st7789dev, dat);
    LCD_WR_SET;
    LCD_CS_SET;


}


void LCD_Clear(uint16_t Color)
{
    u16 i,j;      
    LCD_Address_Set(0,0,LCD_W-1,LCD_H-1);
    for(i=0;i<LCD_W;i++)
     {
      for (j=0;j<LCD_H;j++)
           {
            //LCD_WR_DATA(Color);     里面很多多余动作
            LCD_WR_DATA(Color);

        }
      }
}




MODULE_LICENSE("GPL");
MODULE_AUTHOR("CXJ");

代码难看不太像linux的风格,只是移植能用就行
在时序上明显有可以优化的地方但是我感觉这个问他题主要还是io的操作方式

离线

楼主 #1 2022-02-02 11:18:05

摸鱼moyu
会员
注册时间: 2021-09-18
已发帖子: 41
积分: 41

Re: 关于f1c200s上模拟8080驱动st7789,慢的要命,要没有办法大佬指点下让io快起来

发帖的时候说[]i不能使用我就把i改成了j

离线

楼主 #2 2022-02-02 11:32:03

摸鱼moyu
会员
注册时间: 2021-09-18
已发帖子: 41
积分: 41

Re: 关于f1c200s上模拟8080驱动st7789,慢的要命,要没有办法大佬指点下让io快起来

看了下其他帖子感觉不好办,要直接操作寄存器还是算了,感觉要到此为止了。

离线

楼主 #3 2022-02-02 20:44:38

摸鱼moyu
会员
注册时间: 2021-09-18
已发帖子: 41
积分: 41

Re: 关于f1c200s上模拟8080驱动st7789,慢的要命,要没有办法大佬指点下让io快起来

好像晕哥看我积分少直接给我加了30,我也板子开源一下,之前只放了原理图

离线

#4 2022-02-02 21:14:45

哇酷小二
wechat微信:whycan_cn
所在地: 你猜
注册时间: 2020-04-22
已发帖子: 3,378
积分: 1902
个人网站

Re: 关于f1c200s上模拟8080驱动st7789,慢的要命,要没有办法大佬指点下让io快起来

@摸鱼moyu
摸鱼大佬新年好,8bit i80 lcd可以用官方tina sdk驱动,很流畅的。





离线

楼主 #5 2022-02-02 21:47:08

摸鱼moyu
会员
注册时间: 2021-09-18
已发帖子: 41
积分: 41

Re: 关于f1c200s上模拟8080驱动st7789,慢的要命,要没有办法大佬指点下让io快起来

哇酷小二 说:

@摸鱼moyu
摸鱼大佬新年好,8bit i80 lcd可以用官方tina sdk驱动,很流畅的。

小二新年快乐

离线

#6 2022-02-02 22:52:57

哇酷小二
wechat微信:whycan_cn
所在地: 你猜
注册时间: 2020-04-22
已发帖子: 3,378
积分: 1902
个人网站

Re: 关于f1c200s上模拟8080驱动st7789,慢的要命,要没有办法大佬指点下让io快起来

摸鱼moyu 说:
哇酷小二 说:

@摸鱼moyu
摸鱼大佬新年好,8bit i80 lcd可以用官方tina sdk驱动,很流畅的。

小二新年快乐

主线Linux的LCD TCON驱动貌似只支持HV RGB,其他都不支持。





离线

楼主 #7 2022-02-02 22:59:18

摸鱼moyu
会员
注册时间: 2021-09-18
已发帖子: 41
积分: 41

Re: 关于f1c200s上模拟8080驱动st7789,慢的要命,要没有办法大佬指点下让io快起来

哇酷小二 说:
摸鱼moyu 说:
哇酷小二 说:

@摸鱼moyu
摸鱼大佬新年好,8bit i80 lcd可以用官方tina sdk驱动,很流畅的。

小二新年快乐

主线Linux的LCD TCON驱动貌似只支持HV RGB,其他都不支持。

谢谢大佬我也就是图个学习过程的

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn