zynq驱动SPI ST7735S LCD

张开发
2026/4/18 12:36:47 15 分钟阅读

分享文章

zynq驱动SPI ST7735S LCD
参考树莓派Pico驱动SPI ST7735S LCD.csdnPS 硬件 SPI 主机访问 W25Q16.csdnBDsystem.tcl注意事项Vivado 自动生成了两个未使用的片选信号。请在 system_wrapper.v 文件中删除与这两个片选相关的代码以避免综合报错。未使用的片选信号包括output SPI_0_0_ss1_o;output SPI_0_0_ss2_o;PIN.xdc## SPI SCLKset_property PACKAGE_PIN M15[get_ports SPI_0_0_sck_io]set_property IOSTANDARD LVCMOS33[get_ports SPI_0_0_sck_io]## SPI MOSIset_property PACKAGE_PIN L16[get_ports SPI_0_0_io0_io]set_property IOSTANDARD LVCMOS33[get_ports SPI_0_0_io0_io]## SPI MISOset_property PACKAGE_PIN K14[get_ports SPI_0_0_io1_io]set_property IOSTANDARD LVCMOS33[get_ports SPI_0_0_io1_io]## SPI CSset_property PACKAGE_PIN J14[get_ports SPI_0_0_ss_io]set_property IOSTANDARD LVCMOS33[get_ports SPI_0_0_ss_io]## DCset_property PACKAGE_PIN N20[get_ports{GPIO_EMIO_tri_io[0]}]set_property IOSTANDARD LVCMOS33[get_ports{GPIO_EMIO_tri_io[0]}]## RESset_property PACKAGE_PIN U19[get_ports{GPIO_EMIO_tri_io[1]}]set_property IOSTANDARD LVCMOS33[get_ports{GPIO_EMIO_tri_io[1]}]裸机驱动main.c#includexparameters.h#includexspips.h#includexgpiops.h#includesleep.h#includexil_printf.h/* * 硬件配置区域 *--------------------------------------------------------- * 这里定义的是 ZYNQ PS 侧外设资源 * - SPI 使用 PS SPI0 * - GPIO 使用 EMIO从 PL 引出来的 IO **/#defineSPI_DEVICE_IDXPAR_XSPIPS_0_DEVICE_ID#defineGPIO_DEVICE_IDXPAR_XGPIOPS_0_DEVICE_ID/* * EMIO 引脚映射 *--------------------------------------------------------- * PIN_DC 数据/命令选择信号DC * PIN_RES LCD 复位信号RESET * * 注意 * 这两个引脚来自 PL → PS EMIO 映射 * 对应 Vivado 里 GPIO_EMIO_tri_io[x] **/#definePIN_DC54// EMIO[0]#definePIN_RES55// EMIO[1]/* * LCD 逻辑分辨率与偏移 *--------------------------------------------------------- * LCD_W / LCD_H 逻辑可用显示区域 * LCD_XOFF / YOFFST7735 内部显存偏移非常关键 * * 原因 * ST7735 实际 GRAM 比显示区域大需要 offset 对齐 **/#defineLCD_W80#defineLCD_H160#defineLCD_XOFF26#defineLCD_YOFF1/* * 全局外设句柄 *--------------------------------------------------------- * Spi SPI 控制器实例 * Gpio EMIO GPIO 控制器实例 **/staticXSpiPs Spi;staticXGpioPs Gpio;/* * GPIO 控制函数DC / RES *--------------------------------------------------------- * DC 0 - 命令模式 * DC 1 - 数据模式 * * RES 0 - LCD 复位 * RES 1 - LCD 正常工作 **/staticinlinevoiddc_cmd(){XGpioPs_WritePin(Gpio,PIN_DC,0);}staticinlinevoiddc_data(){XGpioPs_WritePin(Gpio,PIN_DC,1);}staticinlinevoidres_low(){XGpioPs_WritePin(Gpio,PIN_RES,0);}staticinlinevoidres_high(){XGpioPs_WritePin(Gpio,PIN_RES,1);}/* * SPI 底层发送函数阻塞模式 *--------------------------------------------------------- * 使用 PolledTransfer * - CPU 阻塞等待发送完成 * - 适合 LCD 这种低速外设 **/staticinlinevoidspi_write(u8*buf,intlen){XSpiPs_PolledTransfer(Spi,buf,NULL,len);}/* * LCD 写命令 *--------------------------------------------------------- * 流程 * 1. DC 0命令 * 2. SPI 发送 1 byte **/staticvoidlcd_cmd(u8 cmd){dc_cmd();spi_write(cmd,1);}/* * LCD 写数据 *--------------------------------------------------------- * 流程 * 1. DC 1数据 * 2. SPI 发送 1 byte **/staticvoidlcd_data(u8 data){dc_data();spi_write(data,1);}/* * LCD 硬件复位 *--------------------------------------------------------- * 时序要求 * RES 拉低 ≥10ms * RES 拉高后等待 ≥120ms * * 这是 ST7735 启动稳定关键步骤 **/staticvoidlcd_reset(){res_low();usleep(20000);// 保证复位时间充足res_high();usleep(120000);// 等待内部振荡器稳定}/* * 设置显示窗口核心函数 *--------------------------------------------------------- * 功能 * 指定 LCD GRAM 写入区域 * * ST7735 使用 3 个命令 * 0x2A - 列地址X * 0x2B - 行地址Y * 0x2C - 写显存开始 * * 注意 * 必须加 LCD_XOFF / LCD_YOFF否则图像错位 **/staticvoidlcd_set_addr(u16 x0,u16 y0,u16 x1,u16 y1){/* 加偏移硬件坐标修正 */x0LCD_XOFF;x1LCD_XOFF;y0LCD_YOFF;y1LCD_YOFF;/* * 设置列地址 **/lcd_cmd(0x2A);dc_data();u8 col[]{0,x0,0,x1};spi_write(col,4);/* * 设置行地址 **/lcd_cmd(0x2B);dc_data();u8 row[]{0,y0,0,y1};spi_write(row,4);/* * 写入 GRAM **/lcd_cmd(0x2C);}/* * LCD 初始化流程 *--------------------------------------------------------- * 初始化步骤必须严格顺序 * 1. 复位 * 2. 退出睡眠 * 3. 开启 IPS 模式 * 4. 帧率配置 * 5. 电源控制 * 6. 像素格式 * 7. 显示方向 * 8. 开显示 **/staticvoidlcd_init(){lcd_reset();lcd_cmd(0x11);// Sleep Out退出睡眠usleep(120000);// 必须等待内部稳定lcd_cmd(0x21);// IPS 显示必须开启反色控制/* * 帧率控制 **/lcd_cmd(0xB1);lcd_data(0x05);lcd_data(0x3A);lcd_data(0x3A);lcd_cmd(0xB2);lcd_data(0x05);lcd_data(0x3A);lcd_data(0x3A);lcd_cmd(0xB4);lcd_data(0x03);// 反转控制/* * 电源控制 **/lcd_cmd(0xC0);lcd_data(0x62);lcd_data(0x02);lcd_data(0x04);lcd_cmd(0xC1);lcd_data(0xC0);lcd_cmd(0xC2);lcd_data(0x0D);lcd_data(0x00);lcd_cmd(0xC5);lcd_data(0x0E);/* * 像素格式 显示方向 **/lcd_cmd(0x3A);lcd_data(0x05);// RGB565lcd_cmd(0x36);lcd_data(0xC8);// 扫描方向控制lcd_cmd(0x29);// Display ON开启显示}/* * 全屏填充颜色 *--------------------------------------------------------- * 本质 * - 设置整个窗口 * - 连续写 LCD_W * LCD_H 个像素 * * 注意 * RGB565 2 byte / pixel **/staticvoidlcd_clear(u16 color){lcd_set_addr(0,0,LCD_W-1,LCD_H-1);dc_data();// 进入数据模式u8 hicolor8;u8 locolor0xFF;for(inti0;iLCD_W*LCD_H;i){u8 d[2]{hi,lo};spi_write(d,2);}}/* * 画 8x8 字符 A *--------------------------------------------------------- * A 使用点阵 * 每一行 8bit 表示像素开关 * * fc 前景色字体颜色 * bc 背景色 **/staticvoidlcd_draw_A(u16 x,u16 y,u16 fc,u16 bc){u8 A[8]{0x18,0x24,0x42,0x7E,0x42,0x42,0x42,0x00};lcd_set_addr(x,y,x7,y7);dc_data();// 进入数据模式for(introw0;row8;row){for(intcol0;col8;col){u16 color;/* 判断当前像素是否属于字体笔画 */if(A[row](1(7-col))){colorfc;// 字体颜色}else{colorbc;// 背景颜色}u8 d[2]{color8,color0xFF};spi_write(d,2);}}}/* * 主函数 **/intmain(){xil_printf(ST7735 ZYNQ OK\r\n);/* * SPI 初始化 **/XSpiPs_Config*cfg;cfgXSpiPs_LookupConfig(SPI_DEVICE_ID);XSpiPs_CfgInitialize(Spi,cfg,cfg-BaseAddress);XSpiPs_SetOptions(Spi,XSPIPS_MASTER_OPTION|// 主机模式XSPIPS_FORCE_SSELECT_OPTION// 强制片选控制);XSpiPs_SetClkPrescaler(Spi,XSPIPS_CLK_PRESCALE_16);/* * EMIO GPIO 初始化 **/XGpioPs_Config*gcfg;gcfgXGpioPs_LookupConfig(GPIO_DEVICE_ID);XGpioPs_CfgInitialize(Gpio,gcfg,gcfg-BaseAddr);/* DC 输出配置 */XGpioPs_SetDirectionPin(Gpio,PIN_DC,1);XGpioPs_SetOutputEnablePin(Gpio,PIN_DC,1);/* RES 输出配置 */XGpioPs_SetDirectionPin(Gpio,PIN_RES,1);XGpioPs_SetOutputEnablePin(Gpio,PIN_RES,1);/* * LCD 初始化 **/lcd_init();/* * 主循环演示 **/while(1){lcd_clear(0xF800);// 红色usleep(500000);lcd_clear(0x07E0);// 绿色usleep(500000);lcd_clear(0x001F);// 蓝色usleep(500000);/* 显示字母 A */lcd_draw_A(10,20,0xFFFF,0x0000);usleep(500000);}}测试全红,全黄, 全蓝, 字母A 之间循环播放[10:22:25.989]收←◆ST7735 OK TEST[10:22:26.304]收←◆DONE[10:23:46.980]收←◆ST7735 ZYNQ OKlinux驱动内核配置确认$:grep-iSPI .config|grep-v^#CONFIG_UNINLINE_SPIN_UNLOCKy# ❌ 非必须内核锁优化CONFIG_MUTEX_SPIN_ON_OWNERy# ❌ 非必须锁优化CONFIG_RWSEM_SPIN_ON_OWNERy# ❌ 非必须锁优化CONFIG_LOCK_SPIN_ON_OWNERy# ❌ 非必须锁优化CONFIG_REGMAP_SPIy# ❌ 非必须SPI寄存器抽象框架驱动用CONFIG_MTD_SPI_NORy# ❌ 非必须SPI Flash / W25QxxCONFIG_MTD_SPI_NOR_USE_4K_SECTORSy# ❌ 非必须Flash性能优化CONFIG_SPIy# ✔ 必须SPI核心框架CONFIG_SPI_MASTERy# ✔ 必须SPI主机模式CONFIG_SPI_MEMy# ❌ 非必须SPI Flash/QSPI memory接口CONFIG_SPI_BITBANGy# ❌ 非必须GPIO模拟SPI不用CONFIG_SPI_CADENCEy# ✔ 必须Zynq PS SPI底层驱动CONFIG_SPI_XILINXy# ✔ 必须Xilinx SPI控制器支持CONFIG_SPI_ZYNQ_QSPIy# ❌ 非必须QSPI Flash启动用CONFIG_RTC_I2C_AND_SPIy# ❌ 非必须RTC相关$:grep-iFB .config|grep-v^#CONFIG_DRM_KMS_FB_HELPERy# ❌ 非必须DRM转fb兼容层用于老程序/X11CONFIG_DRM_FBDEV_EMULATIONy# ❌ 非必须DRM自动生成 /dev/fb0CONFIG_DRM_FBDEV_OVERALLOC100# ❌ 非必须fb buffer额外预分配性能参数CONFIG_FB_CMDLINEy# ❌ 非必须允许bootargs配置fb参数CONFIG_FB_NOTIFYy# ❌ 非必须fb事件通知机制CONFIG_FBy# ✔ 必须Framebuffer核心框架CONFIG_FB_CFB_FILLRECTy# ✔ 推荐矩形填充加速CONFIG_FB_CFB_COPYAREAy# ✔ 推荐显存区域拷贝CONFIG_FB_CFB_IMAGEBLITy# ✔ 推荐图像/字符绘制CONFIG_FB_SYS_FILLRECTy# ✔ 建议软件fb基础实现CONFIG_FB_SYS_COPYAREAy# ✔ 建议CONFIG_FB_SYS_IMAGEBLITy# ✔ 建议CONFIG_FB_SYS_FOPSy# ✔ 必须/dev/fb0 用户接口CONFIG_FB_DEFERRED_IOy# ⭐ 强烈推荐SPI LCD刷屏优化减少卡顿设备树ST7735S LCD 驱动测试

更多文章