电赛信号题备赛日记(1)移植正点原子STM32H750 mini pro的TFTLCD屏幕
之所以采用STM32H750的原因是因为电赛信号题要求的ADC采样频率高且STM32H750的性价比很高刚好正点原子的H750mini pro开发板的价格低但首先第一步想要用移植它的LCD屏幕就不同于我之前使用的正点原子STM32F4开发板且正点原子H750开发板的教程及驱动极其的抽象教程也没有使用CubeMX进行配置所以对想用CubeMX对这块开发板进行配置会感到陌生。因为H750的内存配置以及内部Cache都需要配置但是正点原子并没有在教程中有CubeMX相关的配置而是在驱动中对其进行配置这就会导致我们使用CubeMX生成的代码在移植正点原子的驱动过程中会报错。下面我展示第一步移植LCD屏幕首先我们先打开正点原子教程中的HAL库版本的基础入门实验中的新建工程CubeMX版本打开其中的CubeMX这样就省略了一些基础的配置首先重点我们看CubeMX中的CORTEX—M7将其配置为重点就是要打开CPU的ICache和DCache。但是不需要具体配置其内存地址因为后续直接调用驱动会快很多且不容易犯错。在其驱动中已经对其进行了配置然后我们到FMC当中H7于F4的LCD移植区别主要便是将FSMC改为FMC主要便是支持了动态存储器。在当中我们注意要看开发板的原理图我们发现正点原子是将PD7设为了FMC_NE1.我们要先将PD7配置为FMC_NE1不然默认是 PC7。但是其实这一部最主要的目的只是开始FMC引脚在正点原子的驱动中进行了重新分配。接下来配置时钟再生成文件即可。接下来我们随意打开正点原子的示例找到驱动文件其中BSP文件中的MPU和LCD文件是我们需要的以及SYSTEM文件中的这里的usart是串口文件我并没有使用而且接下来也会修改一些驱动代码所以我们并不需要这个文件里的驱动文件如果你需要使用其串口文件进行调试也可以自己配置。我们将其提取出来放到一个新建的BSP文件当中接下来将这个文件放在我们生成的项目与文件当中并且在keil5中包含这个文件打开Keil5我们接下来进行驱动的修改。在驱动文件中我们可以看到其包含了usart文件中的usart.h但是我们并不需要串口功能所以先将所有驱动文件的usart功能删除主要就是printf功能如这样的在所有驱动文件当中基本都有这个我们将其全部删除嫌麻烦我也在下方给出我修改好的文件在我们修改好驱动文件之后我们先进行编译会发现有很多报错这就是正点原子驱动和CubeMX生成文件冲突了主要原因就是正点原子在驱动当中就把CubeMX的活给提前干完了导致编译时发现有些函数定义了两遍。我们先看lcd.c当中的lcd_init函数。void lcd_init(void) { GPIO_InitTypeDef gpio_init_struct; FMC_NORSRAM_TimingTypeDef fmc_read_handle; FMC_NORSRAM_TimingTypeDef fmc_write_handle; LCD_CS_GPIO_CLK_ENABLE(); /* LCD_CS脚时钟使能 */ LCD_WR_GPIO_CLK_ENABLE(); /* LCD_WR脚时钟使能 */ LCD_RD_GPIO_CLK_ENABLE(); /* LCD_RD脚时钟使能 */ LCD_RS_GPIO_CLK_ENABLE(); /* LCD_RS脚时钟使能 */ LCD_BL_GPIO_CLK_ENABLE(); /* LCD_BL脚时钟使能 */ gpio_init_struct.Pin LCD_CS_GPIO_PIN; gpio_init_struct.Mode GPIO_MODE_AF_PP; /* 推挽复用 */ gpio_init_struct.Pull GPIO_PULLUP; /* 上拉 */ gpio_init_struct.Speed GPIO_SPEED_FREQ_VERY_HIGH; /* 高速 */ gpio_init_struct.Alternate GPIO_AF12_FMC; /* 复用为FMC */ HAL_GPIO_Init(LCD_CS_GPIO_PORT, gpio_init_struct); /* 初始化LCD_CS引脚 */ gpio_init_struct.Pin LCD_WR_GPIO_PIN; HAL_GPIO_Init(LCD_WR_GPIO_PORT, gpio_init_struct); /* 初始化LCD_WR引脚 */ gpio_init_struct.Pin LCD_RD_GPIO_PIN; HAL_GPIO_Init(LCD_RD_GPIO_PORT, gpio_init_struct); /* 初始化LCD_RD引脚 */ gpio_init_struct.Pin LCD_RS_GPIO_PIN; HAL_GPIO_Init(LCD_RS_GPIO_PORT, gpio_init_struct); /* 初始化LCD_RS引脚 */ gpio_init_struct.Pin LCD_BL_GPIO_PIN; gpio_init_struct.Mode GPIO_MODE_OUTPUT_PP; /* 推挽输出 */ HAL_GPIO_Init(LCD_BL_GPIO_PORT, gpio_init_struct); /* LCD_BL引脚模式设置(推挽输出) */ g_sram_handle.Instance FMC_NORSRAM_DEVICE; g_sram_handle.Extended FMC_NORSRAM_EXTENDED_DEVICE; g_sram_handle.Init.NSBank FMC_NORSRAM_BANK1; /* 使用NE1 */ g_sram_handle.Init.DataAddressMux FMC_DATA_ADDRESS_MUX_DISABLE; /* 不复用数据线 */ g_sram_handle.Init.MemoryType FMC_MEMORY_TYPE_SRAM; /* SRAM */ g_sram_handle.Init.MemoryDataWidth FMC_NORSRAM_MEM_BUS_WIDTH_16; /* 16位数据宽度 */ g_sram_handle.Init.BurstAccessMode FMC_BURST_ACCESS_MODE_DISABLE; /* 是否使能突发访问,仅对同步突发存储器有效,此处未用到 */ g_sram_handle.Init.WaitSignalPolarity FMC_WAIT_SIGNAL_POLARITY_LOW; /* 等待信号的极性,仅在突发模式访问下有用 */ g_sram_handle.Init.WaitSignalActive FMC_WAIT_TIMING_BEFORE_WS; /* 存储器是在等待周期之前的一个时钟周期还是等待周期期间使能NWAIT */ g_sram_handle.Init.WriteOperation FMC_WRITE_OPERATION_ENABLE; /* 存储器写使能 */ g_sram_handle.Init.WaitSignal FMC_WAIT_SIGNAL_DISABLE; /* 等待使能位,此处未用到 */ g_sram_handle.Init.ExtendedMode FMC_EXTENDED_MODE_ENABLE; /* 读写使用不同的时序 */ g_sram_handle.Init.AsynchronousWait FMC_ASYNCHRONOUS_WAIT_DISABLE; /* 是否使能同步传输模式下的等待信号,此处未用到 */ g_sram_handle.Init.WriteBurst FMC_WRITE_BURST_DISABLE; /* 禁止突发写 */ g_sram_handle.Init.ContinuousClock FMC_CONTINUOUS_CLOCK_SYNC_ASYNC; /* FMC读时序控制寄存器 */ fmc_read_handle.AddressSetupTime 0x0F; /* 地址建立时间(ADDSET)为15个fmc_ker_ck 1/220M4.5ns*1567.5ns */ fmc_read_handle.AddressHoldTime 0x00; fmc_read_handle.DataSetupTime 0x4E; /* 数据保存时间(DATAST)为78个fmc_ker_ck4.5*78351ns */ /* 因为液晶驱动IC的读数据的时候速度不能太快,尤其是个别奇葩芯片 */ fmc_read_handle.AccessMode FMC_ACCESS_MODE_A; /* 模式A */ /* FMC写时序控制寄存器 */ fmc_write_handle.AddressSetupTime 0x0F; /* 地址建立时间(ADDSET)为15个fmc_ker_ck67.5ns */ fmc_write_handle.AddressHoldTime 0x00; fmc_write_handle.DataSetupTime 0x0F; /* 数据保存时间(DATAST)为15个fmc_ker_ck67.5ns */ /* 15个fmc_ker_ckfmc_ker_ck220Mhz,某些液晶驱动IC的写信号脉宽最少也得50ns。 */ fmc_write_handle.AccessMode FMC_ACCESS_MODE_A; /* 模式A */ HAL_SRAM_Init(g_sram_handle, fmc_read_handle, fmc_write_handle); delay_ms(50); /* 初始化FMC后,必须等待一定时间才能开始初始化 */ /* 尝试9341 ID的读取 */ lcd_wr_regno(0XD3); lcddev.id lcd_rd_data(); /* dummy read */ lcddev.id lcd_rd_data(); /* 读到0X00 */ lcddev.id lcd_rd_data(); /* 读取0X93 */ lcddev.id 8; lcddev.id | lcd_rd_data(); /* 读取0X41 */ if (lcddev.id ! 0X9341) /* 不是 9341 , 尝试看看是不是 ST7789 */ { lcd_wr_regno(0X04); lcddev.id lcd_rd_data(); /* dummy read */ lcddev.id lcd_rd_data(); /* 读到0X85 */ lcddev.id lcd_rd_data(); /* 读取0X85 */ lcddev.id 8; lcddev.id | lcd_rd_data(); /* 读取0X52 */ if (lcddev.id 0X8552) /* 将8552的ID转换成7789 */ { lcddev.id 0x7789; } if (lcddev.id ! 0x7789) /* 也不是ST7789, 尝试是不是 NT35310 */ { lcd_wr_regno(0xD4); lcddev.id lcd_rd_data(); /* dummy read */ lcddev.id lcd_rd_data(); /* 读回0x01 */ lcddev.id lcd_rd_data(); /* 读回0x53 */ lcddev.id 8; lcddev.id | lcd_rd_data(); /* 这里读回0x10 */ if (lcddev.id ! 0x5310) /* 也不是NT35310,尝试看看是不是ST7796 */ { lcd_wr_regno(0XD3); lcddev.id lcd_rd_data(); /* dummy read */ lcddev.id lcd_rd_data(); /* 读到0X00 */ lcddev.id lcd_rd_data(); /* 读取0X77 */ lcddev.id 8; lcddev.id | lcd_rd_data(); /* 读取0X96 */ if (lcddev.id ! 0x7796) /* 也不是ST7796,尝试看看是不是NT35510 */ { /* 发送密钥厂家提供 */ lcd_write_reg(0xF000, 0x0055); lcd_write_reg(0xF001, 0x00AA); lcd_write_reg(0xF002, 0x0052); lcd_write_reg(0xF003, 0x0008); lcd_write_reg(0xF004, 0x0001); lcd_wr_regno(0xC500); /* 读取ID低八位 */ lcddev.id lcd_rd_data(); /* 读回0x55 */ lcddev.id 8; lcd_wr_regno(0xC501); /* 读取ID高八位 */ lcddev.id | lcd_rd_data(); /* 读回0x10 */ delay_ms(5); /* 等待5ms, 因为0XC501指令对1963来说就是软件复位指令, 等待5ms让1963复位完成再操作 */ if (lcddev.id ! 0x5510) /* 也不是NT5510,尝试看看是不是ILI9806 */ { lcd_wr_regno(0XD3); lcddev.id lcd_rd_data(); /* dummy read */ lcddev.id lcd_rd_data(); /* 读回0X00 */ lcddev.id lcd_rd_data(); /* 读回0X98 */ lcddev.id 8; lcddev.id | lcd_rd_data(); /* 读回0X06 */ if (lcddev.id ! 0x9806) /* 也不是ILI9806,尝试看看是不是SSD1963 */ { lcd_wr_regno(0xA1); lcddev.id lcd_rd_data(); lcddev.id lcd_rd_data(); /* 读回0x57 */ lcddev.id 8; lcddev.id | lcd_rd_data(); /* 读回0x61 */ if (lcddev.id 0x5761) lcddev.id 0x1963; /* SSD1963读回的ID是5761H,为方便区分,我们强制设置为1963 */ } } } } } }我们发现在这个版本的驱动当中正点原子已经帮我们将FCM的引脚配置好了但是我们又要在CubeMX开启FCM才能使用这个驱动这就是其抽象的地方。其实解决方法就是将main函数当中的FCM初始化注释掉然后调用lcd_init();这样就即开启了FCM时钟也避免了对其进行两次配置。接下来对mian函数中的SCB_EnableICache();和SCB_EnableDCache();也将其注释掉转而调用正点原子sys.h驱动当中的sys_cache_enable();函数还记得我们并没有对ICache和DCache进行配置嘛正点原子在mpu.h中的mpu_memory_protection();函数中已经进行了配置我们只需要调用它即可。这个函数内部是这样的void mpu_memory_protection(void) { /* 保护整个DTCM,共128K字节,允许指令访问,禁止共用,允许cache,允许缓冲 */ mpu_set_protection(0x20000000, MPU_REGION_SIZE_128KB, MPU_REGION_NUMBER1, MPU_INSTRUCTION_ACCESS_ENABLE, MPU_REGION_FULL_ACCESS, MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_CACHEABLE, MPU_ACCESS_BUFFERABLE); /* 保护整个AXI SRAM,共512K字节,允许指令访问,禁止共用,允许cache,允许缓冲 */ mpu_set_protection(0x24000000, MPU_REGION_SIZE_512KB,MPU_REGION_NUMBER2, MPU_INSTRUCTION_ACCESS_ENABLE, MPU_REGION_FULL_ACCESS, MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_CACHEABLE, MPU_ACCESS_BUFFERABLE); /* 保护整个SRAM1~SRAM3,共288K字节,允许指令访问,禁止共用,允许cache,允许缓冲 */ mpu_set_protection(0x30000000, MPU_REGION_SIZE_512KB,MPU_REGION_NUMBER3, MPU_INSTRUCTION_ACCESS_ENABLE, MPU_REGION_FULL_ACCESS, MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_CACHEABLE, MPU_ACCESS_BUFFERABLE); /* 保护整个SRAM4,共64K字节,允许指令访问,禁止共用,允许cache,允许缓冲 */ mpu_set_protection(0x38000000, MPU_REGION_SIZE_64KB, MPU_REGION_NUMBER4, MPU_INSTRUCTION_ACCESS_ENABLE, MPU_REGION_FULL_ACCESS, MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_CACHEABLE, MPU_ACCESS_BUFFERABLE); /* 保护MCU LCD屏所在的FMC区域,,共64M字节,允许指令访问,禁止共用,禁止cache,禁止缓冲 */ mpu_set_protection(0x60000000, MPU_REGION_SIZE_64MB, MPU_REGION_NUMBER5, MPU_INSTRUCTION_ACCESS_ENABLE, MPU_REGION_FULL_ACCESS, MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_NOT_CACHEABLE, MPU_ACCESS_NOT_BUFFERABLE); /* 保护SDRAM区域,共64M字节,允许指令访问,禁止共用,允许cache,允许缓冲 */ mpu_set_protection(0XC0000000, MPU_REGION_SIZE_64MB, MPU_REGION_NUMBER6, MPU_INSTRUCTION_ACCESS_ENABLE, MPU_REGION_FULL_ACCESS, MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_CACHEABLE, MPU_ACCESS_BUFFERABLE); /* 保护整个NAND FLASH区域,共256M字节,禁止指令访问,禁止共用,禁止cache,禁止缓冲 */ mpu_set_protection(0X80000000, MPU_REGION_SIZE_256MB, MPU_REGION_NUMBER7, MPU_INSTRUCTION_ACCESS_DISABLE, MPU_REGION_FULL_ACCESS, MPU_ACCESS_NOT_SHAREABLE, MPU_ACCESS_NOT_CACHEABLE, MPU_ACCESS_NOT_BUFFERABLE); }其实在CubeMX中也可以对它进行配置但是我没成功过反而是直接调用其函数成功了你们有兴趣可以尝试一下然后我看其他博主的移植教程对其的延时函数也进行了修改我们这里就进行了沿用可以尝试一下不进行修改但我没试过QAQ。在CubeMX中用TIM7对它进行精确延时并在delay.c文件中将void delay_us(uint32_t nus)这个函数修改为void delay_us(uint16_t nus) { uint16_t differ 65535-nus-5; HAL_TIM_Base_Start(htim7); __HAL_TIM_SetCounter(htim7,differ); while(differ0xffff-5) { differ __HAL_TIM_GetCounter(htim7); } HAL_TIM_Base_Stop(htim7); }记得包含定时器头文件以及去修改delay.h好的到这里我们进行编译会发现还会发生报错原因就是在其驱动文件中对CubeMX生成的fmc.c中的void HAL_SRAM_MspInit(SRAM_HandleTypeDef* sramHandle)这个函数进行了再次定义我们只需要将fmc.c中的void HAL_SRAM_MspInit(SRAM_HandleTypeDef* sramHandle)函数注释掉即可到这里我们的LCD屏幕就可以正常工作了下面是我修改好的BSP文件链接: https://pan.baidu.com/s/1uA2C8CdIMlsR7NQwRSqIpg?pwd5q44 提取码: 5q44有问题可以联系我QQ2328932766
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2411536.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!