树莓派5 spi控制st7789 屏幕



#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/spi/spidev.h>
#include <sys/ioctl.h>
#include <string.h>

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/gpio.h>
#include <sys/ioctl.h>
#include <string.h>

#include <sys/time.h>

#define SPI_DEVICE_PATH "/dev/spidev0.0"
uint8_t tx_bf[200];



typedef struct spi_args_struct
{
    int fd;
    uint8_t tx_buffer[1000];
    uint8_t rx_buffer[1000];
    struct spi_ioc_transfer transfer;

}spi_args_s;

int api_spi_init(char * dev)
{
    int fd = 0;
    if ((fd = open(dev, O_RDWR)) < 0)
    {
        perror("Failed to open SPI device");
        return -1;
    }
    return fd;
}

int api_spi_cfg(struct spi_args_struct *spi_args_obj)
{
    /* 配置收发缓存 */
    spi_args_obj->transfer.tx_buf = (unsigned long) spi_args_obj->tx_buffer;
    spi_args_obj->transfer.rx_buf = (unsigned long) spi_args_obj->rx_buffer;

    /* Configure SPI mode and bits per word */
    uint8_t mode = SPI_MODE_2;
    uint8_t bits = 8;
    if (ioctl(spi_args_obj->fd, SPI_IOC_WR_MODE, &mode) < 0)
    {
        perror("Failed to set SPI mode");
        close(spi_args_obj->fd);
        return -1;
    }
    if (ioctl(spi_args_obj->fd, SPI_IOC_WR_BITS_PER_WORD, &bits) < 0)
    {
        perror("Failed to set SPI bits per word");
        close(spi_args_obj->fd);
        return -1;
    }
}

void api_spi_send(struct spi_args_struct *spi_args_obj, uint8_t *data, uint32_t size)
{

    spi_args_obj->transfer.len = size;
    memcpy((spi_args_obj->tx_buffer), data, spi_args_obj->transfer.len);
    //printf("Send %d bytes of data  max speed: %d Hz.\n", spi_args_obj->transfer.len, spi_args_obj->transfer.speed_hz);
    if (ioctl(spi_args_obj->fd, SPI_IOC_MESSAGE(1), &(spi_args_obj->transfer) ) < 0)
    {
        perror("Failed to perform SPI transfer");
        close(spi_args_obj->fd);
    }
}


typedef enum gpio_pin_enum
{
    GPIO_PIN_02 = 2,
    GPIO_PIN_03,
    GPIO_PIN_04,
    GPIO_PIN_05,
    GPIO_PIN_06,
    GPIO_PIN_07,
    GPIO_PIN_08,
    GPIO_PIN_09,
    GPIO_PIN_10,
    GPIO_PIN_11,
    GPIO_PIN_12,
    GPIO_PIN_13,
    GPIO_PIN_14,
    GPIO_PIN_15,
    GPIO_PIN_16,
    GPIO_PIN_17,
    GPIO_PIN_18,
    GPIO_PIN_19,
    GPIO_PIN_20,
    GPIO_PIN_21,
    GPIO_PIN_22,
    GPIO_PIN_23,
    GPIO_PIN_24,
    GPIO_PIN_25,
    GPIO_PIN_26,
    GPIO_PIN_27,
}gpio_pin_e;

typedef struct gpio_args_sruct
{
    int fd;
    struct gpiohandle_data data[27];
    struct gpiohandle_request req[27];
}gpio_args_s;
void api_gpio_init(gpio_args_s *args)
{
    // 打开设备
    args->fd = open("/dev/gpiochip0", O_RDWR | O_CLOEXEC);
}
int api_gpio_set_cfg(gpio_args_s *args, unsigned int pin_num)
{
    int ret = 0;
    struct gpiohandle_request *req = &(args->req[pin_num]);

    if(req->fd <= 0)    // 没有设置为资源才进行设置
    {
        req->lineoffsets[0] = pin_num;
        req->flags |= GPIOHANDLE_REQUEST_OUTPUT;
        req->lines = 1;
        ret = ioctl(args->fd, GPIO_GET_LINEHANDLE_IOCTL, req);
        if (ret < 0)
        {
            perror("set pin dir fled");
            return -1;
        }
    }

}

