在线时间68 小时
UID2029919
注册时间2014-9-24
NXP金币0
该用户从未签到
中级会员
 
- 积分
- 444
- 最后登录
- 2019-3-7
|
本帖最后由 晓枫VS枯叶 于 2015-11-19 11:31 编辑
刚画了块K64的板子,然而上电调试后发现各种各样硬件问题亟待解决,不过幸好LCD部分能正常工作。之前对飞卡的硬件不熟悉,板子设计时SPI FLASH和外扩的SRAM都出现问题,跑emwin只能使用内置的192K的SRAM,不过有这么大的RAM跑emwin的demo并不卡,只是512K的FLASH并不能跑完所有的demo。 首先移植emwin要写好你所用的LCD的驱动,我的LCD驱动芯片是NT35510,然后这个芯片对应的初始化过程就去看一些例程或者数据手册了。然后我的LCD和K64的连接采用了K64的16bit的Flexbus(类似ST的FMSC),具体硬件连线如下图(还好这个接口没又画错)
只用到了30针的接口,后面D16-D23这8位可以不用,所以是RGB565模式,初始化Flexbus函数如下:
- void init_fb_pins(uint32_t instance)
- {
- /* Affects PORTA_PCR26 register */
- PORT_HAL_SetMuxMode(PORTA,26UL,kPortMuxAlt6);
- /* Affects PORTD_PCR6 register */
- PORT_HAL_SetMuxMode(PORTD,6UL,kPortMuxAlt5);
- /* Affects PORTD_PCR5 register */
- PORT_HAL_SetMuxMode(PORTD,5UL,kPortMuxAlt5);
- /* Affects PORTD_PCR4 register */
- PORT_HAL_SetMuxMode(PORTD,4UL,kPortMuxAlt5);
- /* Affects PORTD_PCR3 register */
- PORT_HAL_SetMuxMode(PORTD,3UL,kPortMuxAlt5);
- /* Affects PORTD_PCR2 register */
- PORT_HAL_SetMuxMode(PORTD,2UL,kPortMuxAlt5);
- /* Affects PORTC_PCR10 register */
- PORT_HAL_SetMuxMode(PORTC,10UL,kPortMuxAlt5);
- /* Affects PORTC_PCR9 register */
- PORT_HAL_SetMuxMode(PORTC,9UL,kPortMuxAlt5);
- /* Affects PORTC_PCR8 register */
- PORT_HAL_SetMuxMode(PORTC,8UL,kPortMuxAlt5);
- /* Affects PORTC_PCR7 register */
- PORT_HAL_SetMuxMode(PORTC,7UL,kPortMuxAlt5);
- /* Affects PORTC_PCR6 register */
- PORT_HAL_SetMuxMode(PORTC,6UL,kPortMuxAlt5);
- /* Affects PORTC_PCR5 register */
- PORT_HAL_SetMuxMode(PORTC,5UL,kPortMuxAlt5);
- /* Affects PORTC_PCR4 register */
- PORT_HAL_SetMuxMode(PORTC,4UL,kPortMuxAlt5);
- /* Affects PORTC_PCR2 register */
- PORT_HAL_SetMuxMode(PORTC,2UL,kPortMuxAlt5);
- /* Affects PORTC_PCR1 register */
- PORT_HAL_SetMuxMode(PORTC,1UL,kPortMuxAlt5);
- /* Affects PORTC_PCR0 register */
- PORT_HAL_SetMuxMode(PORTC,0UL,kPortMuxAlt5);
- /* Affects PORTB_PCR18 register */
- PORT_HAL_SetMuxMode(PORTB,18UL,kPortMuxAlt5);
- /* Affects PORTD_PCR1 register */
- PORT_HAL_SetMuxMode(PORTD,1UL,kPortMuxAlt5);
- /* Affects PORTB_PCR19 register */
- PORT_HAL_SetMuxMode(PORTB,19UL,kPortMuxAlt5);
- /* Affects PORTC_PCR11 register */
- PORT_HAL_SetMuxMode(PORTC,11UL,kPortMuxAlt5);
- //PORT_HAL_SetMuxMode(PORTC,12UL,kPortMuxAsGpio);
- //PORT_HAL_SetMuxMode(PORTC,13UL,kPortMuxAsGpio);
- PORT_HAL_SetMuxMode(PORTC,27UL,kPortMuxAsGpio);
- PORT_HAL_SetMuxMode(PORTD,0UL,kPortMuxAsGpio);
- gpio_output_pin_user_config_t outputPin[] = {
- {
- .pinName = GPIO_MAKE_PIN(GPIOE_IDX, 27U),
- .config.outputLogic = 1,
- .config.slewRate = kPortFastSlewRate,
- .config.driveStrength = kPortHighDriveStrength,
- .config.isOpenDrainEnabled=0,
- },
- };
- GPIO_DRV_OutputPinInit( outputPin);
- }
复制代码 以上是IO的初始化,我直接拿KDS里的PE生成的,还是比较好用的,接下来是LCD时序的初始化,Flexbus驱动LCD时,可以将LCD看做一个静态的RAM使用,具体配置如下:
- flexbus_user_config_t flexBus1_InitConfig0 = {
- .chip = 0U,
- .waitStates = 1U,
- .baseAddress = LCD_BASE,
- .baseAddressMask =0x800U,
- .writeProtect = false,
- .burstWrite = false,
- .burstRead = false,
- .byteEnableMode = false,
- .autoAcknowledge = true,
- .extendTransferAddress = false,
- .secondaryWaitStates = false,
- .portSize = kFlexbus2bytes,
- .byteLaneShift = kFlexbusShifted,
- .writeAddressHold = kFlexbusHold1cycle,
- .readAddressHold = kFlexbusHold1or0cycle,
- .addressSetup = kFlexbusFirstRisingEdge,
- };
- init_fb_pins(FB_IDX);
- FLEXBUS_DRV_Init(FSL_FLEXBUS1,&flexBus1_InitConfig0);
- PEout(27)=1;
复制代码 PTE27这个IO被我拉到了LCD的背光上去,这里使用了位带操作比较简单。其中注意Flexbus的地址不要超出范围,具体看参考手册,我这里设置的是#define LCD_BASE (0x70000000),然后是地址mask的配置,然后是读写时序配置,位宽就是2字节,还有就是数据格式,最后时序我都设置的最快(毕竟NT35510还是比较给力的)。
底层传输接口配置完了就要开始配置LCD的读写,主要还是两个地址,命令和数据的区分
- #define LCD_CMD_BASE (0x70000000)
- #define LCD_DATA_BASE (0x78000000)
复制代码 然后命令写入和数据读写就主要操作这两个地址了,具体操作见附件源码。 之前玩STM32F4时发现正点原子的参考程序里面有支持NT35510的驱动,果断放弃自己去一步步写,直接照搬过来,由于原子的LCD驱动为了兼容多个屏幕写的非常多,然而我只用一个屏,所以直接将里面多余的东西完全精简掉了,只支持NT35510的屏,驱动供大家参考学习。
还有一点就是原子NT35510的屏幕是800*480的分辨率,我这个屏幕是854*480,需要修改初始化时的分辨率设置寄存器的值,B500h写入5Bh对应854*480的分辨率。
LCD驱动搞好了就可以玩裸屏,可以测试下能不能用,首先驱动里会先读取LCD的ID,然后串口输出LCD的ID,再去初始化LCD。好了LCD驱动搞好了之后就是开始移植emwin了,这里我使用的是IAR编译器,网上找了好长时间的emwin库才找到一个IAR的(并没有用STM32里stemwin支持IAR的库),移植的时候我先搞了一个动态内存管理,方面emwin里使用,下面是支持keil和IAR的几个四字节对齐内存管理的定义
- //内存池(4字节对齐)
- #if defined ( __CC_ARM )
- __align(4) u8 mem1base[MEM1_MAX_SIZE]; //内部SRAM内存池
- //__align(4) u8 mem2base[MEM2_MAX_SIZE] __attribute__((at(0XD0000000))); //外部SRAM内存池
- //__align(4) u8 mem3base[MEM3_MAX_SIZE] __attribute__((at(0X10000000))); //内部CCM内存池
- //内存管理表
- u16 mem1mapbase[MEM1_ALLOC_TABLE_SIZE]; //内部SRAM内存池MAP
- //u16 mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((at(0XD0000000+MEM2_MAX_SIZE))); //外部SRAM内存池MAP
- //u16 mem3mapbase[MEM3_ALLOC_TABLE_SIZE] __attribute__((at(0X10000000+MEM3_MAX_SIZE))); //内部CCM内存池MAP
- #endif
- #if defined ( __ICCARM__ )
- #pragma pack(push)
- #pragma pack(4) //按字节对齐
- __no_init u8 mem1base[MEM1_MAX_SIZE]; //内部SRAM内存池
- // __no_init u8 mem2base[MEM2_MAX_SIZE] @(0XD0100000); //外部SRAM内存池
- //__no_init u8 mem3base[MEM3_MAX_SIZE] @(0X10000000); //内部CCM内存池
- #pragma pack(pop)
- u16 mem1mapbase[MEM1_ALLOC_TABLE_SIZE]; //内部SRAM内存池MAP
- //u16 mem2mapbase[MEM2_ALLOC_TABLE_SIZE] @(0XD0100000+MEM2_MAX_SIZE); //外部SRAM内存池MAP
- //u16 mem3mapbase[MEM3_ALLOC_TABLE_SIZE] @(0X10000000+MEM3_MAX_SIZE); //内部CCM内存池MAP
- #endif //内存总大小
- const u32 memtblsize[SRAMBANK]={MEM1_ALLOC_TABLE_SIZE}; //内存表大小
- const u32 memblksize[SRAMBANK]={MEM1_BLOCK_SIZE}; //内存分块大小
- const u32 memsize[SRAMBANK]={MEM1_MAX_SIZE}; //内存总大小
复制代码 具体还是参考正点原子的内存管理源码,只是移植到了IAR编译器里使用,由于外部SRAM的硬件问题,只能屏蔽掉外部SRAM的内存管理,只使用内部SRAM内存管理。emwin底层也是照搬的正点原子的源码,移植过程见正点原子STemwin教程,具体修改下面的代码(主要是快速画位图):
- static void _DrawBitLine16BPP(GUI_DEVICE * pDevice, int x, int y, U16 const GUI_UNI_PTR * p, int xsize) {
- LCD_PIXELINDEX pixel;
- LCD_Set_Cursor(x,y);
- *(__IO uint16_t *)(LCD_CMD_BASE) = lcddev.wramcmd; //写入颜色值
- for (;xsize > 0; xsize--, x++, p++)
- {
- pixel = *p;
- *(__IO uint16_t *)(LCD_DATA_BASE) =pixel;
- }
- }
复制代码 最后就是emwin时基的配置,由于没有操作系统,不能上系统的时钟,所以我使用一个通道的PIT产生1ms中断作为emwin时基
- void PIT_Init(uint32_t us)
- {
- pit_user_config_t chn0Confg;
- chn0Confg.isInterruptEnabled= true;
- chn0Confg.periodUs=us;
- // Init pit module and enable run in debug
- PIT_DRV_Init(BOARD_PIT_INSTANCE, false);
- // Initialize PIT timer instance for channel 0 and 1
- PIT_DRV_InitChannel(BOARD_PIT_INSTANCE, 0, &chn0Confg);
- //PIT_DRV_InitChannel(BOARD_PIT_INSTANCE, 1, &chn1Confg);
- // Start channel 0
- PIT_DRV_StartTimer(BOARD_PIT_INSTANCE, 0);
- us_time=0;
- // Start channel 1
- // PIT_DRV_StartTimer(BOARD_PIT_INSTANCE, 1);
- }
- void PIT0_IRQHandler(void)
- {
- if(PIT_HAL_IsIntPending(g_pitBase[0], 0))
- {
- us_time++;
- OS_TimeMS++;
- PIT_HAL_ClearIntFlag(g_pitBase[0], 0U);
- }
- }
复制代码 以供emwin使用,到此在主函数里启动初始化emwin之后运行demo就能看到emwin的效果了
- int main(void)
- {
- // Configure board specific pin muxing
- OSA_Init();
- hardware_init();
- delay_init(120);
- PIT_Init(1000);
- FLEXBUS_LCD_Init();
- mem_init(SRAMIN);
- CLOCK_SYS_EnableCrcClock(0);
- WM_SetCreateFlags(WM_CF_MEMDEV);
- GUI_Init();
- GUIDEMO_Main();
- for (;;) // Forever loop
- {
- __asm("NOP");
- }
- }
复制代码 最后上几张飞卡K64跑emwin的图,由于直接拷贝的是STemwin里的demo,所以很多ST的logo,见谅了:
裸机刷屏有1100W,只能说还不错吧,比较不是LCD专用的MCU,由于室内灯光不好,正好头顶两个大灯导致屏幕严重反光,实际效果还是 很给力的,只是在海豚那个界面有一点明显的残影,其他的效果挺好的,毕竟这么高的分辨率嘛,最后emwin例程如下,里面keil的工程没有搞,只是用飞卡的那个生成器生成了放在那里,并且keil的库也没加进去(主要由于keil编译资源占用太多,而且速度慢所以没有使用),IAR的emwin库里面有两个,不知道那两个库的区别在哪里。
emwin.zip
(9.47 MB, 下载次数: 179)
|
评分
-
查看全部评分
|