本设计将要实现一个以单片机为核心的屏显菜单系统设计。以单片机STM32单片机作为主控芯片,通过按键选择不同的选项,显示不同的界面功能。在界面部分主要显示菜单栏、时间、图片、音乐等功能。
掌握与研究的内容有以下几个方面:
(1)研究屏幕SPI通信方式。
(2)研究单总线通信协议。
(3)研究菜单步进系统设计。
(4)研究使用Keil编程环境编写单片机代码。
屏显菜单系统硬件如图1所示。硬件部分主要包括单片机最小系统、电源、按键模块、时钟模块、显示模块、语音模块。单片机检测不同按键按下,进行屏幕菜单选项选择,按下确定键后实现选项功能,可以选择时间显示,图片显示等功能。
基于STM32的屏显菜单系统
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "timer.h"
#include "ADC.h"
#include "usart3.h"
#include "key.h"
#include "rtc.h"
#include "oled.h"
#include "stmflash.h"
#include "math.h"
#include "dht11.h"
#include "bmp280.h"
#include "exti.h"
#include "DS1302.h"
#include "lcd_init.h"
#include "lcd.h"
#include "pic.h"
u8 count;
u8 Play = 1;
u8 display_contrl=0;
u8 curtain_flag=0;
u8 last_curtain_flag=0;
u8 PageIndex = 1;//页面步进值
u8 Page1OptionIndex = 1;//选项步进值 1:时间 2:图片 3:音乐
u8 Page2OptionIndex = 1;
void SendData11( u8 addr )//发送函数。
{
u8 i;
SPEEKSDA = 1;/*开始拉高 */
delay_us ( 1000 );
SPEEKSDA = 0;/*开始引导码*/
delay_us ( 2000 );/*此处延时最少要大于 2ms,此参数延时为 310ms */
for ( i = 0; i < 8; i++ ) /*总共 8 位数据 */
{
SPEEKSDA = 1;
if ( addr & 0x01 ) /*3:1 表示数据位 1,每个位用两个脉冲表示 */
{
delay_us ( 1200 );
SPEEKSDA = 0;
delay_us ( 400 );
}
else /*1:3 表示数据位 0 ,每个位用两个脉冲表示 */
{
delay_us ( 400 );
SPEEKSDA = 0;
delay_us ( 1200 );
}
addr >>= 1;
}
}
//设置音量:vol(0-30)
void ONE_LINE_VOL(u8 vol)
{
if(vol>30)vol=30;
SendData11(vol/10);
SendData11(vol%10);
SendData11(0x0C);
}
void ONE_LINE_PLAY_SONG(u8 song)
{
u8 i;
u8 tmp[3];
tmp[0]=song/100;song%=100;
tmp[1]=song/10;
tmp[2]=song%10;
SendData11(0x0a);
for(i=0;i<3;i++)
{
if(tmp[i]!=0)
{
SendData11(tmp[i]);
}
}
SendData11(0x0b);
}
//单线串口:播放
void ONE_LINE_PLAY()
{
SendData11(0x11);
}
//时间显示
void Time_Display()
{
u8 x=40;
u8 y=50;
LCD_ShowChinese(64,16,"时间",BLACK,LGRAY,16,0);
LCD_ShowIntNum(x,y,TIME[1]/16,1,RED,LGRAY,16);//年
LCD_ShowIntNum(x+8,y,DS1302_Time[3],1,RED,LGRAY,16);
LCD_ShowString(x+16,y,"-",RED,LGRAY,16,0);
LCD_ShowIntNum(x+24,y,DS1302_Time[4],1,RED,LGRAY,16);//月
LCD_ShowIntNum(x+32,y,DS1302_Time[5],1,RED,LGRAY,16);
LCD_ShowString(x+40,y,"-",RED,LGRAY,16,0);
LCD_ShowIntNum(x+48,y,DS1302_Time[6],1,RED,LGRAY,16);//日
LCD_ShowIntNum(x+56,y,DS1302_Time[7],1,RED,LGRAY,16);
LCD_ShowIntNum(x,y+16,DS1302_Time[8],1,RED,LGRAY,16);//时
LCD_ShowIntNum(x+8,y+16,DS1302_Time[9],1,RED,LGRAY,16);
LCD_ShowString(x+16,y+16,":",RED,LGRAY,16,0);
LCD_ShowIntNum(x+24,y+16,DS1302_Time[10],1,RED,LGRAY,16);//分
LCD_ShowIntNum(x+32,y+16,DS1302_Time[11],1,RED,LGRAY,16);
LCD_ShowString(x+40,y+16,":",RED,LGRAY,16,0);
LCD_ShowIntNum(x+48,y+16,DS1302_Time[12],1,RED,LGRAY,16);//秒
LCD_ShowIntNum(x+56,y+16,DS1302_Time[13],1,RED,LGRAY,16);
}
//图片选项显示
void PictureDisplay()
{
if((Page1OptionIndex==2)&&(PageIndex==2))
{
LCD_ShowChinese(64,16,"图片",BLACK,LGRAY,16,0);
if(Page2OptionIndex==1)
{
LCD_ShowString(40+16,40,"1)",RED,LGRAY,16,0);
LCD_ShowChinese(56+16,40,"图片",RED,YELLOW,16,0);
LCD_ShowString(88+16,40,"1",RED,YELLOW,16,0);
}
else
{
LCD_ShowString(40+16,40,"1)",RED,LGRAY,16,0);
LCD_ShowChinese(56+16,40,"图片",RED,LGRAY,16,0);
LCD_ShowString(88+16,40,"1",RED,LGRAY,16,0);
}
if(Page2OptionIndex==2)
{
LCD_ShowString(40+16,56,"2)",RED,LGRAY,16,0);
LCD_ShowChinese(56+16,56,"图片",RED,YELLOW,16,0);
LCD_ShowString(88+16,56,"2",RED,YELLOW,16,0);
}
else
{
LCD_ShowString(40+16,56,"2)",RED,LGRAY,16,0);
LCD_ShowChinese(56+16,56,"图片",RED,LGRAY,16,0);
LCD_ShowString(88+16,56,"2",RED,LGRAY,16,0);
}
}
if(PageIndex==3)
{
if(Page2OptionIndex==1)
{
LCD_ShowPicture(30,0,100,99,Image_xaau);
}
if(Page2OptionIndex==2)
{
LCD_ShowPicture(65,80,40,40,gImage_1);
}
}
}
//音乐选项显示
void MusicDisplay()
{
if((Page1OptionIndex==3)&&(PageIndex==2))
{
LCD_ShowChinese(64,16,"音乐",BLACK,LGRAY,16,0);
if(Page2OptionIndex==1)
{
LCD_ShowString(40+16,40,"1)",RED,LGRAY,16,0);
LCD_ShowChinese(56+16,40,"音乐",RED,YELLOW,16,0);
LCD_ShowString(88+16,40,"1",RED,YELLOW,16,0);
}
else
{
LCD_ShowString(40+16,40,"1)",RED,LGRAY,16,0);
LCD_ShowChinese(56+16,40,"音乐",RED,LGRAY,16,0);
LCD_ShowString(88+16,40,"1",RED,LGRAY,16,0);
}
if(Page2OptionIndex==2)
{
LCD_ShowString(40+16,56,"2)",RED,LGRAY,16,0);
LCD_ShowChinese(56+16,56,"音乐",RED,YELLOW,16,0);
LCD_ShowString(88+16,56,"2",RED,YELLOW,16,0);
}
else
{
LCD_ShowString(40+16,56,"2)",RED,LGRAY,16,0);
LCD_ShowChinese(56+16,56,"音乐",RED,LGRAY,16,0);
LCD_ShowString(88+16,56,"2",RED,LGRAY,16,0);
}
if(Page2OptionIndex==3)
{
LCD_ShowString(40+16,72,"3)",RED,LGRAY,16,0);
LCD_ShowChinese(56+16,72,"音乐",RED,YELLOW,16,0);
LCD_ShowString(88+16,72,"3",RED,YELLOW,16,0);}
else
{
LCD_ShowString(40+16,72,"3)",RED,LGRAY,16,0);
LCD_ShowChinese(56+16,72,"音乐",RED,LGRAY,16,0);
LCD_ShowString(88+16,72,"3",RED,LGRAY,16,0);
}
}
if(PageIndex==3)
{
if(Page2OptionIndex==1)
{
LCD_ShowChinese(50,66,"播放音乐",RED,LGRAY,16,0);
LCD_ShowString(114,66,"1",RED,LGRAY,16,0);
if(Play==1)
{
Play=0;
MUSIC1=0;delay_ms(1000);MUSIC1=1;
}
}
if(Page2OptionIndex==2)
{
LCD_ShowChinese(50,66,"播放音乐",RED,LGRAY,16,0);
LCD_ShowString(114,66,"2",RED,LGRAY,16,0);
if(Play==1)
{
Play=0;
MUSIC3=0;delay_ms(1000);MUSIC3=1;
}
}
if(Page2OptionIndex==3)
{
LCD_ShowChinese(50,66,"播放音乐",RED,LGRAY,16,0);
LCD_ShowString(114,66,"3",RED,LGRAY,16,0);
if(Play==1)
{
Play=0;
MUSIC2=0;delay_ms(1000);MUSIC2=1;
}
}
}
}
//按键扫描
void Key_Scan()
{
if(KEY0==0)//选项步进加
{
delay_ms(20);
if(KEY0==0)
{
if(PageIndex==1)//界面一
{
if(++Page1OptionIndex>=4) Page1OptionIndex=1;
}
if(PageIndex==2)//界面二
{
if(Page1OptionIndex==2)//由图片选项进入
{
if(++Page2OptionIndex>=3) Page2OptionIndex=1;//图片只有2张
}
if(Page1OptionIndex==3)//由音乐选项进入
{
if(++Page2OptionIndex>=4) Page2OptionIndex=1;//音乐只有3首
}
}
}
while(KEY0==0);
}
if(KEY1==0)//选项步进减
{
delay_ms(20);
if(KEY1==0)
{
if(PageIndex==1)//界面一
{
if((Page1OptionIndex--)<=1) Page1OptionIndex=3;
}
if(PageIndex==2)//界面二
{
if(Page1OptionIndex==2)//由图片选项进入
{
if((Page2OptionIndex--)<=1) Page2OptionIndex=2;
}
if(Page1OptionIndex==3)//由音乐选项进入
{
if((Page2OptionIndex--)<=1) Page2OptionIndex=3;
}
}
}
while(KEY1==0);
}
if(KEY2==0)//确定
{
delay_ms(20);
if(KEY2==0)
{
LCD_Fill(0,0,LCD_W,LCD_H,LGRAY);
if(++PageIndex>=3) PageIndex=3;
if((PageIndex==3)&&(Page1OptionIndex==3))
{
Play=1;
}
}
while(KEY2==0);
}
if(KEY3==0)//返回
{
delay_ms(20);
if(KEY3==0)
{
LCD_Fill(0,0,LCD_W,LCD_H,LGRAY);
if((PageIndex--)<=1) PageIndex=1;
}
while(KEY3==0);
}
}
// 界面显示
void DisplayScreen()
{
if(PageIndex==1)//界面一
{
LCD_ShowChinese(64,16,"菜单",BLACK,LGRAY,16,0);
// 选项1
if(Page1OptionIndex==1)
{
LCD_ShowString(56,40,"1:",RED,YELLOW,16,0);
LCD_ShowChinese(72,40,"时间",RED,YELLOW,16,0);
}
else
{
LCD_ShowString(56,40,"1:",RED,LGRAY,16,0);
LCD_ShowChinese(72,40,"时间",RED,LGRAY,16,0);
}
// 选项2
if(Page1OptionIndex==2)
{
LCD_ShowString(56,56,"2:",RED,YELLOW,16,0);
LCD_ShowChinese(72,56,"图片",RED,YELLOW,16,0);
}
else
{
LCD_ShowString(56,56,"2:",RED,LGRAY,16,0);
LCD_ShowChinese(72,56,"图片",RED,LGRAY,16,0);
}
// 选项3
if(Page1OptionIndex==3)
{
LCD_ShowString(56,72,"3:",RED,YELLOW,16,0);
LCD_ShowChinese(72,72,"音乐",RED,YELLOW,16,0);
}
else
{
LCD_ShowString(56,72,"3:",RED,LGRAY,16,0);
LCD_ShowChinese(72,72,"音乐",RED,LGRAY,16,0);
}
}
if((PageIndex==2)||(PageIndex==3))//界面二和三
{
if(Page1OptionIndex==1)//时间显示
{
Time_Display();
}
if(Page1OptionIndex==2)//图片显示
{
PictureDisplay();
}
if(Page1OptionIndex==3)//音乐显示
{
MusicDisplay();
}
}
}
int main(void)
{
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
KEY_Init(); //按键引脚初始化
Ds1302_gpio_init(); //端口初始化
DS1302_Init();
LCD_Init();//LCD初始化
LCD_Fill(0,0,LCD_W,LCD_H,LGRAY);
LCD_ShowChinese(0,16,"欢迎进入屏显菜单系统",RED,LGRAY,16,0);
delay_ms(5000);
LCD_Fill(0,0,LCD_W,LCD_H,LGRAY);
ONE_LINE_VOL(10);
delay_ms(30); //一条指令发送完毕之后,需要间隔20ms在发送下一条指令
ONE_LINE_PLAY_SONG(1);
ONE_LINE_PLAY();
MUSIC1=1;
MUSIC2=1;
MUSIC3=1;
while(1)
{
Key_Scan();
DS1302_ReadTime();
DisplayScreen();
}
}