完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
看RM970原理图得知LCD中IM0 IM1 ID0都接上了GND,查LCD(控制器为SPFD5420A)得知,此时LCD工作于18bit,80-system.既为最常见的MCU接口.所以配置RK2706来说是这么一个通用流程: 1.设置相应引脚为LCD功能 void iomux_lcd(void) { unsigned long muxa; muxa = SCU_IOMUXA_CON & ~(IOMUX_LCD_VSYNC|IOMUX_LCD_DEN|0xff); muxa |= IOMUX_LCD_D18|IOMUX_LCD_D20|IOMUX_LCD_D22|IOMUX_LCD_D17|IOMUX_LCD_D16; SCU_IOMUXA_CON = muxa; SCU_IOMUXB_CON |= IOMUX_LCD_D815; } 2.设置LCD寄存器,配置时序. void lcdctrl_init(void) { /* alpha b111 * stop at current frame complete * MCU mode * 24b RGB */ LCDC_CTRL = ALPHA(7) | LCDC_STOP | LCDC_MCU | RGB24B; MCU_CTRL = ALPHA_BASE(0x3f) | MCU_CTRL_BYPASS; HOR_ACT = 400 + 3; /* define horizonatal active region */ VERT_ACT = 240; /* define vertical active region */ VERT_PERIOD = 0xfff; /* CSn/WEn/RDn signal timings */ LINE0_YADDR = LINE_ALPHA_EN | 0x7fe; LINE1_YADDR = LINE_ALPHA_EN | ((1 * 400) - 2); LINE2_YADDR = LINE_ALPHA_EN | ((2 * 400) - 2); LINE3_YADDR = LINE_ALPHA_EN | ((3 * 400) - 2); LINE0_UVADDR = 0x7fe + 1; LINE1_UVADDR = ((1 * 400) - 2 + 1); LINE2_UVADDR = ((2 * 400) - 2 + 1); LINE3_UVADDR = ((3 * 400) - 2 + 1); LCDC_INTR_MASK = INTR_MASK_LINE; /* INTR_MASK_EVENLINE; */ } 3.初始化LCD寄存器. void lcd_init_device() { unsigned int x, y; iomux_lcd(); /* setup pins for 18bit lcd interface */ lcdctrl_init(); /* basic lcdc module configuration */ lcdctrl_bypass(1); /* run in bypass mode - all writes goes directly to lcd controller */ lcd_write_reg(RESET, 0x0001); delay_nop(10000); lcd_write_reg(RESET, 0x0000); delay_nop(10000); lcd_write_reg(IF_ENDIAN, 0x0000); /* order of receiving data */ lcd_write_reg(DRIVER_OUT_CTRL, 0x0000); lcd_write_reg(ENTRY_MODE, 0x1038); lcd_write_reg(WAVEFORM_CTRL, 0x0100); lcd_write_reg(SHAPENING_CTRL, 0x0000); lcd_write_reg(DISPLAY_CTRL2, 0x0808); lcd_write_reg(LOW_PWR_CTRL1, 0x0001); lcd_write_reg(LOW_PWR_CTRL2, 0x0010); lcd_write_reg(EXT_DISP_CTRL1, 0x0000); lcd_write_reg(EXT_DISP_CTRL2, 0x0000); lcd_write_reg(BASE_IMG_SIZE, 0x3100); ...................... } 细心的朋友会发现这些寄存器初始值都为16bit,而LCD为18bit,所以得用下面函数转换成18bit后才能写给LCD. __inline unsigned int lcd_data_transform(unsigned int data) { /* 18 bit interface */ unsigned int r, g, b; r = (data & 0x0000fc00)<<8; g = ((data & 0x00000300) << 6) | ((data & 0x000000e0) << 5); b = (data & 0x00000001f) << 3; return (r | g | b); } 初试化完毕后,一个不约而同的规则便是实现画横竖线与打点了. /* 画水平线 */ void rt_hw_lcd_draw_hline(rtgui_color_t *c, rt_base_t x1, rt_base_t x2, rt_base_t y) { lcd_write_reg(WINDOW_H_START, y); lcd_write_reg(WINDOW_H_END, y); lcd_write_reg(WINDOW_V_START, x1); lcd_write_reg(WINDOW_V_END, x2); lcd_write_reg(GRAM_H_ADDR, y); lcd_write_reg(GRAM_V_ADDR, x1); lcd_cmd(GRAM_WRITE); /* Prepare to write GRAM */ while (x1 < x2) { LCD_DATA = lcd_pixel_transform(*c); x1++; } } /* 垂直线 */ void rt_hw_lcd_draw_vline(rtgui_color_t *c, rt_base_t x, rt_base_t y1, rt_base_t y2) { lcd_write_reg(WINDOW_H_START, y1); lcd_write_reg(WINDOW_H_END, y2); lcd_write_reg(WINDOW_V_START, x); lcd_write_reg(WINDOW_V_END, x); lcd_SetCursor(x, y1); lcd_cmd(GRAM_WRITE); /* Prepare to write GRAM */ while (y1 < y2) { LCD_DATA = lcd_pixel_transform(*c); y1++; } } /* 设置像素点 颜色,X,Y */ void rt_hw_lcd_set_pixel(rtgui_color_t *c, rt_base_t x, rt_base_t y) { lcd_write_reg(WINDOW_H_START, y); lcd_write_reg(WINDOW_H_END, y); lcd_write_reg(WINDOW_V_START, x); lcd_write_reg(WINDOW_V_END, x); lcd_SetCursor(x,y); lcd_cmd(GRAM_WRITE); LCD_DATA = lcd_pixel_transform(*c); } 注意这SPFD5420A打点函数与常见的控制器还不一样,还要设置窗口为此点.要不然会有些莫名奇妙的问题.(起码这边测试的是这样). 实现打点函数后便可以将printf定位到LCD了,新建Retarget.c文件,在里面实现fputc()函数 int fputc(int ch, FILE *f) { int MaxX = 400 / 6; int MaxY = 240 / 12; int n; if(ch != ' ' && ch != ' ' && ch != '') { lcd_show_char(CurrentX*6, ((CurrentY + MaxY)%MaxY)*12, ch); } CurrentX++; return 1; } 这里并没考虑更多情况,请各位按需要自行改进. 最后顺便在rtthread.h加上: #define rt_kprintf printf 两个应该注意的地方.一是记得开背光,二是Options-Target-Use Micro LIB选项记得勾上,而且启动代码中Micro_Lib_Stack_Size宏大小最好相应改大. 如无意外printf,与rt_kprintf都已经定位到LCD了. |
|
相关推荐
3个回答
|
|
也可以去实现下RTT的console,这样可以不用做rt_kprintf到printf的转换,然后使用printf
不过默认在RTT下还真不能够使用printf (Keil MDK),需要实现一些retarget.c中的函数。实现retarget.c还是非常有好处的,这样可以使用Keil MDK中提供的libc大部分功能,对于程序移植非常有帮助(就好比GNU GCC上实现newlib c库的移植)。 |
|
|
|
非常感谢楼主分享大量的研究结果和心得。有个地方很纠结,就是那个转换函数。
1. 不知道理解对不对,该函数是 将数据 D15D14D13D12 D11D10D9D8 D7D6D5D4 D3D2D1D0 转换成 0000 0000 D15D14D13D12 D11D10 0 0 D9 D8 0 D7 D6 D5 00 D4D3D2D1 D0 000 估计是RGB888的吧?排版很麻烦, 2.不理解为什么配置5420的寄存器(16位,丢掉D0和D9)要换成上述的格式。 根据5420的datasheet,转换方式应该是D15-D8左移2位,D7-D0左移1位。 3.根据RM970的原理图,D17,16是打乱顺序的,SDK的RK27换屏指南说,18位屏采用全部18根数据线时必须这样连接,纠结这个“必须”,更纠结用这种数据线连接顺序并采用原数据转换方式,配置lcd驱动寄存器又是怎样得到正确的结果的呢? 4.另外能请楼主推荐个单步调试方法,想用来验证一下数据的,不知楼主现在有没有空,能进一步弄出视频就完美了。 向楼主学习。 |
|
|
|
这个没细究,因为我也是拿来主义,直接copy了Rockbox的代码,当然Rockbox rk2706部分也是来自SDK。关于所说的调试问题,是不可能有单步调试的了,或者说怎么可能有呢?一个rt_kprintf足以。开源固件的工程个人觉得已经很方便了,配置好了只要点击编译就秒下到播放器并且运行。关于这播放器的问题,也只能靠记忆了,因为与现在的工作一点也不相干,也会有一段时间(或者更长)与RT-Thread无缘。
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
AI模型部署边缘设备的奇妙之旅:如何在边缘端部署OpenCV
1209 浏览 0 评论
tms320280021 adc采样波形,为什么adc采样频率上来波形就不好了?
1058 浏览 0 评论
1444 浏览 0 评论
1371 浏览 0 评论
1023 浏览 0 评论
74575 浏览 21 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-18 09:57 , Processed in 0.691796 second(s), Total 74, Slave 58 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号