#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;
}
树莓派5 spi控制st7789 屏幕
最新推荐文章于 2025-03-15 00:24:40 发布