int api_gpio_set_val(gpio_args_s *args, unsigned int pin_num, int val)
{
    int ret = 0;
    struct gpiohandle_request *req = &(args->req[pin_num]);
    args->data[pin_num].values[0] = val; //设置输出电平
    ret = ioctl(req->fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &(args->data[pin_num]));
    if (ret < 0)
    {
        perror("set pin val fled");
        return -1;
    }
}

void api_gpio_close(int fd)
{
    close(fd);
}



spi_args_s spi_args_obj = 
{
    .transfer = 
    {
        .len = 10,
        .delay_usecs = 0,
        .speed_hz = 31200000, // SPI speed in Hz
        .bits_per_word = 8,
    },
};


void spi_transmit(uint8_t data)
{
    api_spi_send(&spi_args_obj, &data, 1);
}

/**
 * GPIO2 BLK
 * GPIO3 DC
 * GPIO4 RST
 */

gpio_args_s g_args;


#define CS_EN   
#define RST_EN      api_gpio_set_val(&g_args, GPIO_PIN_04, 0)
#define RST_NOT_EN  api_gpio_set_val(&g_args, GPIO_PIN_04, 1)
#define BK_EN       api_gpio_set_val(&g_args, GPIO_PIN_02, 1)
#define BK_NOT_EN   api_gpio_set_val(&g_args, GPIO_PIN_02, 0)
#define RS_CMD      api_gpio_set_val(&g_args, GPIO_PIN_03, 0)
#define RS_DAT      api_gpio_set_val(&g_args, GPIO_PIN_03, 1)

#define rt_thread_mdelay(dly) usleep(dly*1000)

void WriteComm(uint8_t cmd)
{
    RS_CMD;
    spi_transmit(cmd);
}
void WriteData(uint8_t data)
{
    RS_DAT;
    spi_transmit(data);
}



static void WriteThreeByte(uint32_t data)
{
    uint8_t dt[3];
    dt[0] = data>>16;
    dt[1] = data>>8;
    dt[2] = data;
    RS_DAT;
    api_spi_send(&spi_args_obj, dt, 3);
}

void SetDispArea(uint16_t x, uint16_t y, uint16_t width, uint16_t high)
{
    WriteComm(0x2A);  //Column Address Set  列地址设置
    WriteData(0x00);
    WriteData((uint8_t)(x));  //x:起始列
    WriteData(0x00);
    WriteData((uint8_t)(x+width)-1);  //x+width-1:结束列
    WriteComm(0x2B);
    WriteData(0x00);
    WriteData((uint8_t)(y));
    WriteData(0x00);
    WriteData((uint8_t)(y+high)-1);
    WriteComm(0x2C);
}


void LcdSetBackground(uint16_t x, uint16_t y, uint16_t width, uint16_t high, uint32_t color)
{
    uint32_t i;
    SetDispArea(x, y, width, high);
    
    for(i=0;i<width*high;i++)
    {
        WriteThreeByte(color);
    }
    
}

