有幸参加了这次APM32E103ZET6 EVAL评估板活动,EVAL开发板与MINI BOARD相比多了很多外设功能,给我们工程师更多的DIY资源,同时也减少了我们扩展连接线时错综复杂的烦恼……
APM32E103ZET6 EVAL评估板是APM32E1系列增强型MCU的完整演示和开发平台,它带有一颗基于ARM Cortex-M3内核的MCU(APM32E103ZET6),其最高工作主频可达到120MHz,带有512KB的FLASH程序空间和128KB的SRAM空间;板载外设资源丰富,带有一个2.4英寸的TFT LCD接口(硬件SPI接口形式,像素为240*320),实现了显示功能、还有一个SPI FLASH(硬件SPI接口)、一个EEPROM(硬件I2C接口)、一个SD Card卡槽(SDIO接口)、一个SDRAM(FMC接口),实现了多元化的存储系统功能;另外还有两路CAN接口、一个USB接口、一个USB转UART TTL接口,构成了多形式的通讯系统功能;此外还有RTC实时时钟模块、ADC模拟外设等等……具备完整的开发资料和SDK软件开发包,能够让开发者快速上手。
- 开发板
- 准备资料硬件
原理图:https://geehy.com/uploads/tool/APM32E103ZE%20EVAL%20V1.0.SchDoc.pdf使用说明书:https://geehy.com/uploads/tool/APM32E103ZE%C2%A0EVAL%C2%A0Board%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E%E4%B9%A6V1.0.pdf软件开发包:https://geehy.com/uploads/tool/APM32E10x_EVAL_SDK_v1.0.zip
- 硬件准备
- APM32E103ZE EVAL评估板
- J-LINK调试仿真下载器MiniUSB线,连接USB转串口,用于程序功能调试监控打印信息
- 2.4英寸TFT LCD(240*320)
- 实现功能
- 基于APM32E103ZE EVAL评估板的板载资源,购置了一个与开发板接口匹配的2.4英寸TFT LCD液晶演示屏,实现功能如下:
- 基于SysTick与MultiTimer实现任务创建、管理、调用的功能
- 实现LED闪烁的基础功能
- 基于KEY和MultiButton实现按键检测、事件处理的功能
- 通过硬件I2C接口实现对EEPROM进行读写操作的功能
- 通过硬件SPI接口结合SFUD实现对SPI FLASH进行读写操作的功能
- 通过RTC及TIME.H库程序实现日历及显示的功能
- 通过ADC来采样旋钮ADC电压的功能,并将结果显示在TFT LCD上
- 通过FMC接口实现对SRAM的读写功能测试
- 通过硬件SPI接口与相应的GPIO端口实现TFT LCD的显示功能
- 功能实现基于SysTick与MultiTimer实现任务创建、管理、调用的功能
volatile uint32_t SysTick_Tick = 0;
/*!
* @brief Get SysTick tick
*
* @param None
*
* @retval SysTick_Tick
*
*/
uint64_t SysTick_GetTick(void)
{
return (SysTick_Tick);
}
/*!
* @brief Main program
*
* @param None
*
* @retval None
*
*/
int main(void)
{
uint32_t PCLK1, PCLK2;
MultiTimerInstall(SysTick_GetTick);
SysTick_Config(SystemCoreClock / 1000);
USART_Init(115200);
RCM_ReadPCLKFreq(&PCLK1, &PCLK2);
printf("\r\nAPM32E103ZE EVAL V1.0 %s %s\r\n", __DATE__, __TIME__);
printf("\r\nSYSCLK : %dHz", RCM_ReadSYSCLKFreq());
printf("\r\nHCLK : %dHz", RCM_ReadHCLKFreq());
printf("\r\nPCLK1 : %dHz", PCLK1);
printf("\r\nPCLK2 : %dHz", PCLK2);
printf("\r\nADCCLK : %dHz", RCM_ReadADCCLKFreq());
printf("\r\n");
ADC_Init();
EEPROM_Init();
KEY_Init();
LED_Init();
RTC_Init();
SDRAM_Init();
SPI_FLASH_Init();
TFT_LCD_Init();
while (1)
{
MultiTimerYield();
}
}
运行结果:
- 实现LED闪烁的基础功能
MultiTimer LED_MultiTimer;
/*!
* @brief LED MultiTimer callback
*
* @param None
*
* @retval None
*
*/
void LED_MultiTimerCallback(MultiTimer *timer, void *userData)
{
GPIO_WriteBitValue(GPIOD, GPIO_PIN_13, (BIT_SET == GPIO_ReadOutputBit(GPIOD, GPIO_PIN_13)) ? BIT_RESET : BIT_SET);
GPIO_WriteBitValue(GPIOD, GPIO_PIN_14, (BIT_SET == GPIO_ReadOutputBit(GPIOD, GPIO_PIN_14)) ? BIT_RESET : BIT_SET);
GPIO_WriteBitValue(GPIOD, GPIO_PIN_15, (BIT_SET == GPIO_ReadOutputBit(GPIOD, GPIO_PIN_15)) ? BIT_RESET : BIT_SET);
MultiTimerStart(&LED_MultiTimer, 250, LED_MultiTimerCallback, "LED");
}
/*!
* @brief LED Init
*
* @param None
*
* @retval None
*
*/
void LED_Init(void)
{
GPIO_Config_T GPIO_ConfigStruct;
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOD);
GPIO_ConfigStructInit(&GPIO_ConfigStruct);
GPIO_ConfigStruct.pin = GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
GPIO_ConfigStruct.speed = GPIO_SPEED_50MHz;
GPIO_ConfigStruct.mode = GPIO_MODE_OUT_PP;
GPIO_Config(GPIOD, &GPIO_ConfigStruct);
MultiTimerStart(&LED_MultiTimer, 250, LED_MultiTimerCallback, "LED");
}
/*!
* @brief LED Control
*
* @param Index & Enable or Disable
*
* @retval None
*
*/
void LED_Enable(uint8_t Index, uint8_t Enable)
{
switch (Index)
{
case 1:
GPIO_WriteBitValue(GPIOD, GPIO_PIN_13, (Enable) ? BIT_RESET : BIT_SET);
break;
case 2:
GPIO_WriteBitValue(GPIOD, GPIO_PIN_14, (Enable) ? BIT_RESET : BIT_SET);
break;
case 3:
GPIO_WriteBitValue(GPIOD, GPIO_PIN_15, (Enable) ? BIT_RESET : BIT_SET);
break;
default:
break;
}
}
- 基于KEY和MultiButton实现按键检测、事件处理的功能
KEY是GPIO作为输入的一个基本功能,通过与MultiButton的结合,能够实现单个按键的多个事件检测和处理操作,比如按键按下、抬起、单击、双击、长按等等,再结合MultiTimer任务实现按键扫描,具体程序如下所示:
MultiTimer KEY_MultiTimer;
struct Button btnKEY1, btnKEY2, btnKEY3;
/*!
* @brief Read key input level
*
* @param btn
*
* @retval level
*
*/
uint8_t read_pin_level(uint8_t pin_id)
{
switch (pin_id)
{
case 0:
return (GPIO_ReadInputBit(GPIOF, GPIO_PIN_9));
case 1:
return (GPIO_ReadInputBit(GPIOC, GPIO_PIN_13));
case 2:
return (GPIO_ReadInputBit(GPIOA, GPIO_PIN_0));
default:
break;
}
return (BIT_SET);
}
/*!
* @brief Key handler
*
* @param btn
*
* @retval None
*
*/
void KEY_Handler(void *btn)
{
Button *key = btn;
uint8_t button_id = key->button_id + 1;
char buffer[50];
memset(buffer, 0, sizeof(buffer));
switch (key->event)
{
case PRESS_DOWN:
sprintf(buffer, "KEY%d : PRESS_DOWN", button_id);
break;
case PRESS_UP:
sprintf(buffer, "KEY%d : PRESS_UP ", button_id);
break;
case SINGLE_CLICK:
sprintf(buffer, "KEY%d : SINGLE_CLICK", button_id);
break;
case DOUBLE_CLICK:
sprintf(buffer, "KEY%d : DOUBLE_CLICK", button_id);
break;
case LONG_PRESS_START:
sprintf(buffer, "KEY%d : LONG_PRESS_START", button_id);
break;
case LONG_PRESS_HOLD:
sprintf(buffer, "KEY%d : LONG_PRESS_HOLD", button_id);
break;
default:
break;
}
LCD_DisplayString(0, 140, buffer, FORECOLOR, BACKCOLOR, 16, 0);
}
/*!
* @brief KEY MultiTimer callback
*
* @param None
*
* @retval None
*
*/
void KEY_MultiTimerCallback(MultiTimer *timer, void *userData)
{
button_ticks();
MultiTimerStart(&KEY_MultiTimer, 5, KEY_MultiTimerCallback, "KEY");
}
/*!
* @brief KEY Init
*
* @param None
*
* @retval None
*
*/
void KEY_Init(void)
{
GPIO_Config_T GPIO_ConfigStruct;
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOF);
GPIO_ConfigStructInit(&GPIO_ConfigStruct);
GPIO_ConfigStruct.pin = GPIO_PIN_9;
GPIO_ConfigStruct.mode = GPIO_MODE_IN_FLOATING;
GPIO_Config(GPIOF, &GPIO_ConfigStruct);
button_init(&btnKEY1, read_pin_level, BIT_RESET, 0);
button_attach(&btnKEY1, PRESS_DOWN, KEY_Handler);
button_attach(&btnKEY1, PRESS_UP, KEY_Handler);
button_start(&btnKEY1);
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOC);
GPIO_ConfigStructInit(&GPIO_ConfigStruct);
GPIO_ConfigStruct.pin = GPIO_PIN_13;
GPIO_ConfigStruct.mode = GPIO_MODE_IN_FLOATING;
GPIO_Config(GPIOC, &GPIO_ConfigStruct);
button_init(&btnKEY2, read_pin_level, BIT_RESET, 1);
button_attach(&btnKEY2, PRESS_DOWN, KEY_Handler);
button_attach(&btnKEY2, PRESS_UP, KEY_Handler);
button_start(&btnKEY2);
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA);
GPIO_ConfigStructInit(&GPIO_ConfigStruct);
GPIO_ConfigStruct.pin = GPIO_PIN_0;
GPIO_ConfigStruct.mode = GPIO_MODE_IN_PD;
GPIO_Config(GPIOA, &GPIO_ConfigStruct);
button_init(&btnKEY3, read_pin_level, BIT_SET, 2);
button_attach(&btnKEY3, PRESS_DOWN, KEY_Handler);
button_attach(&btnKEY3, PRESS_UP, KEY_Handler);
button_start(&btnKEY3);
MultiTimerStart(&KEY_MultiTimer, 5, KEY_MultiTimerCallback, "KEY");
}
- 通过硬件I2C接口实现对EEPROM进行读写操作的功能
通过硬件I2C接口来操作EEPROM进行读写,主要是参考官方提供的SDK软件包中的示例程序完成的,I2C结合DMA的操作,速度更快,CPU的干预时间更少……充分节省了MCU的开销,具体程序如下所示:
/*!
* @brief EEPROM Init
*
* @param None
*
* @retval None
*
*/
void EEPROM_Init(void)
{
I2C_EE_ERROR_T errSta = I2C_EE_OK;
uint16_t i = 0;
APM_I2C_EE_Init();
/* initialization Buffer*/
for (i = 0; i < DATA_BUF_SIZE; i++)
{
txDataBufI2C = i;
rxDataBufI2C = 0;
}
printf("\r\nI2C write Data to EEPROM \r\n");
/* Write data to EEPROM */
errSta = I2C_EE_BufferWrite(txDataBufI2C, EEPROM_WRITE_ADDR, DATA_BUF_SIZE);
if (errSta == I2C_EE_OK)
{
printf("Write data: \r\n");
Buffer_Print(txDataBufI2C, DATA_BUF_SIZE);
/* Set the Number of data to be read */
readDataSize = DATA_BUF_SIZE;
/* Read data from EEPROM */
errSta = I2C_EE_BufferRead(rxDataBufI2C, EEPROM_READ_ADDR, (uint16_t *)(&readDataSize));
/* Wait till DMA transfer is complete */
while (readDataSize > 0)
{
}
if (errSta == I2C_EE_OK)
{
printf("\r\nRead data: \r\n");
Buffer_Print(rxDataBufI2C, DATA_BUF_SIZE);
}
else
{
printf("I2C EE Error Code:%d\r\n", errSta);
}
}
else
{
printf("I2C EE Error Code:%d\r\n", errSta);
}
/* Compare receive Buffer */
if (Buffer_Compare(txDataBufI2C, rxDataBufI2C, DATA_BUF_SIZE) == 1)
{
/* Data is ok then turn on LED2 */
printf("\r\nEEPROM AT24C32 test OK!\r\n\r\n");
}
else
{
printf("\r\nEEPROM AT24C32 test fail!\r\n\r\n");
}
}
运行结果:
- 通过硬件SPI接口结合SFUD实现对SPI FLASH进行读写操作的功能
#define SFUD_DEMO_BUFFER_SIZE (512)
uint8_t sfud_demo_buf[SFUD_DEMO_BUFFER_SIZE];
/*!
* @brief SFUD demo for the first flash device test
*
* @param addr flash start address
*
* @param size test flash size
*
* @param size test flash data buffer
*
* @retval None
*
*/
void sfud_demo(uint32_t addr, size_t size, uint8_t *data)
{
sfud_err result = SFUD_SUCCESS;
const sfud_flash *flash = sfud_get_device_table() + 0;
size_t i;
/* prepare write data */
for (i = 0; i < size; i++)
{
data = i;
}
/* erase test */
result = sfud_erase(flash, addr, size);
if (result == SFUD_SUCCESS)
{
printf("\r\nErase the %s flash data finish. Start from 0x%08X, size is %d.\r\n", flash->name, addr, size);
}
else
{
printf("\r\nErase the %s flash data failed.\r\n", flash->name);
return;
}
/* write test */
result = sfud_write(flash, addr, size, data);
if (result == SFUD_SUCCESS)
{
printf("\r\nWrite the %s flash data finish. Start from 0x%08X, size is %d.\r\n", flash->name, addr, size);
}
else
{
printf("\r\nWrite the %s flash data failed.\r\n", flash->name);
return;
}
/* read test */
result = sfud_read(flash, addr, size, data);
if (result == SFUD_SUCCESS)
{
printf("\r\nRead the %s flash data success. Start from 0x%08X, size is %d. The data is:\r\n", flash->name, addr, size);
printf("Offset (h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\r\n");
for (i = 0; i < size; i++)
{
if ((i % 16) == 0)
{
printf("[%08X] ", addr + i);
}
printf("%02X ", data);
if (((i + 1) % 16 == 0) || (i == size - 1))
{
printf("\r\n");
}
}
printf("\r\n");
}
else
{
printf("\r\nRead the %s flash data failed.\r\n", flash->name);
}
/* data check */
for (i = 0; i < size; i++)
{
if (data != i % 256)
{
printf("\r\nRead and check write data has an error. Write the %s flash data failed.\r\n", flash->name);
break;
}
}
if (i == size)
{
printf("\r\nThe %s flash test is success.\r\n", flash->name);
}
}
/*!
* @brief SPI_FLASH Init
*
* @param None
*
* @retval None
*
*/
void SPI_FLASH_Init(void)
{
printf("\r\n");
if (sfud_init() == SFUD_SUCCESS)
{
sfud_demo(0, sizeof(sfud_demo_buf), sfud_demo_buf);
}
}
运行结果:
- 通过RTC及TIME.H库程序实现日历及显示的功能
MultiTimer RTC_MultiTimer;volatile uint32_t RTC_InterruptFlag = 0; /*! * @brief LED MultiTimer callback * * @param None * * @retval None * */ void RTC_MultiTimerCallback(MultiTimer *timer, void *userData) { if (1 == RTC_InterruptFlag) { RTC_InterruptFlag = 0; time_t t = RTC_ReadCounter(); struct tm *lt = localtime(&t); char buffer[50]; memset(buffer, 0, sizeof(buffer)); strftime(buffer, sizeof(buffer), "%b-%d-%Y %a %H:%M:%S", lt); LCD_DisplayString(0, 80, buffer, FORECOLOR, BACKCOLOR, 16, 0); } MultiTimerStart(&RTC_MultiTimer, 100, RTC_MultiTimerCallback, "RTC"); } /*! * @brief RTC_LoadDefault * * @param None * * @retval None * */ struct tm RTC_LoadDefault(void) { char date[20], time[20]; char text[6][5]; uint8_t index = 0, month = 0; struct tm load; memset(date, 0, sizeof(date)); memset(time, 0, sizeof(time)); memset(text, 0, sizeof(text)); memcpy(date, __DATE__, sizeof(__DATE__)); memcpy(time, __TIME__, sizeof(__TIME__)); char *str; str = strtok(date, " "); while (str != NULL) { memcpy(text[index], str, strlen(str)); index++; str = strtok(NULL, " "); } str = strtok(time, ":"); while (str != NULL) { memcpy(text[index], str, strlen(str)); index++; str = strtok(NULL, ":"); } char *strMonth[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", }; for (uint8_t i = 0; i < 12; i++) { if (strcmp(text[0], strMonth[i]) == 0) { month = i; break; } } load.tm_mday = atoi(text[1]); load.tm_mon = month; load.tm_year = atoi(text[2]) - 1900; load.tm_hour = atoi(text[3]); load.tm_min = atoi(text[4]); load.tm_sec = atoi(text[5]); return (load); } /*! * @brief RTC Init * * @param None * * @retval None * */ void RTC_Init(void) { struct tm load; RCM_EnableAPB1PeriphClock((RCM_APB1_PERIPH_T)RCM_APB1_PERIPH_PMU); PMU_EnableBackupAccess(); RCM_EnableLSI(); while (RCM_ReadStatusFlag(RCM_FLAG_LSIRDY) == RESET) { } RCM_ConfigRTCCLK(RCM_RTCCLK_LSI); RCM_EnableRTCCLK(); RTC_WaitForSynchro(); RTC_WaitForLastTask(); RTC_EnableInterrupt(RTC_INT_SEC); RTC_WaitForLastTask(); RTC_ConfigPrescaler(32767); RTC_WaitForLastTask(); load = RTC_LoadDefault(); time_t t = mktime(&load); RTC_ConfigCounter(t); RTC_WaitForLastTask(); NVIC_EnableIRQRequest(RTC_IRQn, 0, 0); MultiTimerStart(&RTC_MultiTimer, 100, RTC_MultiTimerCallback, "RTC"); }
复制代码- 通过ADC来采样旋钮ADC电压的功能,并将结果显示在TFT LCD上,具体代码如下所示:
MultiTimer ADC_MultiTimer;
/*!
* @brief ADC_MultiTimerCallback
*
* @param None
*
* @retval None
*
*/
void ADC_MultiTimerCallback(MultiTimer *timer, void *userData)
{
char buffer[50];
memset(buffer, 0, sizeof(buffer));
ADC_EnableSoftwareStartConv(ADC1);
while (ADC_ReadSoftwareStartConvStatus(ADC1) != BIT_RESET)
{
}
ADC_ClearStatusFlag(ADC1, ADC_FLAG_EOC);
uint32_t Value = ADC_ReadConversionValue(ADC1);
sprintf(buffer, "ADC Voltage : %0.1fv", (float)Value / 4096.0 * 3.3);
LCD_DisplayString(0, 110, buffer, FORECOLOR, BACKCOLOR, 16, 0);
MultiTimerStart(&ADC_MultiTimer, 100, ADC_MultiTimerCallback, "ADC");
}
/*!
* @brief ADC Init
*
* @param None
*
* @retval None
*
*/
void ADC_Init(void)
{
ADC_Config_T ADC_ConfigStruct;
GPIO_Config_T GPIO_ConfigStruct;
RCM_ConfigADCCLK(RCM_PCLK2_DIV_4); /* ADCCLK = PCLK2/4 */
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOC);
GPIO_ConfigStructInit(&GPIO_ConfigStruct);
GPIO_ConfigStruct.pin = GPIO_PIN_0;
GPIO_ConfigStruct.mode = GPIO_MODE_ANALOG;
GPIO_Config(GPIOC, &GPIO_ConfigStruct);
ADC_ConfigStructInit(&ADC_ConfigStruct);
ADC_ConfigStruct.mode = ADC_MODE_INDEPENDENT;
ADC_ConfigStruct.scanConvMode = DISABLE;
ADC_ConfigStruct.continuosConvMode = ENABLE;
ADC_ConfigStruct.externalTrigConv = ADC_EXT_TRIG_CONV_None;
ADC_ConfigStruct.dataAlign = ADC_DATA_ALIGN_RIGHT;
ADC_ConfigStruct.nbrOfChannel = 1;
ADC_Config(ADC1, &ADC_ConfigStruct);
ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_10, 1, ADC_SAMPLETIME_239CYCLES5);
ADC_Enable(ADC1);
ADC_ResetCalibration(ADC1);
while (ADC_ReadResetCalibrationStatus(ADC1))
{
}
ADC_StartCalibration(ADC1);
while (ADC_ReadCalibrationStartFlag(ADC1))
{
}
MultiTimerStart(&ADC_MultiTimer, 100, ADC_MultiTimerCallback, "ADC");
}
- 通过FMC接口实现对SRAM的读写功能测试
通过FMC接口扩展的SRAM存储,可以让我们在应对需要大容量RAM时,给以应对的最好方案……通过对SRAM的基础读写操作,来熟悉SRAM的操作方法;后面有机会可以尝试一下在系统启动的时候直接映射成系统内存,直接使用;具体代码如下所示:
/**
* @brief W/R Err Count structure definition
*/
typedef struct
{
uint32_t ByteCount;
uint32_t HalfWordCount;
uint32_t WordCount;
} Err_Count_T;
Err_Count_T Err;
/* printf message */
#define MESSAGE0 "*******************************"
#define MESSAGE1 "* APM32E103xE DMC SDRAM Demo "
#define MESSAGE2 "* SystemCoreClock :"
#define MESSAGE3 "* SDRAMClock :"
#define MESSAGE4 "* 8 bit W/R Err Count :"
#define MESSAGE5 "* 16 bit W/R Err Count :"
#define MESSAGE6 "* 32 bit W/R Err Count :"
#define RCM_SDRAM_GPIO_PERIPH \
(RCM_APB2_PERIPH_AFIO | \
RCM_APB2_PERIPH_GPIOB | \
RCM_APB2_PERIPH_GPIOC | \
RCM_APB2_PERIPH_GPIOD | \
RCM_APB2_PERIPH_GPIOE | \
RCM_APB2_PERIPH_GPIOF | \
RCM_APB2_PERIPH_GPIOG)
#define RCM_SDRAM_PERIPH (RCM_AHB_PERIPH_SMC)
#define SDRAM_START_ADDR ((uint32_t)0x60000000)
#define SDRAM_END_ADDR ((uint32_t)0x60200000)
/*!
* @brief SDRAM GPIO Config
*
* @param None
*
* @retval None
*
*/
static void SDRAM_GPIO_ConfigStruct(void)
{
GPIO_Config_T GPIO_ConfigStruct;
RCM_EnableAPB2PeriphClock(RCM_SDRAM_GPIO_PERIPH);
/** SDRAM pins assignment */
/**
+-------------------------+--------------------------+--------------------------+
| PB10 <-> MMC_SDRAM_UNQM | PC10 <-> MMC_SDRAM_D8 | PD2 <-> MMC_SDRAM_D10 |
| PB11 <-> MMC_SDRAM_CKE | PC11 <-> MMC_SDRAM_D9 | PD3 <-> MMC_SDRAM_D11 |
| | | PD4 <-> MMC_SDRAM_D12 |
| | | PD5 <-> MMC_SDRAM_D13 |
| | | PD6 <-> MMC_SDRAM_D14 |
+-------------------------+--------------------------+--------------------------+
| PE3 <-> MMC_SDRAM_D4 | PF0 <-> MMC_SDRAM_D7 | PG0 <-> MMC_SDRAM_D15 |
| PE5 <-> MMC_SDRAM_D5 | PF2 <-> MMC_SDRAM_NCS | PG9 <-> MMC_SDRAM_D9 |
| PE6 <-> MMC_SDRAM_D6 | PF4 <-> MMC_SDRAM_NRAS | PG12 <-> MMC_SDRAM_D0 |
| PE8 <-> MMC_SDRAM_A4 | PF5 <-> MMC_SDRAM_NCAS | PG13 <-> MMC_SDRAM_D1 |
| PE9 <-> MMC_SDRAM_A5 | PF6 <-> MMC_SDRAM_NWE | PG14 <-> MMC_SDRAM_D2 |
| PE10 <-> MMC_SDRAM_A6 | PF10 <-> MMC_SDRAM_LDQM | PG15 <-> MMC_SDRAM_D3 |
| PE11 <-> MMC_SDRAM_A7 | PF11 <-> MMC_SDRAM_Bank | |
| PE12 <-> MMC_SDRAM_A8 | PF12 <-> MMC_SDRAM_A10 | |
| PE13 <-> MMC_SDRAM_A9 | PF13 <-> MMC_SDRAM_A0 | |
| PE14 <-> MMC_SDRAM_A5 | PF14 <-> MMC_SDRAM_A1 | |
| PE15 <-> MMC_SDRAM_CLK | PF15 <-> MMC_SDRAM_A2 | |
+-------------------------+--------------------------+--------------------------+
*/
GPIO_ConfigStruct.speed = GPIO_SPEED_50MHz;
GPIO_ConfigStruct.mode = GPIO_MODE_AF_PP;
GPIO_ConfigStruct.pin = GPIO_PIN_10 | GPIO_PIN_11;
GPIO_Config(GPIOB, &GPIO_ConfigStruct);
GPIO_ConfigStruct.pin = GPIO_PIN_10 | GPIO_PIN_11;
GPIO_Config(GPIOC, &GPIO_ConfigStruct);
GPIO_ConfigStruct.pin = GPIO_PIN_2 | GPIO_PIN_3 |
GPIO_PIN_4 | GPIO_PIN_5 |
GPIO_PIN_6;
GPIO_Config(GPIOD, &GPIO_ConfigStruct);
GPIO_ConfigStruct.pin = GPIO_PIN_3 | GPIO_PIN_5 |
GPIO_PIN_6 | GPIO_PIN_8 |
GPIO_PIN_9 | GPIO_PIN_10 |
GPIO_PIN_11 | GPIO_PIN_12 |
GPIO_PIN_13 | GPIO_PIN_15;
GPIO_Config(GPIOE, &GPIO_ConfigStruct);
GPIO_ConfigStruct.pin = GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_4 |
GPIO_PIN_5 | GPIO_PIN_6 |
GPIO_PIN_10 | GPIO_PIN_11 |
GPIO_PIN_12 | GPIO_PIN_13 |
GPIO_PIN_14 | GPIO_PIN_15;
GPIO_Config(GPIOF, &GPIO_ConfigStruct);
GPIO_ConfigStruct.pin = GPIO_PIN_0 | GPIO_PIN_9 |
GPIO_PIN_12 | GPIO_PIN_13 |
GPIO_PIN_14 | GPIO_PIN_15;
GPIO_Config(GPIOG, &GPIO_ConfigStruct);
}
/*!
* @brief SDRAM DMC Config
*
* @param None
*
* @retval None
*
*/
static void SDRAM_DMC_ConfigStruct(void)
{
uint32_t SDRAM_Capacity;
DMC_Config_T DMC_ConfigStruct;
DMC_TimingConfig_T DMC_TimingConfigStruct;
RCM_EnableAHBPeriphClock(RCM_SDRAM_PERIPH);
DMC_TimingConfigStruct.latencyCAS = DMC_CAS_LATENCY_3; //!< Configure CAS latency period
DMC_TimingConfigStruct.tARP = DMC_AUTO_REFRESH_10; //!< Configure auto refresh period
DMC_TimingConfigStruct.tRAS = DMC_RAS_MINIMUM_5; //!< Configure line activation and precharging minimum time
DMC_TimingConfigStruct.tCMD = DMC_ATA_CMD_7; //!< Configure active to active period
DMC_TimingConfigStruct.tRCD = DMC_DELAY_TIME_2; //!< Configure RAS To CAS delay Time
DMC_TimingConfigStruct.tRP = DMC_PRECHARGE_2; //!< Configure precharge period
DMC_TimingConfigStruct.tWR = DMC_NEXT_PRECHARGE_2; //!< Configure time between the Last Data and The Next Precharge for write
DMC_TimingConfigStruct.tXSR = 6; //!< Configure XSR0
DMC_TimingConfigStruct.tRFP = 0xC3; //!< Configure refresh Cycle
DMC_ConfigStruct.bankWidth = DMC_BANK_WIDTH_1; //!< Configure bank address width
DMC_ConfigStruct.clkPhase = DMC_CLK_PHASE_REVERSE; //!< Configure clock phase
DMC_ConfigStruct.rowWidth = DMC_ROW_WIDTH_11; //!< Configure row address width
DMC_ConfigStruct.colWidth = DMC_COL_WIDTH_8; //!< Configure column address width
DMC_ConfigStruct.memorySize = DMC_MEMORY_SIZE_2MB;
DMC_ConfigStruct.timing = DMC_TimingConfigStruct;
DMC_Config(&DMC_ConfigStruct);
DMC_ConfigOpenBank(DMC_BANK_NUMBER_2);
DMC_EnableAccelerateModule();
DMC_Enable();
/* SDRAM_Capacity = row * col * 16bit * bank (16bit == 2Bytes) */
SDRAM_Capacity = (1 << (DMC_ConfigStruct.rowWidth + 1)) * (1 << (DMC_ConfigStruct.colWidth + 1)) * 2 * (1 << (DMC_ConfigStruct.bankWidth + 1));
printf("This is an example of DMC SDRAM \r\n");
printf("> Row Address Width :%d bit\r\n", DMC_ConfigStruct.rowWidth + 1);
printf("> Column Address Width :%d bit\r\n", DMC_ConfigStruct.colWidth + 1);
printf("> Bank Address Width :%d bit band addr\r\n", DMC_ConfigStruct.bankWidth + 1);
printf("> capacity :%d MByte\r\n\r\n", SDRAM_Capacity / 1024 / 1024);
}
/*!
* @brief SDRAM Write Word
*
* @param address:the address to be programmed.
*
* @param data: the data to be programmed.
*
* @retval None
*
*/
void SDRAM_WriteWord(uint32_t address, uint32_t data)
{
*(__IOM uint32_t *)address = data;
}
/*!
* @brief SDRAM Write Half Word
*
* @param address:the address to be programmed.
*
* @param data: the data to be programmed.
*
* @retval None
*
*/
void SDRAM_WriteHalfWord(uint32_t address, uint16_t data)
{
*(uint16_t *)address = (uint16_t)data;
}
/*!
* @brief SDRAM Write Byte
*
* @param address:the address to be programmed.
*
* @param data: the data to be programmed.
*
* @retval None
*
*/
void SDRAM_WriteByte(uint32_t address, uint8_t data)
{
*(uint8_t *)address = data;
}
/*!
* @brief SDRAM Word Test
*
* @param None
*
* @retval i : W/R Err Count
*
*/
uint32_t SDRAM_Word_Test(void)
{
uint32_t Addr = 0;
uint32_t i = 0;
for (Addr = SDRAM_START_ADDR; Addr < SDRAM_END_ADDR; Addr += 0x4)
{
SDRAM_WriteWord(Addr, (uint32_t)Addr);
}
for (Addr = SDRAM_START_ADDR; Addr < SDRAM_END_ADDR; Addr += 0x4)
{
if (*(__IO uint32_t *)(Addr) != (uint32_t)Addr)
{
i++;
}
}
return (i);
}
/*!
* @brief SDRAM HalfWord Test
*
* @param None
*
* @retval i : W/R Err Count
*
*/
uint32_t SDRAM_HalfWord_Test(void)
{
uint32_t Addr = 0;
uint32_t i = 0;
for (Addr = SDRAM_START_ADDR; Addr < SDRAM_END_ADDR; Addr += 0x2)
{
SDRAM_WriteHalfWord(Addr, (uint16_t)Addr);
}
for (Addr = SDRAM_START_ADDR; Addr < SDRAM_END_ADDR; Addr += 0x2)
{
if (*(__IO uint16_t *)(Addr) != (uint16_t)Addr)
{
i++;
}
}
return (i);
}
/*!
* @brief SDRAM Byte Test
*
* @param None
*
* @retval i : W/R Err Count
*
*/
uint32_t SDRAM_Byte_Test(void)
{
uint32_t Addr = 0;
uint32_t i = 0;
for (Addr = SDRAM_START_ADDR; Addr < SDRAM_END_ADDR; Addr += 0x1)
{
SDRAM_WriteByte(Addr, (uint8_t)Addr);
}
for (Addr = SDRAM_START_ADDR; Addr < SDRAM_END_ADDR; Addr += 0x1)
{
if (*(__IO uint8_t *)(Addr) != (uint8_t)Addr)
{
i++;
}
}
return (i);
}
/*!
* @brief SDRAM Init
*
* @param None
*
* @retval None
*
*/
void SDRAM_Init(void)
{
SDRAM_GPIO_ConfigStruct();
SDRAM_DMC_ConfigStruct();
printf("\r\n");
printf("%s \r\n", MESSAGE0);
printf("%s \r\n", MESSAGE1);
printf("%s %d MHz\r\n", MESSAGE2, RCM_ReadSYSCLKFreq() / 1000000);
printf("%s %d MHz\r\n", MESSAGE3, RCM_ReadSYSCLKFreq() / 1000000 / (RCM->CFG_B.SDRAMPSC + 1));
/* SDRAM byte write/read test */
Err.ByteCount = SDRAM_Byte_Test();
printf("%s %d\r\n", MESSAGE4, Err.ByteCount);
/* SDRAM halfword write/read test */
Err.HalfWordCount = SDRAM_HalfWord_Test();
printf("%s %d\r\n", MESSAGE5, Err.HalfWordCount);
/* SDRAM word write/read test */
Err.WordCount = SDRAM_Word_Test();
printf("%s %d\r\n", MESSAGE6, Err.WordCount);
printf("%s \r\n", MESSAGE0);
/* The SDRAM test failed */
if ((Err.ByteCount != 0) || (Err.HalfWordCount != 0) || ((Err.WordCount != 0)))
{
printf("The SDRAM test failed\r\n");
}
else
{
printf("The SDRAM test success\r\n");
}
}
运行结果:
- 通过硬件SPI接口与相应的GPIO端口实现TFT LCD的显示功能
#define TFT_LCD_CS_H() GPIO_WriteBitValue(GPIOA, GPIO_PIN_4, BIT_SET)
#define TFT_LCD_CS_L() GPIO_WriteBitValue(GPIOA, GPIO_PIN_4, BIT_RESET)
#define TFT_LCD_DC_H() GPIO_WriteBitValue(GPIOA, GPIO_PIN_6, BIT_SET)
#define TFT_LCD_DC_L() GPIO_WriteBitValue(GPIOA, GPIO_PIN_6, BIT_RESET)
#define TFT_LCD_RES_H() GPIO_WriteBitValue(GPIOA, GPIO_PIN_1, BIT_SET)
#define TFT_LCD_RES_L() GPIO_WriteBitValue(GPIOA, GPIO_PIN_1, BIT_RESET)
#define TFT_LCD_BLK_H() GPIO_WriteBitValue(GPIOA, GPIO_PIN_8, BIT_SET)
#define TFT_LCD_BLK_L() GPIO_WriteBitValue(GPIOA, GPIO_PIN_8, BIT_RESET)
/*!
* @brief TFT LCD Init SPI1
*
* @param None
*
* @retval None
*
*/
void TFT_LCD_InitSPI1(void)
{
GPIO_Config_T GPIO_ConfigStruct;
SPI_Config_T SPI_ConfigStruct;
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA);
GPIO_ConfigStructInit(&GPIO_ConfigStruct);
GPIO_ConfigStruct.pin = GPIO_PIN_7 | GPIO_PIN_5;
GPIO_ConfigStruct.speed = GPIO_SPEED_50MHz;
GPIO_ConfigStruct.mode = GPIO_MODE_AF_PP;
GPIO_Config(GPIOA, &GPIO_ConfigStruct);
GPIO_ConfigStructInit(&GPIO_ConfigStruct);
GPIO_ConfigStruct.pin = GPIO_PIN_4;
GPIO_ConfigStruct.speed = GPIO_SPEED_50MHz;
GPIO_ConfigStruct.mode = GPIO_MODE_OUT_PP;
GPIO_Config(GPIOA, &GPIO_ConfigStruct);
TFT_LCD_CS_H();
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SPI1);
SPI_ConfigStructInit(&SPI_ConfigStruct);
SPI_ConfigStruct.mode = SPI_MODE_MASTER;
SPI_ConfigStruct.length = SPI_DATA_LENGTH_8B;
SPI_ConfigStruct.phase = SPI_CLKPHA_2EDGE;
SPI_ConfigStruct.polarity = SPI_CLKPOL_HIGH;
SPI_ConfigStruct.nss = SPI_NSS_SOFT;
SPI_ConfigStruct.firstBit = SPI_FIRSTBIT_MSB;
SPI_ConfigStruct.direction = SPI_DIRECTION_2LINES_FULLDUPLEX;
SPI_ConfigStruct.baudrateDiv = SPI_BAUDRATE_DIV_2;
SPI_ConfigStruct.crcPolynomial = 7;
SPI_Config(SPI1, &SPI_ConfigStruct);
SPI_Enable(SPI1);
}
/*!
* @brief LCD SPI sends a byte through the SPI
*
* @param data: byte send
*
* @retval The error code
*
*/
void TFT_LCD_SPI_ReadWriteByte(uint8_t Data)
{
while (RESET == SPI_I2S_ReadStatusFlag(SPI1, SPI_FLAG_TXBE))
{
}
SPI_I2S_TxData(SPI1, Data);
while (RESET != SPI_I2S_ReadStatusFlag(SPI1, SPI_FLAG_BSY))
{
}
}
/*!
* @brief TFT LCD Init GPIO
*
* @param None
*
* @retval None
*
*/
void TFT_LCD_InitGPIO(void)
{
GPIO_Config_T GPIO_ConfigStruct;
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA);
GPIO_ConfigStructInit(&GPIO_ConfigStruct);
GPIO_ConfigStruct.pin = GPIO_PIN_1 | GPIO_PIN_6 | GPIO_PIN_8;
GPIO_ConfigStruct.speed = GPIO_SPEED_50MHz;
GPIO_ConfigStruct.mode = GPIO_MODE_OUT_PP;
GPIO_Config(GPIOA, &GPIO_ConfigStruct);
TFT_LCD_DC_H();
TFT_LCD_RES_H();
TFT_LCD_BLK_H();
}
/*!
* @brief TFT LCD Write Byte
*
* @param Data
*
* @retval None
*
*/
void TFT_LCD_WriteByte(uint8_t Data)
{
TFT_LCD_DC_H();
TFT_LCD_CS_L();
TFT_LCD_SPI_ReadWriteByte(Data);
TFT_LCD_CS_H();
}
/*!
* @brief TFT LCD Write Half-word
*
* @param Data
*
* @retval None
*
*/
void TFT_LCD_WriteHalfword(uint16_t Data)
{
TFT_LCD_DC_H();
TFT_LCD_CS_L();
TFT_LCD_SPI_ReadWriteByte(Data >> 8);
TFT_LCD_SPI_ReadWriteByte(Data >> 0);
TFT_LCD_CS_H();
}
/*!
* @brief TFT LCD Write Command
*
* @param Data
*
* @retval None
*
*/
void TFT_LCD_WriteCommand(uint8_t Data)
{
TFT_LCD_DC_L();
TFT_LCD_CS_L();
TFT_LCD_SPI_ReadWriteByte(Data);
TFT_LCD_CS_H();
}
/*!
* @brief TFT LCD Set Cursor Address
*
* @param StartX
*
* @param StartY
*
* @param EndX
*
* @param EndY
*
* @retval None
*
*/
void TFT_LCD_SetCursorAddress(uint16_t StartX, uint16_t StartY, uint16_t EndX, uint16_t EndY)
{
TFT_LCD_WriteCommand(0x2A);
TFT_LCD_WriteHalfword(StartX);
TFT_LCD_WriteHalfword(EndX);
TFT_LCD_WriteCommand(0x2B);
TFT_LCD_WriteHalfword(StartY);
TFT_LCD_WriteHalfword(EndY);
TFT_LCD_WriteCommand(0x2C);
}
/*!
* @brief TFT LCD Draw Point
*
* @param x: Row Lable
*
* @param y: Column Lable
*
* @param Color: Color To Be Filled
*
* @retval None
*
*/
void TFT_LCD_DrawPoint(uint16_t x, uint16_t y, uint16_t Color)
{
TFT_LCD_SetCursorAddress(x, y, x, y);
TFT_LCD_WriteHalfword(Color);
}
/*!
* @brief LCD clear content
*
* @param StartX
*
* @param StartY
*
* @param EndY
*
* @param EndY
*
* @param Color
*
* @retval None
*
*/
void TFT_LCD_Clear(uint16_t StartX, uint16_t StartY, uint16_t EndX, uint16_t EndY, uint16_t Color)
{
TFT_LCD_SetCursorAddress(StartX, StartY, EndX - 1, EndY - 1);
for (uint16_t y = StartY; y < EndY; y++)
{
for (uint16_t x = StartX; x < EndX; x++)
{
TFT_LCD_WriteHalfword(Color);
}
}
}
/*!
* @brief TFT LCD Display Character
*
* @param x: Row Lable
*
* @param y: Column Lable
*
* @param ForeColor: Foreground Color
*
* @param BackColor: Background Color
*
* @param FontSize: Font Size
*
* @param Mode: Superposition Mode
*
* @retval None
*
*/
void LCD_DisplayChar(uint16_t x, uint16_t y, char ch, uint16_t ForeColor, uint16_t BackColor, uint8_t FontSize, uint8_t Mode)
{
const uint8_t *FontTable;
uint8_t TableSize = 0;
uint8_t FontHeight = FontSize;
uint8_t FontWidth = FontSize / 2;
uint16_t StartX = x;
switch (FontSize)
{
case 12:
FontTable = &ASCII_FONT_1206[ch - 0x20][0];
TableSize = 12;
break;
case 16:
FontTable = &ASCII_FONT_1608[ch - 0x20][0];
TableSize = 16;
break;
case 24:
FontTable = &ASCII_FONT_2412[ch - 0x20][0];
TableSize = 48;
break;
case 32:
FontTable = &ASCII_FONT_3216[ch - 0x20][0];
TableSize = 64;
break;
default:
break;
}
if (0 == Mode)
{
TFT_LCD_SetCursorAddress(x, y, x + FontWidth - 1, y + FontHeight - 1);
for (uint8_t i = 0; i < TableSize; i++)
{
for (uint8_t j = 0; j < 8; j++)
{
if (FontTable & (0x01 << j))
{
TFT_LCD_WriteHalfword(ForeColor);
}
else
{
TFT_LCD_WriteHalfword(BackColor);
}
x++;
if (x % FontWidth == 0)
{
x = 0;
break;
}
}
}
}
else
{
for (uint8_t i = 0; i < TableSize; i++)
{
for (uint8_t j = 0; j < 8; j++)
{
if (FontTable & (0x01 << j))
{
TFT_LCD_DrawPoint(x, y, ForeColor);
}
x++;
if ((x - StartX) == FontWidth)
{
x = StartX;
y = y + 01;
break;
}
}
}
}
}
/*!
* @brief TFT LCD Display String
*
* @param x: Row Lable
*
* @param y: Column Lable
*
* @param ForeColor: Foreground Color
*
* @param BackColor: Background Color
*
* @param str: Point To String Buffer
*
* @param FontSize: Font Size
*
* @param Mode: Superposition Mode
*
* @retval None
*
*/
void LCD_DisplayString(uint16_t x, uint16_t y, const char *str, uint16_t ForeColor, uint16_t BackColor, uint8_t FontSize, uint8_t Mode)
{
while (*str != '\0')
{
LCD_DisplayChar(x, y, *str, ForeColor, BackColor, FontSize, Mode);
switch (FontSize)
{
case 12:
x += 6;
break;
case 16:
x += 8;
break;
case 24:
x += 12;
break;
case 32:
x += 16;
break;
default:
break;
}
if(x >= 240)
{
x = 0;
y += FontSize;
}
str++;
}
}
/*!
* @brief TFT LCD DelayMS
*
* @param Tick
*
* @retval None
*
*/
void TFT_LCD_DelayMS(uint32_t Tick)
{
extern volatile uint32_t SysTick_Tick;
uint32_t Start = SysTick_Tick;
if ((UINT32_MAX - Start) >= Tick)
{
while ((SysTick_Tick - Start) != Tick)
{
}
}
else
{
while ((SysTick_Tick + (UINT32_MAX - Start)) != Tick)
{
}
}
}
/*!
* @brief TFT LCD Configure
*
* @param None
*
* @retval None
*
*/
void TFT_LCD_Configure(void)
{
TFT_LCD_WriteCommand(0x11);
TFT_LCD_DelayMS(120);
TFT_LCD_WriteCommand(0xCF);
TFT_LCD_WriteByte(0x00);
TFT_LCD_WriteByte(0xD9);
TFT_LCD_WriteByte(0X30);
TFT_LCD_WriteCommand(0xED);
TFT_LCD_WriteByte(0x64);
TFT_LCD_WriteByte(0x03);
TFT_LCD_WriteByte(0X12);
TFT_LCD_WriteByte(0X81);
TFT_LCD_WriteCommand(0xE8);
TFT_LCD_WriteByte(0x85);
TFT_LCD_WriteByte(0x10);
TFT_LCD_WriteByte(0x78);
TFT_LCD_WriteCommand(0xCB);
TFT_LCD_WriteByte(0x39);
TFT_LCD_WriteByte(0x2C);
TFT_LCD_WriteByte(0x00);
TFT_LCD_WriteByte(0x34);
TFT_LCD_WriteByte(0x02);
TFT_LCD_WriteCommand(0xF7);
TFT_LCD_WriteByte(0x20);
TFT_LCD_WriteCommand(0xEA);
TFT_LCD_WriteByte(0x00);
TFT_LCD_WriteByte(0x00);
TFT_LCD_WriteCommand(0xC0);
TFT_LCD_WriteByte(0x21);
TFT_LCD_WriteCommand(0xC1);
TFT_LCD_WriteByte(0x12);
TFT_LCD_WriteCommand(0xC5);
TFT_LCD_WriteByte(0x32);
TFT_LCD_WriteByte(0x3C);
TFT_LCD_WriteCommand(0xC7);
TFT_LCD_WriteByte(0XC1);
TFT_LCD_WriteCommand(0x36);
TFT_LCD_WriteByte(0xC8);
TFT_LCD_WriteCommand(0x3A);
TFT_LCD_WriteByte(0x55);
TFT_LCD_WriteCommand(0xB1);
TFT_LCD_WriteByte(0x00);
TFT_LCD_WriteByte(0x18);
TFT_LCD_WriteCommand(0xB6);
TFT_LCD_WriteByte(0x0A);
TFT_LCD_WriteByte(0xA2);
TFT_LCD_WriteCommand(0xF2);
TFT_LCD_WriteByte(0x00);
TFT_LCD_WriteCommand(0x26);
TFT_LCD_WriteByte(0x01);
TFT_LCD_WriteCommand(0xE0);
TFT_LCD_WriteByte(0x0F);
TFT_LCD_WriteByte(0x20);
TFT_LCD_WriteByte(0x1E);
TFT_LCD_WriteByte(0x09);
TFT_LCD_WriteByte(0x12);
TFT_LCD_WriteByte(0x0B);
TFT_LCD_WriteByte(0x50);
TFT_LCD_WriteByte(0XBA);
TFT_LCD_WriteByte(0x44);
TFT_LCD_WriteByte(0x09);
TFT_LCD_WriteByte(0x14);
TFT_LCD_WriteByte(0x05);
TFT_LCD_WriteByte(0x23);
TFT_LCD_WriteByte(0x21);
TFT_LCD_WriteByte(0x00);
TFT_LCD_WriteCommand(0XE1);
TFT_LCD_WriteByte(0x00);
TFT_LCD_WriteByte(0x19);
TFT_LCD_WriteByte(0x19);
TFT_LCD_WriteByte(0x00);
TFT_LCD_WriteByte(0x12);
TFT_LCD_WriteByte(0x07);
TFT_LCD_WriteByte(0x2D);
TFT_LCD_WriteByte(0x28);
TFT_LCD_WriteByte(0x3F);
TFT_LCD_WriteByte(0x02);
TFT_LCD_WriteByte(0x0A);
TFT_LCD_WriteByte(0x08);
TFT_LCD_WriteByte(0x25);
TFT_LCD_WriteByte(0x2D);
TFT_LCD_WriteByte(0x0F);
TFT_LCD_WriteCommand(0x29);
}
/*!
* @brief TFT LCD Init
*
* @param None
*
* @retval None
*
*/
void TFT_LCD_Init(void)
{
TFT_LCD_InitSPI1();
TFT_LCD_InitGPIO();
TFT_LCD_RES_L();
TFT_LCD_DelayMS(99);
TFT_LCD_RES_H();
TFT_LCD_DelayMS(99);
TFT_LCD_BLK_H();
TFT_LCD_DelayMS(99);
TFT_LCD_Configure();
TFT_LCD_Clear(0, 0, 240, 320, BACKCOLOR);
LCD_DisplayString(0, 10, "Geehy", FORECOLOR, BACKCOLOR, 32, 1);
LCD_DisplayString(0, 50, "APM32E103ZE EVAL V1.0", FORECOLOR, BACKCOLOR, 16, 1);
}
运行效果:
全部回复 0
暂无评论,快来抢沙发吧