基于STM32的多功能數字鐘
程序功能:基于STM32的多功能數字鐘
**************************************************************************************
1、時(shí)鐘的基準用STM32F103RCT6自帶的RTC實(shí)現。
2、這三個(gè)按鍵的功能分別為:"設置"、"+"、"-"。(WAKEUP KEY0 KEY1)
三個(gè)按鍵作為這三個(gè)功能:
鍵盤(pán)上的WAKEUP用作"設置",KEY0用作"+",KEY1用作"-"。
設定時(shí)間、日期、星期時(shí),按下設定鍵,
相應的參數會(huì )閃動(dòng),即一亮一滅,提示正的修改的數據,每按一下設置鍵,
設定的項目就會(huì )變化,順序為:
秒--分--時(shí)--星期--日--月--年。
順序設定完后,再按一下設定鍵,就退出設定狀態(tài),回到正顯示狀態(tài)。
3、用DS18B20顯示溫度。精確到小數點(diǎn)后一位。如:33.5℃。
4、增加用紅外遙控器的CH CH+ CH- 三個(gè)按鍵進(jìn)行時(shí)間設置,
功能等同于鍵盤(pán)上的(WAKEUP KEY0 KEY1)"設置"、"+"、"-"。
5、通過(guò)串行口設置時(shí)間日期。
如串行口發(fā)送t12:30:00 設置時(shí)間;
如串行口發(fā)送d2016-08-12 設置日期;
6、通過(guò)觸摸屏進(jìn)行時(shí)間日期設置
在觸摸屏上有 SET + -三個(gè)標志,當用觸筆去按時(shí),就會(huì )產(chǎn)生同開(kāi)發(fā)板上的
按鍵一樣的效果。
觸摸按下去和彈起來(lái)時(shí),按鍵的顏色會(huì )發(fā)生變化。
**************************************************************************************
硬件:LED0----GPIOA.8
KEY0----GPIOC.5
KEY1----GPIOA.15
KEY_WAKEUP----GPIOA.0
TIMER2定時(shí)器定時(shí)功能。
TIMER5定時(shí)器的定時(shí)和捕獲功能
TFT液晶屏2。8寸屏帶觸摸功能。
TOUCH觸摸屏。
DS18B20---PC4;
HS138紅外遙控---PA1;
串行口USART1;
RTC實(shí)時(shí)時(shí)鐘
開(kāi)發(fā)板:正點(diǎn)原子MINI開(kāi)發(fā)板
**************************************************************************************
編程目的:讓大賽學(xué)生盡快學(xué)會(huì )STM32的綜合編程。
**************************************************************************************
編程軟件:KEIL5
**************************************************************************************
常用的算法:
按鍵采用狀態(tài)機實(shí)現按鍵掃描。在定時(shí)器中對按鍵進(jìn)行處理。
紅外部分采用定時(shí)器捕獲功能實(shí)現。
時(shí)間用STM32自帶的RTC實(shí)現;
**************************************************************************************
時(shí)間:2016.8.12
作者:王廬山
工作室:湖北工業(yè)職業(yè)技術(shù)學(xué)院電子創(chuàng )新中心
***************************************************************************************/
#include "stm32f10x_conf.h"
#include "delay.h"
#include "sys.h"
#include "LED.h"
#include "key.h"
#include "timer2.h"
#include "24cxx.h"
#include "lcd.h"
#include "touch.h"
#include "usart.h"
#include "rtc.h"
#include "ds18b20.h"
#include "remote.h"
//時(shí)間結構體
typedef struct
{
vu8 s_hour;
vu8 s_min;
vu8 s_sec;
//公歷日月年周
vu16 s_year;
vu8 s_month;
vu8 s_date;
vu8 s_week;
}Timer;
Timer S_timer;
unsigned char flag_20ms=0x0,flag_500ms=0,flag_250ms=0,flag_1s=0;//定時(shí)標志
unsigned char flag_key0=0,flag_key1=0,flag_key2=0,flag_tiao=0,key_remot=0;
void Disp_Tiao_Shan(void);
void Load_Drow_Dialog(void);
int main(void)
{
unsigned char temp[12],sec_back=0xff,t=0,len=0;
short temp5;
delay_init();
NVIC_Configuration();
uart_init(9600);
Led_Init();
key_init();
Timer2_config(71,2000); //定時(shí)兩毫秒
DS18B20_Init();
Remote_Init();
AT24CXX_Init();
RTC_Init();
LCD_Init();
LCD_Clear(BLUE);
TP_Init();
POINT_COLOR=RED;
BACK_COLOR=BLUE;
LCD_ShowString(10,50,220,24,24,"--MULT FUNC CLOCK--");
LCD_ShowString(60,260,180,24,24,"SET + - ");
// POINT_COLOR=YELLOW ;
LCD_DrawRectangle(50,250,100,290);
LCD_DrawRectangle(110,250,160,290);
LCD_DrawRectangle(170,250,220,290);
while(1)
{
if(tp_dev.sta&TP_PRES_DOWN)//有觸摸按下?tīng)顟B(tài)。
{//按下時(shí),方框的顏色要發(fā)生變化,這樣看效果才明顯示,
//手松開(kāi)后,又要恢復原畫(huà)的顏色。
if((tp_dev.x[0]>50)&&(tp_dev.x[0]<100)&&(tp_dev.y[0]>250)&&(tp_dev.y[0]<290))
{LCD_Fill(51,251,99,289,YELLOW);LCD_ShowString(60,260,36,24,24,"SET");}
else if((tp_dev.x[0]>110)&&(tp_dev.x[0]<160)&&(tp_dev.y[0]>250)&&(tp_dev.y[0]<290))
{LCD_Fill(111,251,159,289,YELLOW);LCD_ShowString(120,260,36,24,24," + ");}
else if((tp_dev.x[0]>170)&&(tp_dev.x[0]<220)&&(tp_dev.y[0]>250)&&(tp_dev.y[0]<290))
{LCD_Fill(171,251,219,289,YELLOW);LCD_ShowString(180,260,36,24,24," - ");}
}
if((USART_RX_STA&0x8000))//收到了一幀串行口數據,進(jìn)行解析。
{
switch(USART_RX_BUF[0])
{
case t:{//time是調時(shí)間
S_timer.s_hour=(USART_RX_BUF[1]-0)*10+(USART_RX_BUF[2]-0);
S_timer.s_min=(USART_RX_BUF[3]-0)*10+(USART_RX_BUF[4]-0);
S_timer.s_sec=(USART_RX_BUF[5]-0)*10+(USART_RX_BUF[6]-0);
USART_RX_STA=0;
printf("set time:%s",USART_RX_BUF);
calendar.sec=S_timer.s_sec;
calendar.hour=S_timer.s_hour;
calendar.min=S_timer.s_min;
calendar.w_date=S_timer.s_date;
calendar.w_month=S_timer.s_month;
calendar.w_year=S_timer.s_year;
calendar.week=S_timer.s_week;
RTC_Set(calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);
break;
}
case d:{//date是調日期
S_timer.s_year =(USART_RX_BUF[1]-0)*1000+(USART_RX_BUF[2]-0)*100+(USART_RX_BUF[3]-0)*10+(USART_RX_BUF[4]-0);
S_timer.s_month=(USART_RX_BUF[5]-0)*10+(USART_RX_BUF[6]-0);
S_timer.s_date=(USART_RX_BUF[7]-0)*10+(USART_RX_BUF[8]-0);
USART_RX_STA=0;
printf("set date:%s",USART_RX_BUF);
calendar.sec=S_timer.s_sec;
calendar.hour=S_timer.s_hour;
calendar.min=S_timer.s_min;
calendar.w_date=S_timer.s_date;
calendar.w_month=S_timer.s_month;
calendar.w_year=S_timer.s_year;
calendar.week=S_timer.s_week;
RTC_Set(calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);
break;
}
default :break;
}
}
if(flag_tiao!=0)//用于調節時(shí)閃爍顯示
{
switch(flag_tiao)
{
case 1: {
if(flag_250ms==1)
{
LCD_ShowString(30+12*13,140,24,24,24," ");
break;
}
else goto kk2;
}
case 2: {
if(flag_250ms==1)
{
LCD_ShowString(30+12*10,140,24,24,24," ");
break;
}
else goto kk2;
}
case 3: {
if(flag_250ms==1)
{
LCD_ShowString(30+12*7,140,24,24,24," ");
break;
}
else goto kk2;
}
case 4: {
if(flag_250ms==1)
{
LCD_ShowString(30+12*15,100,24,24,24," ");
break;
}
else goto kk2;
}
case 5: {
if(flag_250ms==1)
{
LCD_ShowString(30+12*12,100,24,24,24," ");
break;
}
else goto kk2;
}
case 6: {
if(flag_250ms==1)
{
LCD_ShowString(30+12*10,100,24,24,24," ");
break;
}
else goto kk2;
}
case 7: {
if(flag_250ms==1)
{
LCD_ShowString(30+12*5,100,48,24,24," ");
break;
}
else goto kk2;
}
kk2:
{
sprintf(temp,"DATE:%d-%d-%d %d",calendar.w_year,calendar.w_month,calendar.w_date,calendar.week);
LCD_ShowString(30,100,210,24,24,temp);
sprintf(temp,"TIME: %d:%d:%d ",calendar.hour,calendar.min,calendar.sec);
LCD_ShowString(30,140,210,24,24,temp);
break;
}
default :break ;
}
}
else//正常顯示
{
if(sec_back!=calendar.sec)
{
sprintf(temp,"DATE:%d-%d-%d %d",calendar.w_year,calendar.w_month,calendar.w_date,calendar.week);
LCD_ShowString(30,100,210,24,24,temp);
sprintf(temp,"TIME: %d:%d:%d ",calendar.hour,calendar.min,calendar.sec);
LCD_ShowString(30,140,210,24,24,temp);
}
}
keyfunction();//按鍵掃描和功能解析(包括了開(kāi)發(fā)板上的按鍵、紅外遙控按鍵、觸摸按鍵)
if(flag_1s ==1)//每秒讀取一次溫度
{
flag_1s =0;
LCD_ShowString(30+5*12,180,210,24,24," ");
temp5=DS18B20_Get_Temp();
sprintf(temp,"TEMP:%d.%d",temp5/10,temp5%10);
LCD_ShowString(30,180,210,24,24,temp);
}
}
}
/*
函數功能:顯示畫(huà)圖框
*/
void Load_Drow_Dialog(void)
{
LCD_Clear(RED);//清屏
POINT_COLOR=BLUE;//設置字體為藍色
LCD_ShowString(lcddev.width-30,0,200,24,24,"RST");//顯示清屏區域
}
void Disp_Tiao_Shan(void)
{
unsigned char temp[12];
switch(flag_tiao)
{
case 1: {
if(flag_250ms==1)
{
LCD_ShowString(30+12*13,140,24,24,24," ");
break;
}
else goto kk2;
}
case 2: {
if(flag_250ms==1)
{
LCD_ShowString(30+12*10,140,24,24,24," ");
break;
}
else goto kk2;
}
case 3: {
if(flag_250ms==1)
{
LCD_ShowString(30+12*7,140,24,24,24," ");
break;
}
else goto kk2;
}
case 4: {
if(flag_250ms==1)
{
LCD_ShowString(30+12*15,100,24,24,24," ");
break;
}
else goto kk2;
}
case 5: {
if(flag_250ms==1)
{
LCD_ShowString(30+12*12,100,24,24,24," ");
break;
}
else goto kk2;
}
case 6: {
if(flag_250ms==1)
{
LCD_ShowString(30+12*10,100,24,24,24," ");
break;
}
else goto kk2;
}
case 7: {
if(flag_250ms==1)
{
LCD_ShowString(30+12*5,100,48,24,24," ");
break;
}
else goto kk2;
}
kk2:
{
sprintf(temp,"DATE:%d-%d-%d %d",calendar.w_year,calendar.w_month,calendar.w_date,calendar.week);
LCD_ShowString(30,100,210,24,24,temp);
sprintf(temp,"TIME: %d:%d:%d ",calendar.hour,calendar.min,calendar.sec);
LCD_ShowString(30,140,210,24,24,temp);
break;
}
default :break ;
}
}
#include "sys.h"
#include "delay.h"
#include "key.h"
#include "rtc.h"
#include "remote.h"
#include "touch.h"
#include "lcd.h"
typedef struct
{
vu8 s_hour;
vu8 s_min;
vu8 s_sec;
//公歷日月年周
vu16 s_year;
vu8 s_month;
vu8 s_date;
vu8 s_week;
}Timer;
extern unsigned char flag_20ms;
extern unsigned char flag_key0,flag_key1,flag_key2,flag_tiao;
extern Timer S_timer;
void key_init(void)
{
GPIO_InitTypeDef KEY_InitTypeDef;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOC,ENABLE);
KEY_InitTypeDef.GPIO_Pin=GPIO_Pin_0;
KEY_InitTypeDef.GPIO_Mode=GPIO_Mode_IPD;
KEY_InitTypeDef.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&KEY_InitTypeDef);
KEY_InitTypeDef.GPIO_Pin=GPIO_Pin_5;
KEY_InitTypeDef.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GPIOC,&KEY_InitTypeDef);
KEY_InitTypeDef.GPIO_Pin=GPIO_Pin_15;
KEY_InitTypeDef.GPIO_Mode=GPIO_Mode_IPU;
GPIO_Init(GPIOA,&KEY_InitTypeDef);
KEY0=1;
KEY1=1;
WK_UP=0;
}
/*
函數功能:按鍵掃描函數
輸入參數:無(wú)
輸出參數:返回鍵碼。無(wú)按鍵時(shí)返回0;
外部變量:
算法:采用軟件延時(shí)實(shí)現按鍵掃描。
*/
unsigned char KeyScan(void)
{
unsigned char keynum=0;
if((KEY0!=1)||(KEY1!=1)||(WK_UP!=0))
{
delay_ms(10);
if((KEY0!=1)||(KEY1!=1)||(WK_UP!=0))
{
if(KEY0!=1)
{
while(KEY0!=1);
keynum=1;return keynum;}
else if(KEY1!=1)
{while(KEY1!=1);
keynum=2;return keynum;}
else if(WK_UP!=0)
{while(WK_UP!=0);
keynum=3;return keynum;}
else
return 0;
}
else
return keynum;
}
else
return keynum;
}
/*
函數功能:按鍵掃描函數
輸入參數:無(wú)
輸出參數:返回鍵碼。無(wú)按鍵時(shí)返回0;
外部變量:flag_20ms
算法:采用狀態(tài)機實(shí)現按鍵掃描。
*/
unsigned char KeyScan2(void)
{
static unsigned char keynum=0,step1=0;
if(flag_20ms==0x01)
{
flag_20ms=0;
switch(step1)
{
case 0:{//狀態(tài)1:檢測是否有按鍵按下
if((KEY0!=1)||(KEY1!=1)||(WK_UP!=0))
step1=1;
else
step1=0;
return 0;
//break;
}
case 1:{//狀態(tài)2:檢測是否真的有按鍵按下
if((KEY0!=1)||(KEY1!=1)||(WK_UP!=0))
{
if(KEY0!=1)
{step1=2; keynum=1;}
else if(KEY1!=1)
{step1=2; keynum=2;}
else if(WK_UP!=0)
{step1=2; keynum=3;}
else
{step1=0; }
}
return 0;
//break;
}
case 2:{//狀態(tài)3:檢測按鍵是否彈起
if((KEY0!=1)||(KEY1!=1)||(WK_UP!=0))
{step1=2; return 0;}
else
{ step1=0;return keynum;}
//break;
}
default :return 0;
}
}
return 0;
}
/*
函數功能:按鍵功能解析函數
輸入參數:無(wú)
輸入函數:KeyScan2();
輸出參數:無(wú)
外部變量:flag_key0,flag_key1
*/
void keyfunction(void)
{
unsigned char temp;
temp=(KeyScan2())|(Remote_Scan());
if(TP_Scan(0))//當觸摸按鍵按下并松開(kāi)后才返回1,否則返回0;
{//按下時(shí),方框的顏色要發(fā)生變化,這樣看效果才明顯示,
//手松開(kāi)后,又要恢復原畫(huà)的顏色。
if((tp_dev.x[0]>50)&&(tp_dev.x[0]<100)&&(tp_dev.y[0]>250)&&(tp_dev.y[0]<290))
{ temp =3;
{LCD_Fill(51,251,99,289,BLUE);LCD_ShowString(60,260,180,24,24,"SET");}
}
else if((tp_dev.x[0]>110)&&(tp_dev.x[0]<160)&&(tp_dev.y[0]>250)&&(tp_dev.y[0]<290))
{ temp=1;
{LCD_Fill(111,251,159,289,BLUE);LCD_ShowString(120,260,180,24,24," + ");}
}
else if((tp_dev.x[0]>170)&&(tp_dev.x[0]<220)&&(tp_dev.y[0]>250)&&(tp_dev.y[0]<290))
{temp=2;
{LCD_Fill(171,251,219,289,BLUE);LCD_ShowString(180,260,180,24,24," - ");}
}
}
if(temp>0)
{ TIM_Cmd(TIM2,ENABLE);
switch(temp)
{
case 1:{
flag_key0=1;
if(flag_tiao>0)
{
S_timer.s_sec =calendar.sec;
S_timer.s_hour=calendar.hour;
S_timer.s_min =calendar.min;
S_timer.s_date=calendar.w_date;
S_timer.s_month =calendar.w_month;
S_timer.s_year=calendar.w_year;
S_timer.s_week =calendar.week;
switch(flag_tiao)
{
case 1: {
if((S_timer.s_sec)<60);
else
S_timer.s_sec=0;
goto kk1;
}
case 2: {
if(S_timer.s_min++<60);
else
S_timer.s_min=0; goto kk1;
}
case 3: {
if(S_timer.s_hour ++<60);
else
S_timer.s_hour=0; goto kk1;
}
case 4: {
if(S_timer.s_week++<7);
else
S_timer.s_week =1; goto kk1;
}
case 5: {
if(S_timer.s_date++<30);
else
S_timer.s_date=1; goto kk1;
}
case 6: {
if(S_timer.s_month++<12);
else
S_timer.s_month =1; goto kk1;
}
case 7: {
if(S_timer.s_year++<2099);
else
S_timer.s_year =1970; goto kk1;
}
default :break ;
}
}
break;
}
case 2:{
flag_key1=1;
if(flag_tiao>0)
{
S_timer.s_sec =calendar.sec;
S_timer.s_hour=calendar.hour;
S_timer.s_min =calendar.min;
S_timer.s_date=calendar.w_date;
S_timer.s_month =calendar.w_month;
S_timer.s_year=calendar.w_year;
S_timer.s_week =calendar.week;
switch(flag_tiao)
{
case 1: {
if((S_timer.s_sec)-->0);
else
S_timer.s_sec=60; goto kk1;
//break ;
}
case 2: {
if(S_timer.s_min-->0);
else
S_timer.s_min=60; goto kk1;
//break ;
}
case 3: {
if(S_timer.s_hour-->0);
else
S_timer.s_hour=24; goto kk1;
//break ;
}
case 4: {
if(S_timer.s_week-->0);
else
S_timer.s_week =7; goto kk1;
//break ;
}
case 5: {
if(S_timer.s_date-->0);
else
S_timer.s_date=31; goto kk1;
//break ;
}
case 6: {
if(S_timer.s_month-->0);
else
S_timer.s_month =12; goto kk1;
//break ;
}
case 7: {
if(S_timer.s_year-->1970);
else
S_timer.s_year =1970; goto kk1;
//break ;
}
kk1:
calendar.sec=S_timer.s_sec;
calendar.hour=S_timer.s_hour;
calendar.min=S_timer.s_min;
calendar.w_date=S_timer.s_date;
calendar.w_month=S_timer.s_month;
calendar.w_year=S_timer.s_year;
calendar.week=S_timer.s_week;
RTC_Set(calendar.w_year,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);
break;
default :break ;
}
}
break;
}
case 3:{
flag_key2=1;
if(flag_tiao++<7);
else
flag_tiao=0;
break;
}
default :break;
}
TIM_Cmd(TIM2,ENABLE);
}
}
評論