void LcdInit(void)
{
    RST_NOT_EN;             //复位清除
    rt_thread_mdelay(1200);        //延时 1200ms
	BK_EN;
    CS_EN;                  //片选使能
    rt_thread_mdelay(120);        //延时 120ms
    RST_EN;                 //复位
    rt_thread_mdelay(120);        //延时 120ms
    RST_NOT_EN;             //复位清除
    rt_thread_mdelay(120);         //延时 120ms
    //BK_EN;					//开启背光
    //rt_thread_mdelay(120);         //延时 120ms
    WriteComm(0x11);        // sleep mode 退出
    rt_thread_mdelay(120);         //延时 120ms
    
    WriteComm(0x36);        //Memory data access control 存储器数据访问控制
    WriteData(0x00);        //D3:1 BGR  0:RGB
    

    WriteComm(0x3A);    //Interface Pixel Format 
    WriteData(0x60);    // 05:656模式   0x66:666模式(06:262k of RGB interface,06:18bit/pixel)
    
    WriteComm(0xB2);    //Porch Setting 入口设置
    WriteData(0x0C);   
    WriteData(0x0C);   
    WriteData(0x00);   
    WriteData(0x33);   
    WriteData(0x33);   
 
    WriteComm(0xBB);   //VCOM Setting  电压设置
    WriteData(0x1F);   //1F

    WriteComm(0xC0);   //LCM Control 模块控制
    WriteData(0x2C);   

    WriteComm(0xC2);   //VDV and VRH Command Enable 
    WriteData(0x01);   

    WriteComm(0xC3);   //GVDD  VRH Set 
    WriteData(0x0F);   //4.3V   

    WriteComm(0xC4);   //VDV Set 
    WriteData(0x20);   

    WriteComm(0xC6);   //Frame Rate Control in Normal Mode 正常模式下的帧速率控制
    WriteData(0x0F);   //Dot INV, 60Hz  0F

    WriteComm(0xD0);     //Power Control 电压控制
    WriteData(0xA4);     //两组参数
    WriteData(0xA1);   

    WriteComm(0xE0);        //  Positive Voltage Gamma Control 正电压伽马控制
    WriteData(0xD0);        //  第1组参数 
    WriteData(0x0A);        //  第2组参数
    WriteData(0x10);        //  第3组参数
    WriteData(0x0A);        //  第4组参数
    WriteData(0x0A);        //  第5组参数
    WriteData(0x26);        //  ....
    WriteData(0x36);        //  ....
    WriteData(0x34);        //  ....
    WriteData(0x4D);        //  ....
    WriteData(0x18);        //  ....
    WriteData(0x13);        //  ....
    WriteData(0x14);        //  ....
    WriteData(0x2F);        //  ....
    WriteData(0x34);        //  第14组参数

    WriteComm(0xE1);        //  Negative Voltage Gamma Control 正电压伽马控制
    WriteData(0xD0);   
    WriteData(0x0A);   
    WriteData(0x10);   
    WriteData(0x0A);   
    WriteData(0x09);   
    WriteData(0x26);   
    WriteData(0x36);   
    WriteData(0x53);   
    WriteData(0x4C);   
    WriteData(0x18);   
    WriteData(0x14);   
    WriteData(0x14);   
    WriteData(0x2F);   
    WriteData(0x34);   

    WriteComm(0x21);        //Display inversion on 颠倒显示开

    WriteComm(0x2A);        //Column Address Set  列地址设置
    WriteData(0x00);   
    WriteData(0x00);        //0:起始列
    WriteData(0x00);   
    WriteData(0xEF);        //239:结束列

    WriteComm(0x2B);        //Row Address Set  行地址设置
    WriteData(0x00);   
    WriteData(0x00);        //0:起始行
    WriteData(0x00);   
    WriteData(0xEF);        //239:结束行

    WriteComm(0x29);        // Display on 打开显示

    rt_thread_mdelay(120);         //延迟时间ms
    
}



int main()
{
    api_gpio_init(&g_args);
    api_gpio_set_cfg(&g_args, GPIO_PIN_02);
    api_gpio_set_cfg(&g_args, GPIO_PIN_03);
    api_gpio_set_cfg(&g_args, GPIO_PIN_04);

    /* Open the SPI device */
    spi_args_obj.fd = api_spi_init(SPI_DEVICE_PATH);

    /* Configure SPI mode and bits per word */
    api_spi_cfg(&spi_args_obj);



    /* Send Data */
    LcdInit();

    
    int i;


    struct timeval start, end;
   



    while(1)
    {
        printf("code is running:%d\n", i++);
        
        gettimeofday(&start, NULL);
        LcdSetBackground(0,0,240,240,0xff0000);
        LcdSetBackground(0,0,240,240,0x00ff00);
        LcdSetBackground(0,0,240,240,0x0000ff);
    
        gettimeofday(&end, NULL);
        long time_usec = 1000000 * (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec);
        printf("运行时间: %ld微秒\n", time_usec);
    }

    /* Close the SPI device */
    close(spi_args_obj.fd);

    return 0;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值