【国民技术N32G430】05 页面初显,系统构成
[复制链接]
05 页面初显,系统构成
为了实现测试有序进行,并能有效显示,准备先进行测试之前进行页面显示,这样可以将所有的测试分区进行,并最终可以构成一个完成展示。
这里面其实包括三部分部分:其一是显示单元的驱动;第二是测试内容的区分;第三就是操作输入,目前开发板板载的用户按键一共有4个,作为页面串联起来的实时工具。
显示单元的驱动:本次测试选用的是1.54寸tft作为显示元件,主要参数是240*240分辨率,主控是7789,通过SPI/8080进行通信,在本次测试使用SPI进行通信,同时驱动部分也是对SPI功能的试用。这里面分别使用IO口模拟及硬件SPI来驱动。
IO模拟初始化:
#define SPI1_CS_OUT0 GPIO_Pins_Reset(SPI1_MASTER_GPIO,SPI1_MASTER_NSS_PIN)
#define SPI1_CS_OUT1 GPIO_Pins_Set(SPI1_MASTER_GPIO,SPI1_MASTER_NSS_PIN)
#define SPI1_MOSI_OUT0 GPIO_Pins_Reset(SPI1_MASTER_GPIO,SPI1_MASTER_MOSI_PIN)
#define SPI1_MOSI_OUT1 GPIO_Pins_Set(SPI1_MASTER_GPIO,SPI1_MASTER_MOSI_PIN)
#define SPI1_CLK_OUT0 GPIO_Pins_Reset(SPI1_MASTER_GPIO,SPI1_MASTER_CLK_PIN)
#define SPI1_CLK_OUT1 GPIO_Pins_Set(SPI1_MASTER_GPIO,SPI1_MASTER_CLK_PIN)
//******************************************************************************
//* 函数名称 : SPI1_IOInit()
//* 函数描述 : SPI对应的IO口初始化
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void SPI1_IOInit(void)
{
GPIO_InitType GPIO_InitStructure;
RCC_AHB_Peripheral_Clock_Enable(SPI1_MASTER_PERIPH_GPIO);
RCC_AHB_Peripheral_Clock_Enable(TFT_BL_PERIPH_GPIO);
GPIO_Structure_Initialize(&GPIO_InitStructure);
GPIO_InitStructure.Pin = TFT_RS_PIN|SPI1_MASTER_NSS_PIN|TFT_RESET_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
GPIO_Peripheral_Initialize(SPI1_MASTER_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.Pin = SPI1_MASTER_CLK_PIN|SPI1_MASTER_MOSI_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
GPIO_InitStructure.GPIO_Pull = GPIO_NO_PULL;
GPIO_Peripheral_Initialize(SPI1_MASTER_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.Pin = TFT_BL_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
GPIO_InitStructure.GPIO_Pull = GPIO_PULL_DOWN;
GPIO_Peripheral_Initialize(TFT_BL_GPIO, &GPIO_InitStructure);
SPI1_CLK_OUT0;
SPI1_MOSI_OUT0;
SPI1_CS_OUT1;
TFT_RS_reset;
TFT_RESET_reset;
TFT_BL_RESET;
}
//******************************************************************************
//* 函数名称 : SPI1_Send_Data(uint8_t Data)
//* 函数描述 : SPI1发送8位数据
//* 输入参数 : Data
//* 参数描述 : 具体的指令代码
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void SPI1_Send_Data(uint8_t Data)
{
SPI1_CS_OUT0; //选中该从机
delay_us(2);
uint8_t i;
for (i = 0;i < 8;i++)
{
if ((Data << i) & 0x80)
{
SPI1_MOSI_OUT1;
SPI1_CLK_OUT0;//rising edge
SPI1_CLK_OUT1;
}
else
{
SPI1_MOSI_OUT0;
SPI1_CLK_OUT0;//rising edge
SPI1_CLK_OUT1;
}
}
SPI1_CS_OUT1;
}
SPI初始化:
//******************************************************************************
//* 函数名称 : SPI1_IOInit()
//* 函数描述 : SPI1对应的IO口初始化
//* 输入参数 :
//* 参数描述 :
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void SPI1_IOInit(void)
{
GPIO_InitType GPIO_InitStructure;
SPI_InitType SPI_InitStructure;
RCC_AHB_Peripheral_Clock_Enable(SPI1_MASTER_PERIPH_GPIO);
RCC_AHB_Peripheral_Clock_Enable(TFT_BL_PERIPH_GPIO);
RCC_APB2_Peripheral_Clock_Enable(SPI1_MASTER_PERIPH);
RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
GPIO_Structure_Initialize(&GPIO_InitStructure);
GPIO_InitStructure.Pin = TFT_RS_PIN|SPI1_MASTER_NSS_PIN|TFT_RESET_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
GPIO_Peripheral_Initialize(SPI1_MASTER_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.Pin = TFT_BL_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUT_PP;
GPIO_InitStructure.GPIO_Pull = GPIO_PULL_DOWN;
GPIO_Peripheral_Initialize(TFT_BL_GPIO, &GPIO_InitStructure);
SPI1_CS_OUT1;
TFT_RS_reset;
TFT_RESET_reset;
TFT_BL_RESET;
GPIO_InitStructure.Pin = SPI1_MASTER_MOSI_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.GPIO_Slew_Rate = GPIO_SLEW_RATE_FAST;
GPIO_InitStructure.GPIO_Alternate = SPI1_MOSI_GPIO_ALTERNATE;
GPIO_Peripheral_Initialize(SPI1_MASTER_GPIO, &GPIO_InitStructure);
GPIO_InitStructure.Pin = SPI1_MASTER_CLK_PIN;
GPIO_InitStructure.GPIO_Alternate = SPI1_CLK_GPIO_ALTERNATE;
GPIO_Peripheral_Initialize(SPI1_MASTER_GPIO, &GPIO_InitStructure);
SPI_I2S_Reset(SPI1_MASTER);
/* SPI1_MASTER configuration ------------------------------------------------------*/
SPI_Initializes_Structure(&SPI_InitStructure);
SPI_InitStructure.DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX;
SPI_InitStructure.SpiMode = SPI_MODE_MASTER;
SPI_InitStructure.DataLen = SPI_DATA_SIZE_8BITS;
SPI_InitStructure.CLKPOL = SPI_CLKPOL_HIGH;
SPI_InitStructure.CLKPHA = SPI_CLKPHA_SECOND_EDGE;
SPI_InitStructure.NSS = SPI_NSS_SOFT;
/* It is recommended that the SPI master mode of the C version chips should not exceed 18MHz */
SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_8;
SPI_InitStructure.FirstBit = SPI_FB_MSB;
SPI_InitStructure.CRCPoly = 7;
SPI_Initializes(SPI1_MASTER, &SPI_InitStructure);
SPI_Set_Nss_Level(SPI1, SPI_NSS_HIGH);
// SPI_CRC_Enable(SPI1_MASTER);
SPI_ON(SPI1_MASTER);
}
//******************************************************************************
//* 函数名称 : SPI_Send_Data(uint8_t Data)
//* 函数描述 : SPI发送8位数据
//* 输入参数 : Data
//* 参数描述 : 具体的指令代码
//* 输出参数 : 无
//* 返回值 : 无
//******************************************************************************
void SPI1_Send_Data(uint8_t Data)
{
SPI1_CS_OUT0; //选中该从机
delay_us(1);
SPI_I2S_Data_Transmit(SPI1_MASTER, Data);
while(SPI_I2S_Flag_Status_Get(SPI1_MASTER, SPI_I2S_FLAG_TE) == RESET);
delay_us(1);
SPI1_CS_OUT1;
}
接下来就是界面设置的介绍,在进行TFT初始化后,tft一般会是一个花色(如果初始化失败,屏是全视角的屏会无色,而普通tft一般会是白屏的),这时候需要写一个单色赋予一个初始底色,然后再打开背光。
第一个界面就是欢迎界面,主要是展示一下本次测评的一些信息,这里选择了活动论坛的图标,开发板图标以及测评活动信息。这里面取图使用的16位全彩模式,注意扫描方式要与屏配置的方向要一致。
下图为取图小程序:
这里需要注意一下,全彩需要的存储空间是比较大的,例如上图的90*25分辨率的就需要4.5K字节的数据,对于单片机资源来说,尽量减少全彩图像或者减小分辨率。
欢迎界面作为展示界面没有选项菜单,通过任何按键操作进行入菜单界面,这才是我们真正进行功能划分的地方。不过在此之前我们要先实现一下按键功能。
按键功能实际就是对按键状态的识别,这里有几种方法实现按键功能的采集,基于本开发板,如下图:
这4个按键都能获取状态,其中WAKEP与其他是三个不同,按下后状态相反,不过根据按键在开发板上的位置分别定义:返回键、上键、下键、确定键(S6、S1、S2、S3)。
方法一可以使用扫描的方式进行,加上延时防抖,就可以获取了;
方法二是通过外部中断方式进行,已知芯片所有的GPIO引脚都可以实现外部中断,在加上定时器防抖可以实现按键状态识别;
经过对比选择通过方法二实现,这时候就设计外部中断和定时器的体验了。
外部中断初始化:
//******************************************************************************
// 函数名称 : port_EXIT_init
// 函数描述 : 单片机的外部中断初始化
// 输入参数 :
// 参数描述 :
// 输出参数 : 无
// 返回值 : 无
//******************************************************************************
void port_EXIT_init(void)
{
GPIO_InitType GPIO_InitStructure;
EXTI_InitType EXTI_InitStructure;
NVIC_InitType NVIC_InitStructure;
RCC_AHB_Peripheral_Clock_Enable(RCC_AHB_PERIPH_GPIOA);
RCC_APB2_Peripheral_Clock_Enable(RCC_APB2_PERIPH_AFIO);
GPIO_Structure_Initialize(&GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6;
GPIO_InitStructure.GPIO_Pull = GPIO_PULL_UP;
GPIO_Peripheral_Initialize(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_0;
GPIO_InitStructure.GPIO_Pull = GPIO_NO_PULL;
GPIO_Peripheral_Initialize(GPIOA, &GPIO_InitStructure);
/* Configure key EXTI Line to key input Pin */
GPIO_EXTI_Line_Set(EXTI_LINE_SOURCE0, AFIO_EXTI_PA0);
GPIO_EXTI_Line_Set(EXTI_LINE_SOURCE4, AFIO_EXTI_PA4);
GPIO_EXTI_Line_Set(EXTI_LINE_SOURCE5, AFIO_EXTI_PA5);
GPIO_EXTI_Line_Set(EXTI_LINE_SOURCE6, AFIO_EXTI_PA6);
/* Configure key EXTI line */
EXTI_InitStructure.EXTI_Line = EXTI_LINE4|EXTI_LINE5|EXTI_LINE6;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Peripheral_Initializes(&EXTI_InitStructure);
EXTI_InitStructure.EXTI_Line = EXTI_LINE0;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_Peripheral_Initializes(&EXTI_InitStructure);
/* Set key input interrupt priority */
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PER_PRIORITY_0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_SUB_PRIORITY_1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Initializes(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_Initializes(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI4_IRQn;
NVIC_Initializes(&NVIC_InitStructure);
}
定时器初始化:
void Tmr6Base_init(uint16_t Prescaler)
{
TIM_TimeBaseInitType TIM_TimeBaseStructure;
NVIC_InitType NVIC_InitStructure;
RCC_APB1_Peripheral_Clock_Enable(RCC_APB1_PERIPH_TIM6);
/* tmr6 configuration */
/* time base configuration */
/* 64000000/64000/1000 = 1hz */
TIM_Base_Struct_Initialize(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.Period = 63999;
TIM_TimeBaseStructure.Prescaler = Prescaler-1;
TIM_TimeBaseStructure.ClkDiv = 0;
TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_UP;
TIM_Base_Initialize(TIM6, &TIM_TimeBaseStructure);
NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Initializes(&NVIC_InitStructure);
TIM_Base_Reload_Mode_Set(TIM6, TIM_PSC_RELOAD_MODE_IMMEDIATE);
TIM_Interrupt_Enable(TIM6, TIM_INT_UPDATE);
TIM_On(TIM6);
}
这里的定时器选取了TIM6,作为一个只需要定时的功能,选择一个普通定时器就可以了,这里提个醒,不同定时器用的函数是不一样的。
定义按键结构体:
typedef struct
{
uint8_t Confirm; //用于界面状态确认
uint8_t Return; //用于界面返回
uint8_t Add; //用于加
uint8_t Less; //用于减
uint8_t SelectCnt; //用于界面状态选择计数
uint8_t Cumsumflag; //累加标志,1加;2减
}KEY_State;
通过在定时器中循环检测实现按键的长按短按等操作,以OK键为例,如下:
if(key_Ok.EXIT_flag == 1)//防抖判断
{
key_Ok.EXIT_Data++;
if(key_Ok.EXIT_Data == 2 && READ_KEY_Ok == 0)
{
key_Ok.Press_flag = 1;
key_Ok.Press_Data = 0;
key_Ok.ShortPress_flag = 0;
key_Ok.LongPress_flag = 0;
key_Ok.EXIT_flag = 0;
}
else if(key_Ok.EXIT_Data > 2)
{
key_Ok.EXIT_flag = 0;
key_Ok.EXIT_Data = 0;
}
}
if(key_Ok.Press_flag == 1)
{
key_Ok.Press_Data++;
if(READ_KEY_Ok == 1)
{
if(key_Ok.Press_Data >= 100)
{
key_Ok.LongPress_flag = 1;
}
else if(key_Ok.Press_Data < 100)
{
key_Ok.ShortPress_flag = 1;
}
key_Ok.Press_flag = 0;
}
else
{
if(key_Ok.Press_Data >= 120)
{
key_Ok.LongPress_flag = 1;
key_Ok.Press_flag = 0;
}
}
}
这时候就可以通过对不同按键的反应来实现界面的切换,菜单的选择。接下来就是菜单界面了,这里面主要供我们选择不同的菜单然后进行各分部的体验,例如LED体验、RTC展示,传感器展示、串口等等。
|