新手上路
积分 25
金钱 25
注册时间 2020-1-19
在线时间 11 小时
1 金钱
大家好,刚刚在测试7"的MCU TFT屏的时候,发现如下问题,还望各位大佬帮忙看下可能是什么原因(相关代码附在最后了)
STM32F103ZET6 + ALIENTEK 7" TFTLCD MODULE + JLink
问题发生过程描述(下述过程中,硬件未做任何变动):
1、使用FSMC驱动TFT屏幕,已完成。能够正常显示/刷新等。使用的是Bank1,NE1,A16作为RS线。
2、能正常驱动后,想测试一下刷新帧率(后来掐秒表测试实际12.5fps),于是初始化了一个定时器TIM2(先试了TIM2,后测试了TIM3,都不行)用来计时:方法是,使用一个全局变量,定时器每1ms对其+1。(对定时器进行了封装,该代码在之前多次测试中均正常工作。)
3、TIM2初始化放在TFT初始化后面,TFT能正常工作,但是TIM2进不了中断。
4、将TIM2初始化放在TFT初始化前面,TIM2能正常初始化,能正常进中断,GPIO和FSMC的外设能正常初始化,但是卡在了TFT的初始化上(TFT->Register = TFT_SSD1963_PLLMn_Set; TFT->Data = 0x1D;卡在了后面这句上)
5、单步调试卡在TFT->Data = 0x1D;上时,STM32好像直接复位了(硬件故障中断?总线故障中断?) 。然后JLink连接就中断了,所以后续什么情况也不太清楚。而且,下次下载程序/调试前,STM32必须要断开电源,重新上电才可以,否则会报找不到CortexM设备。
相关代码:
GPIO+FSMC外设初始化代码(正常运行):
// 时钟/IO口使能/配置
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE | GPIO2Rcc(GPIO_RST), ENABLE);
// PD 复用推挽输出,50MHz
// D15,D14, , ,D11,D10,D9,D8 | D7, ,D5,D4, , , D1,D0
GPIOD->CRH &= 0x00FF0000;
GPIOD->CRH |= 0xBB00BBBB;
GPIOD->CRL &= 0x0F00FF00;
GPIOD->CRL |= 0xB0BB00BB;
// PE 复用推挽输出,50MHz
// E15,E14,E13,E12,E11,E10,E9,E8 | E7,,,,,,,
GPIOE->CRH &= 0x00000000;
GPIOE->CRH |= 0xBBBBBBBB;
GPIOE->CRL &= 0x0FFFFFFF;
GPIOE->CRL |= 0xB0000000;
// 复位引脚,推挽输出,50MHz
// Pin0 ~ Pin7
if (PinNo_RST < GPIO_Pin_8) {
for (unsigned int i = 0; i < 8; ++i)
{
if (1 << i == PinNo_RST) {
// 0011,推挽输出,50MHz
GPIO_RST->CRL &= ~(0x0F << (i << 2));
GPIO_RST->CRL |= 0x03 << (i << 2);
RST_Pin = i;
break;
}
}
}
// Pin8 ~ Pin15
else {
unsigned short pin = PinNo_RST >> 8;
for (unsigned int i = 0; i < 8; ++i)
{
if (1 << i == pin) {
// 0011,推挽输出,50MHz
GPIO_RST->CRH &= ~(0x0F << (i << 2));
GPIO_RST->CRH |= 0x03 << (i << 2);
RST_Pin = i + 8;
break;
}
}
}
TFT_RSTo = 1;
// FSMC寄存器配置
FSMC_NORSRAMInitTypeDef FSMC_InitStruct;
FSMC_NORSRAMTimingInitTypeDef FSMC_ReadTiming, FSMC_WriteTiming;
FSMC_ReadTiming.FSMC_AddressSetupTime = 1; // 地址建立时间
FSMC_ReadTiming.FSMC_AddressHoldTime = 0; // 地址保持时间
FSMC_ReadTiming.FSMC_DataSetupTime = 15; // 数据建立时间
FSMC_ReadTiming.FSMC_DataLatency = 0; // 数据保持时间
FSMC_ReadTiming.FSMC_BusTurnAroundDuration = 0; // 总线恢复时间
FSMC_ReadTiming.FSMC_CLKDivision = 0; // 时钟分频
FSMC_ReadTiming.FSMC_AccessMode = FSMC_AccessMode_A;
FSMC_WriteTiming.FSMC_AddressSetupTime = 0; // 地址建立时间
FSMC_WriteTiming.FSMC_AddressHoldTime = 0; // 地址保持时间
FSMC_WriteTiming.FSMC_DataSetupTime = 3; // 数据建立时间
FSMC_WriteTiming.FSMC_DataLatency = 0; // 数据保持时间
FSMC_WriteTiming.FSMC_BusTurnAroundDuration = 0; // 总线恢复时间
FSMC_WriteTiming.FSMC_CLKDivision = 0; // 时钟分频
FSMC_WriteTiming.FSMC_AccessMode = FSMC_AccessMode_A;
FSMC_InitStruct.FSMC_Bank = FSMC_Bank1_NORSRAM1;
FSMC_InitStruct.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; // 地址数据总线复用
FSMC_InitStruct.FSMC_MemoryType = FSMC_MemoryType_SRAM;
FSMC_InitStruct.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
FSMC_InitStruct.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
FSMC_InitStruct.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
FSMC_InitStruct.FSMC_WrapMode = FSMC_WrapMode_Disable;
FSMC_InitStruct.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
FSMC_InitStruct.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
FSMC_InitStruct.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
FSMC_InitStruct.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
FSMC_InitStruct.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable;
FSMC_InitStruct.FSMC_ReadWriteTimingStruct = &FSMC_ReadTiming;
FSMC_InitStruct.FSMC_WriteTimingStruct = &FSMC_WriteTiming;
FSMC_NORSRAMInit(&FSMC_InitStruct);
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE);
复制代码
TIM2初始化代码(正常运行)
TFT初始化代码(节选部分):
// TFT配置
//u16 i = 0;
// 复位
TFT_RSTo = 0;
DelayMs(100);
TFT_RSTo = 1;
DelayMs(100);
TFT->Register = TFT_SSD1963_PLLMn_Set;
TFT->Data = 0x1D; // 先初始化定时器,就会卡死在该位置。该位置也是整个程序第一次向TFT写数据的时候(前一句写指令)。
TFT->Data = 0x02;
TFT->Data = 0x04;
DelayUs(100);
TFT->Register = TFT_SSD1963_PLL_Set;
TFT->Data = 0x01;
DelayMs(10);
复制代码
主函数初始化代码(其中使用了一个我自己封装的DebugOutput方法,用来输出调试信息。之前测试过SoftTimer和DebugOutput一起能正常使用):
void SysInit(void)
{
DebugOutput_InitTypeDef DebugOutput_InitStruct;
Sys_ClockInit(9);
//SoftTimer_Init(TIM3,NVIC_PriorityGroup_2);
DebugOutput_InitStruct.USARTx = USART1;
DebugOutput_InitStruct.USART_BaudRate = 38400;
DebugOutput_InitStruct.USART_Parity = USART_Parity_No;
DebugOutput_InitStruct.USART_StopBits = USART_StopBits_1;
DebugOutput_InitStruct.USART_WordLength = USART_WordLength_8b;
DebugOutput_InitStruct.ReceiveHandler = UploadData;
DebugOutput_InitStruct.ReceiveMode = DebugInput_ReceiveMode_EachLine;
DebugOutput_Init(DebugOutput_InitStruct, NVIC_PriorityGroup_2);
DebugOutput_WriteLine("系统时钟初始化完成!");
DebugOutput_WriteLine("调试输出模块初始化完成!");
TFT_SSD1963_Init(GPIOA,GPIO_Pin_2);
DebugOutput_WriteLine("TFT初始化完成!");
TFT_SSD1963_ClearScreen(Color_White_RGB565);
} 复制代码
我来回答